我有一个遗留的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对象的交易。
所以我可以做两件事之一:
通过设置lazy=”false”
(除了我的交易)并且不执行Hibernate.initialize(personObjectJustReturned)
,只需在我的XML文件中急切加载每一个内容。但这意味着返回数据的任何其他方法都会急切地获取子数据,以及应用程序中的所有方法都使用相同的hibernate映射。这并不理想,例如并非所有方法都需要地址详细信息。因此,我将获取比全球范围内所需的更多数据,这是不好的做法。
从我的配置文件中删除交易字段关系,以便hibernate在检索人员时甚至不知道交易字段。这将完美地工作,但是在我们保存人物对象并且该人具有新生成的交易的情况下,我们将不得不单独保存交易。 Aka我们不能简单地告诉hibernate去保存自动保存新生成的事务的person对象,因为hibernate不再知道这种关系了。
有更好的方法吗?
答案 0 :(得分:1)
如果每个对象有很多子项,则显示的第一个选项可能会导致内存消耗问题。
然后,最好的选择是加载父对象提取的子项:
SELECT * FROM transaction_detail WHERE person = ?
通过这种方式,您可以避免使用Hibernate.initialize(personObjectJustReturned)
并更精确地获取详细信息(已排序或过滤)。
然后,要保存新的transactionDetail,TransactionDetail
对象必须设置Person
对象(作为父对象),并在保存时(保存将在TransactionDetail
处完成) ,不应该发生错误(外键会避免孤儿)。