Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate Mapping Parent/Child Relationship

I have a database table which contains a simple self parent/child relationship (categories) like this:

+------------+----------+--------------------+
| categoryid | parentid | category_name      |
+------------+----------+--------------------+
|          1 |        0 | Java               |
|          2 |        0 | SKM                |
|          3 |        0 | Neuigkeiten        |
|          4 |        0 | Neue Versionen     |
|          5 |        0 | PlugIn             |
..
|          9 |        2 | Subversion         |
|         10 |        2 | DVCS               |
|         11 |        2 | SVK                |
|         12 |        2 | Bazaar             |
|         13 |        2 | CVS                |
|         14 |        2 | SpectrumSCM        |
|         15 |        2 | Plastic SCM        |
|         16 |        2 | Monotone           |
|         17 |        2 | Mercurial          |
|         18 |        2 | ClearCase          |

Now I've created a Hibernate mapping class CategoryBO with the above Table like this (AbstractBaseBO contains only two public methods getId() and setId()..):

@Entity
@Table(name = TabellenNamen.CATEGORY)
public class CategoryBO extends AbstractBaseBO {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "categoryid", nullable = false, unique = true)
    private Long Id;

    @Column(name = "category_name")
    private String categoryName;

    @ManyToOne( cascade = { CascadeType.ALL } )
    @JoinColumn(name = "parentid")
    private CategoryBO parent;

    @OneToMany(mappedBy = "parent")
    private ArrayList<CategoryBO> subCategories = new ArrayList<CetegoryBO>();


    ...getter/setters

}

But if I try to get the list of category entries from the database i get the following error message:

2013-05-30 16:58:57,329|DEBUG|main|hibernate.cfg.AnnotationBinder||Processing annotations of com.soebes.casestudy.bo.CategoryBO.subCategories
2013-05-30 16:58:57,329|DEBUG|main|hibernate.cfg.Ejb3Column||Binding column null. Unique false. Nullable true.
2013-05-30 16:58:57,329|DEBUG|main|hibernate.cfg.Ejb3Column||Binding column subCategories. Unique false. Nullable true.
2013-05-30 16:58:57,331|DEBUG|main|hibernate.cfg.Ejb3Column||Binding column null. Unique false. Nullable true.
FAILED: testGet
org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: com.soebes.casestudy.bo.CategoryBO.subCategories
    at org.hibernate.cfg.annotations.CollectionBinder.getCollectionBinder(CollectionBinder.java:266)
    at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1448)
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:754)
    at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:546)
    at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:291)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1319)
    at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867)
    at com.soebes.casestudy.hibernate.HibernateUtil.getSession(HibernateUtil.java:36)
    at com.soebes.casestudy.hibernate.HibernateUtil.beginTransaction(HibernateUtil.java:48)

which i don't understand.

So where is my misunderstanding or my problem (I assume something really stupid)...

Update:

After I have updated the code accordingly to the suggestion in the answer of Jimmy T like this:

@OneToMany(mappedBy = "parent")
private List<CategoryBO> subCategories;

I got the following error messages:

2013-05-30 19:08:33,363|DEBUG|main|hibernate.loader.Loader||done entity load
2013-05-30 19:08:33,364|INFO|main|event.def.DefaultLoadEventListener||Error performing load command
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.soebes.casestudy.bo.CategoryBO#0]
    at org.hibernate.impl.SessionFactoryImpl$2.handleEntityNotFound(SessionFactoryImpl.java:449)
    at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:233)
    at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:285)
    at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
    at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
    at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:1028)
    at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:623)
    at org.hibernate.type.EntityType.resolve(EntityType.java:431)
    at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:140)
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:898)
    at org.hibernate.loader.Loader.doQuery(Loader.java:773)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
    at org.hibernate.loader.Loader.doList(Loader.java:2449)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2192)
    at org.hibernate.loader.Loader.list(Loader.java:2187)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:119)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1706)
    at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:347)
    at com.soebes.casestudy.dao.HibernateDAO.findAll(HibernateDAO.java:68)
    at com.soebes.casestudy.dao.HibernateDAO.get(HibernateDAO.java:75)
    at com.soebes.casestudy.dao.IdDAO.get(IdDAO.java:23)
    at com.soebes.casestudy.CategoryBOTest.testGet(CategoryBOTest.java:26)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:128)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)

which I assume is caused by the rows where parentId is 0. Which makes sense, cause no category with the categoryid of 0 exists. But the question is: How can i map that to the meaning not having a parent category?

Update

So after updating my definitions in code like this:

@ManyToOne( cascade = { CascadeType.ALL } )
@JoinColumn(name = "parentid")
@NotFound(action = NotFoundAction.IGNORE)
private CategoryBO parent;

@OneToMany(mappedBy = "parent")
@NotFound(action = NotFoundAction.IGNORE)
private List<CategoryBO> subCategories;

Now i get a list of categories.

like image 985
khmarbaise Avatar asked May 30 '13 16:05

khmarbaise


People also ask

Which databases allow only a parent child relationship?

1 Answer. Parent child relationship is established in Hierarchical database Models.

Which is the parent child relationship in DBMS?

In database management, a relationship between two files. The parent file contains required data about a subject, such as employees and customers. The child is the offspring; for example, an order is the child to the customer, who is the parent.

How do you create a parent child relationship in ServiceNow?

ServiceNow provides OOTB Parent child relationship. On the incident form Right click on the header and click on the Create Child Incident option. Mark Helpful or correct if it helps.


1 Answers

You should use Listinstead of ArrayList.

Hibernate may put in another List-implementation to support lazy loading.

EDIT: You also have to use NULL instead of 0 because otherwise Hibernate searches for the object with the id 0.

like image 169
Jimmy T. Avatar answered Oct 09 '22 11:10

Jimmy T.