次のような単純な自己親子関係 (カテゴリ) を含むデータベース テーブルがあります。
+------------+----------+--------------------+
| 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(..) の 2 つのパブリック メソッドのみが含まれます)。
@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)
わかりません。
それで、私の誤解や問題はどこにありますか(本当にばかげていると思います)...
更新:
次のように、ジミー T の回答の提案に応じてコードを更新した後:
@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 である行が原因であると想定しています。これは理にかなっています。categoryid が 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;
今、私はカテゴリのリストを取得します。