1

如何使用 Hibernate 嵌套子类?

例如,我有以下类层次结构:

PageElement
- PageParagraph
- PageImage
- PageVideo
- PageAudio
- PageQuestion
  - PageFillInTheBlankQuestion
  - PageOpenEndedQuestion
  - PageMultipleChoiceQuestion
  - ...

这是理想的对象结构。如何使用 Hibernate 成功映射它?我会说PageQuestion抽象类非常重要。它包含许多可重用的属性和逻辑。我还需要PageQuestion专门引用而不引用PageElement<- 这会很糟糕。我还想查询所有PageQuestion对象。

4

2 回答 2

1

在 Hibernate 4.0(可能更早)中,如果您使用的是 table-per-hierarchy 模型,则可以使用嵌套元素。

示例类结构:

Word (has property "text", string)
- Subject (adds property "plural", boolean)
  - Pronoun (adds property "masculine", boolean)
  - ProperNoun (adds property "person", boolean)
- Verb (adds property "past_tense", boolean)

示例 Hibernate 映射 XML:

<class name="test.Word" table="words">
    <id name="id"><generator class="native"/></id>
    <discriminator column="word_type" type="string"/>
    <property name="text"/>
    <subclass name="test.Subject">
        <property name="plural"/>
        <subclass name="test.ProperNoun">
            <property name="person"/>
        </subclass>
        <subclass name="test.Pronoun">
            <property name="masculine"/>
        </subclass>
    </subclass>
    <subclass name="test.Verb">
        <property name="past_tense"/>
    </subclass>
</class>

然后,在运行以下代码之后(我省略了类代码,它非常基本,老实说,只有对象类型本身对这个示例很重要):

    HibernateUtil.beginTransaction();
    HibernateUtil.getCurrentSession().persist(new Word("blue"));
    HibernateUtil.getCurrentSession().persist(new Subject("chairs", true));
    HibernateUtil.getCurrentSession().persist(new ProperNoun("James", true));
    HibernateUtil.getCurrentSession().persist(new Pronoun("he", false, true));
    HibernateUtil.getCurrentSession().persist(new Verb("sat", true));
    HibernateUtil.commitTransaction();

数据库最终包含以下信息:

id, word_type, text, plural, person, masculine, past_tense,
1, test.Word, blue, NULL, NULL, NULL, NULL
2, test.Subject, chairs, 1, NULL, NULL, NULL
3, test.ProperNoun, James, 0, 1, NULL, NULL
4, test.Pronoun, he, 0, NULL, 1, NULL
5, test.Verb, sat, NULL, NULL, NULL, 1

并查询返回的对象列表会产生正确的类型:

    HibernateUtil.beginTransaction();
    List<Word> words = HibernateUtil.getCurrentSession().createCriteria(Word.class).list();
    for (Word w:words)
        System.out.println(w);
    HibernateUtil.commitTransaction();

印刷:

test.Word@caf6c1
test.Subject@10e35d5
test.ProperNoun@18e8541
test.Pronoun@1ce85c4
test.Verb@17aece8

请参阅http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html/inheritance.html的第 10.1.1 节(尽管它与旧文档基本相同),但不幸的是它确实如此没有清楚地表明允许嵌套子类 - 但这是一件容易试验的事情。

我同意 Hibernate 文档的组织非常糟糕。一切都在那里,但我发现它的组织方式让我很难找到完整的信息;主要是由于过度使用交叉引用,以及并不总是涵盖所有基础的面向用例的布局。但是,信息那里。

于 2013-07-03T17:47:45.667 回答
0

这正是对象和关系范式之间的问题。

Hibernate 就是这个工具。并且您已经为此提供了参考。

http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#d0e6906

于 2011-12-11T14:08:24.577 回答