Hibernate Mapping Отношения родитель/потомок

У меня есть таблица базы данных, которая содержит простые родительские/дочерние отношения (категории), например:

+------------+----------+--------------------+
| 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          |

Теперь я создал класс отображения Hibernate CategoryBO с приведенной выше таблицей, подобной этой (AbstractBaseBO содержит только два общедоступных метода getId() и 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

}

Но если я попытаюсь получить список записей категорий из базы данных, я получу следующее сообщение об ошибке:

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)

чего я не понимаю.

Так в чем же мое непонимание или моя проблема (я предполагаю что-то действительно глупое)...

Обновление:

После того, как я обновил код в соответствии с предложением в ответе Джимми Т., например:

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

Я получил следующие сообщения об ошибках:

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)

что, как я предполагаю, вызвано строками, где parentId равен 0. Что имеет смысл, потому что не существует категории с идентификатором категории 0. Но вопрос в том, как я могу сопоставить это со значением, не имеющим родительской категории?

Обновить

Итак, после обновления моих определений в коде следующим образом:

@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;

Теперь я получаю список категорий.


person khmarbaise    schedule 30.05.2013    source источник


Ответы (1)


Вы должны использовать Listвместо ArrayList.

Hibernate может добавить другую реализацию List для поддержки ленивой загрузки.

EDIT: вы также должны использовать NULL вместо 0, потому что в противном случае Hibernate ищет объект с идентификатором 0.

person Jimmy T.    schedule 30.05.2013
comment
@khmarbaise Это должно решить проблему - person Jimmy T.; 30.05.2013