Hibernate不会检索孩子,但如果存在仍然存在?

时间:2017-01-26 08:43:38

标签: java hibernate

我有一个遗留的hibernate应用程序(使用hibernate 3.2.6.ga),我们获取类似于下面结构的信息。我们有一个人包含其他几个属性,如地址详细信息或银行帐户或交易。

    • 地址详情清单
    • 银行帐户清单
    • 交易清单
    • 以及更多...

使用这样的hibernate映射文件:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="myPkg.Person" table="PERSON" schema="WhatEver" lazy="false">    

        <id name="personId" type="java.lang.Long">
            <column name="PERSON_ID" precision="1" />
            <generator class="sequence">
                <param name="sequence">some_sequence_generator</param>
            </generator>
        </id>

        <!-- lazy init is true as only some methods is interested in addressDetails-->
        <bag name="addressDetails" inverse="true" cascade="all" lazy="true">
            <meta attribute="propertyType">java.util.LinkedList</meta>          
            <key>
                <column name="PERSON_ID" precision="10" not-null="true" />
            </key>
            <one-to-many class="myPkg.Address" />
        </bag>
        ...

        <!-- lazy init is true as a person can have billion transactions -->
        <bag name="transactionDetails" inverse="true" cascade="all" lazy="true">
            <meta attribute="propertyType">java.util.LinkedList</meta>          
            <key>
                <column name="PERSON_ID" precision="10" not-null="true" />
            </key>
            <one-to-many class="myPkg.transaction" />
        </bag>

    </class>
</hibernate-mapping>

我们有几种方法来检索这些人。有些人要求返回与孩子相关的数据,有些则不需要。因此,映射文件中的所有内容都设置为lazy=”true”

如果我们在返回数据后立即对孩子感兴趣,我们会Hibernate.initialize(personObjectJustReturned)去抓取孩子:

Person personInstance = (Person) getHibernateTemplate().get(Person.class, new Long(id));
Hibernate.initialize(personInstance);

但问题在于交易清单,因为这可能会成为一个非常庞大的数据集 - 一个人可能拥有数十亿的交易。

我想做的是永远不会返回与person对象的交易。

所以我可以做两件事之一:

  1. 通过设置lazy=”false”(除了我的交易)并且不执行Hibernate.initialize(personObjectJustReturned),只需在我的XML文件中急切加载每一个内容。但这意味着返回数据的任何其他方法都会急切地获取子数据,以及应用程序中的所有方法都使用相同的hibernate映射。这并不理想,例如并非所有方法都需要地址详细信息。因此,我将获取比全球范围内所需的更多数据,这是不好的做法。

  2. 从我的配置文件中删除交易字段关系,以便hibernate在检索人员时甚至不知道交易字段。这将完美地工作,但是在我们保存人物对象并且该人具有新生成的交易的情况下,我们将不得不单独保存交易。 Aka我们不能简单地告诉hibernate去保存自动保存新生成的事务的person对象,因为hibernate不再知道这种关系了。

  3. 有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

如果每个对象有很多子项,则显示的第一个选项可能会导致内存消耗问题。

然后,最好的选择是加载父对象提取的子项:

SELECT * FROM transaction_detail WHERE person = ?

通过这种方式,您可以避免使用Hibernate.initialize(personObjectJustReturned)并更精确地获取详细信息(已排序或过滤)。

然后,要保存新的transactionDetail,TransactionDetail对象必须设置Person对象(作为父对象),并在保存时(保存将在TransactionDetail处完成) ,不应该发生错误(外键会避免孤儿)。