Hibernate多态:实例化正确的类

时间:2009-04-16 19:58:15

标签: java hibernate orm

我很快就会进入休眠状态,你很快就会看到。如果这个问题有一个简单的答案我很抱歉,但我对所有的术语都不太熟悉,很容易找到它。

假设我有一个基类“A”和一个子类“B”,我用Hibernate映射,也许使用每个子类策略的表。基类不是抽象的。所有的B都是As,但不是所有的B都是。这反映在数据库中,表B引用表A。

好的,现在假设我有一个显示A对象列表的某种程序。用户可以选择任何A对象并进入屏幕进行修改......但是,如果A对象也是B,则屏幕将允许用户修改B而不是A。

我如何处理这个问题?

注意:我不是在询问如何确定对象是什么类。我问的是如何让hibernate返回一个正确类的对象列表。

3 个答案:

答案 0 :(得分:6)

我再次为这个问题道歉。我对hibernate的工作原理感到非常惊讶,这真的很酷。我不认为它会自动完成所有这些,我甚至不确定我想要问的是什么。当我回复评论时,我开始在脑海中改进这个问题,然后能够找到我想要的答案。感谢所有帮助过的人。

答案是:hibernate会自动执行此操作。

假设您的数据库表A中有一个主键“id”,另一个表B有一个名为“a_id”的主键,它引用了表A.

所以你创建了以下类(缩写):

public class A {
  private String aProperty;
  // ... getter and setter, etc
{

public class B extends A {
  private String bProperty;
  // ... getter and setter, etc
}

然后像这样映射它们:

<hibernate-mapping>
    <class name="A" table="a" catalog="testokdelete">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="identity" />
        </id>
        <property name="aProperty" column="a_property"/>
        <joined-subclass name="B" table="b">
            <key column="a_id"/>
            <property name="bProperty" column="b_property"/>
        </joined-subclass>
    </class>
</hibernate-mapping>

您可以使用简单的“from A”查询返回A和B对象,如下面的代码所示:

Query query = session.createQuery("from A");
List<Object> objects = query.list();
for (Object object: objects) {
    System.out.print("A property: ");
    System.out.print(((A)object).getAProperty());
    System.out.print(", B property: ");
    System.out.println( (object.getClass() == B.class) ? ((B)object).getBProperty() : "not a B");
}

所有这一切都是使用“来自A”的查询返回一个对象列表,然后遍历它们从A类中打印出aProperty,如果类是B类,则从我们的B类中打印出bProperty。 / p>

在这种情况下,hibernate查询是自动多态的,并在适当的时候给你一个B对象。

答案 1 :(得分:2)

您可以使用带有instanceof的RTTI,但这不是面向对象的。

相反,为基类A提供一个方法,该方法与B的额外内容有关,例如ACustomer还是BPreferredCustomer,方法可能是isPreferredCustomer()

A中,方法返回false,在B中返回true。

重要的是要注意,我们不是在询问一个物体是否属于某一类;我们问一个商业问题,问对象是否可以做某事。这是一个微妙但重要的区别。

特别是,这意味着只要每个子类真实地回答了问题Customer,就可以在何时以及如果添加更多isPreferredCustomer()子类时更改下面的代码。

在您的代码中:

if( a.isPreferredCustomer() ) {
  showPreferredCustomerPage( a) ;
else { 
  show CustomerPage(a);
}

您可能认为给Customer showPage()方法提供更好的方法,但这会使您的模型与您的观点紧密联系。

相反,您将上面的代码放在某个ViewDispatcher类中,该类可以与Customer及其子类正交。

例如,您可能有几个ViewDispatcher子类,其中一些关注PreferredCustomer s,另一些关注{{1}}。

答案 2 :(得分:1)

好吧我会假设您已正确映射您的类。如果你这样做了,你应该能够做到以下几点,我想:

public List<A> getAllClassA(){
      Session session = HibernateUtil.getSession();
      Criteria criteria = session.createCriteria(A.class);

      List<A> ret = criteria.list();

      return ret;
}

如果你不熟悉Criteria,它很容易上手。这段代码将从数据库中检索出A类的所有对象。如果你已正确映射它,我认为Hibernate也将维护你A对象的B属性,如果它们实际上是B对象(对不起,如果那令人困惑)。

如果您正在寻找或者您是否需要HibernateUtil的代码,请告诉我。