Hibernate 4:HQL 和继承 - 获取集合和 javassist

Posted

技术标签:

【中文标题】Hibernate 4:HQL 和继承 - 获取集合和 javassist【英文标题】:Hibernate 4: HQL and Inheritance - fetching collections and javassist 【发布时间】:2012-11-17 04:53:02 【问题描述】:

我有这种情况:父类 Person,子类:个人和企业。我正在使用如下所示的加入子类策略映射这些类:

<hibernate-mapping>
  <class catalog="test" name="test.Person" table="Persons">
    <id name="id" type="int">
      <column name="IdPerson"/>
      <generator class="increment"/>
    </id>

    <set inverse="true" name="addresses">
      <key>
        <column name="IdPerson" not-null="true"/>
      </key>
      <one-to-many class="test.Address"/>
    </set>

    <set inverse="true" name="phones">
      <key>
        <column name="IdPerson" not-null="true"/>
      </key>
      <one-to-many class="test.Phone"/>
    </set>

    <joined-subclass name="test.Individual" table="Individuals">
      <key column="IdPerson"/>

      <property name="nameIndividual" type="string">
        <column length="30" name="Name" not-null="true"/>
      </property>
    ...
    </joined-subclass>

    <joined-subclass name="test.Enterprise" table="Enterprises">
      <key column="IdPerson"/>

      <property name="nameEnterprise" type="string">
        <column length="30" name="Name" not-null="true"/>
      </property>
    ...
    </joined-subclass>

  </class>

  <class catalog="test" name="test.Address" table="Addresses">

    <composite-id class="test.AddressId" name="id">
      <key-many-to-one name="person" class="test.Person">
        <column name="IdPerson" not-null="true"/>
      </key-many-to-one>
      <key-property name="id" type="int">
        <column name="IdAddress"/>
      </key-property>
    </composite-id>

    <many-to-one name="person" class="test.Person" fetch="select" insert="false" update="false">
      <column name="IdPerson" not-null="true"/>
    </many-to-one>
    ...    
  </class>

  <class catalog="test" name="test.Phone" table="Phones">

    <composite-id class="test.PhoneId" name="id">
      <key-many-to-one name="person" class="test.Person">
        <column name="IdPerson" not-null="true"/>
      </key-many-to-one>
      <key-property name="id" type="int">
        <column name="IdPhone"/>
      </key-property>
    </composite-id>

    <many-to-one name="person" class="test.Person" fetch="select" insert="false" update="false">
      <column name="IdPerson" not-null="true"/>
    </many-to-one>
    ...
  </class>

</hibernate-mapping>

当我使用这个简单的 HQL 加载人员列表时:

List result = session.createQuery("from Person as en").list();

hibernate 解决了多态问题,我得到了个人和企业对象的列表。

但是当我包括地址和电话时:

List result = session.createQuery("from Person as en left join fetch en.addresses left join fetch en.phones").list();

hibernate 返回一个 Person_$$_javassist_5 对象列表,无法访问 Indivual 和 Enterprise 类的特定属性。

这是预期的行为吗?我该如何解决这个问题?

提前致谢。

已编辑:

我已经包含了 Address 和 Phone 类映射,它的 id 是复合的,这似乎是 hibernate 生成 javassist 代理的原因,但是为什么代理不能正确解析多态性?即使hibernate从数据库中获取所有数据。

我的 JSF 页面抛出 javax.el.PropertyNotFoundException 错误:类“test.Person_$$_javassist_5”没有属性“nameIndividual”。

【问题讨论】:

【参考方案1】:

我尝试了类似的例子,即一个类有两个连接子类 并且父类是一对多的关联。

就像在您的示例中一样,我在不使用 fetch 的情况下检索父类记录,然后使用“left join fetch”。

两次都正确检索了一对多关联。

当我使用 fetch 模式时,结果列表包含重复记录。

例如在一对多关联中,一条记录在相关表中有 4 条记录,则结果列表包含 4 次相同的对象。 对于其他记录,如果相关有 2 条记录,则结果列表包含相同的对象 2 次。

但是根据 Hibernate 文档,这是预期的:- http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html

"fetch 构造不能用于调用 iterate() 的查询(尽管可以使用 scroll())。Fetch 应该与 setMaxResults() 或 setFirstResult() 一起使用,因为这些操作基于结果行它通常包含用于急切集合获取的重复项,因此,行数不是您所期望的。Fetch 也不应该与即兴条件一起使用。可以通过连接获取多个集合来创建笛卡尔积一个查询,所以在这种情况下要小心。join fetch 多个collection 角色可能会产生bag mapping 的意外结果,因此在这种情况下制定查询时建议用户谨慎。最后请注意,full join fetch 和 right join fetch 没有意义。 "

【讨论】:

感谢您的时间和回答,对不起,我省略了地址和电话映射,如果这些类有简单的 id,那么当您评论时休眠可以正常工作,但它们实际上是复合的。

以上是关于Hibernate 4:HQL 和继承 - 获取集合和 javassist的主要内容,如果未能解决你的问题,请参考以下文章

hibernate用HQL查询集合属性

Hibernate之HQL基本用法

hibernate的hql把一列的结果集拼接成一个字符串

Hibernate查询(HQL——Hibernate Query Language)

Hibernate 之HQL数据查询

hibernate之HQL查询