如何阻止Hibernate急切地获取多对一关联对象

时间:2008-10-21 16:09:43

标签: java hibernate

我在一个域对象上有一个属性,该属性在多对一元素中声明。此属性的基本语法如下所示:

<many-to-one name="propertyName" class="propertyClass" fetch="select" not-found="ignore" lazy="proxy" />

现在,我们的想法是让Hibernate不急切地获取这个属性。它可能为null,因此设置了未找到的忽略。

但是,Hibernate在加载包含此关联的类时,会在加载父类时自行加载实际的类(甚至不是代理)实例。由于某些属性的大小超过1MB,因此占用了大量的堆空间。

但是,如果not-found设置为异常(或默认为异常),则具有此属性的父类会加载代理!

如何在不加载代理的情况下阻止hibernate,同时仍允许此属性为空?

我发现lazy = no-proxy,但是文档讨论了某种字节码修改,并没有详细说明。有人可以帮助我吗?

如果重要的话,它是Hibernate的Java版本,它至少是版本3(如果它有帮助我可以查看实际版本,但现在它是Hibernate 3+)。

我之前没有说明,但Java版本是1.4。因此,不支持Java注释。

6 个答案:

答案 0 :(得分:9)

如果关联的另一端可以是 null ,我相信hibernate必须查询关联结束,以确定它是否应该使用代理(如果另一个则不需要代理)结束是 null )。我现在找不到对此的引用,但我记得在某处读过它。

为了提供字段的延迟加载,文档引用了构建时字段的字节码增强功能:Using lazy property fetching。这是一段摘录:

  

Hibernate3支持延迟抓取   个人财产。这个   优化技术也是已知的   作为获取组。请注意这一点   主要是营销功能,如   练习,优化行读取很多   比优化更重要   列读。但是,只能加载   类的某些属性可能是   遗留下来的极端情况下很有用   表有数百列和   数据模型无法改进。

     

懒惰的属性加载需要   构建时间字节码检测!如果   你的持久化课程不是   增强,Hibernate将默默无闻   忽略懒惰的属性设置和下降   回到即时提取。

答案 1 :(得分:2)

  

我发现懒惰=没有代理,但是   文档谈论某种   字节码修改,不去   任何细节。有人能帮我吗   出?

我假设您正在使用ANT来构建项目。

<property name="src" value="/your/src/directory"/><!-- path of the source files -->
<property name="libs" value="/your/libs/directory"/><!-- path of your libraries -->
<property name="destination" value="/your/build/directory"/><!-- path of your build directory -->

<fileset id="applibs" dir="${libs}">
  <include name="hibernate3.jar" />
  <!-- include any other libraries you'll need here -->
</fileset>

<target name="compile">
  <javac srcdir="${src}" destdir="${destination}" debug="yes">
    <classpath>
      <fileset refid="applibs"/>
    </classpath>
  </javac>
</target>

<target name="instrument" depends="compile">
  <taskdef name="instrument" classname="org.hibernate.tool.instrument.javassist.InstrumentTask">
    <classpath>
      <fileset refid="applibs"/>
    </classpath>
  </taskdef>

  <instrument verbose="true">
    <fileset dir="${destination}">
      <!-- substitute the package where you keep your domain objs -->
      <include name="/com/mycompany/domainobjects/*.class"/>
    </fileset>
  </instrument>
</target>

答案 2 :(得分:2)

确保你的课程不是最终的!

答案 3 :(得分:0)

如果您通过控制器将hibernate对象从模型传递到视图,请不要!

而是创建一个“快照对象”来存储要传递给视图并显示的Hibernate对象的值。

<强>为什么吗 代理仍可以在控制器中检索值...但是当您将代理/对象传递给视图时,它不再能够检索值,因为事务已经结束。这就是为什么我建议我上面提到的。

答案 4 :(得分:0)

使用Hibernate注释时,在关联上放置@ManyToOne(fetch = FetchType.LAZY),完成你想要的。您是否尝试过设置fetch =“lazy”以查看是否有效?

答案 5 :(得分:0)

@Miguel Ping: 我认为你所指的页面是[http://www.hibernate.org/162.html]。据我所知,在一对一的情况下需要额外的SELECT,其中不存在外键。设置constrained="true"告诉Hibernate,另一端始终存在,不需要额外的SELECT。

因此,对于外键所在的多对一方,没有必要这么做 执行另一个SELECT,因为FK的值告诉另一端是否存在或null。至少,这就是我理解的方式。

迄今为止的理论。代理在外键/多对一方面为我工作。用于关联的映射是:

<many-to-one name="haendler" column="VERK_HAENDLOID" lazy="proxy" />

但代理对我来说并不适用于使用给定URL(constrained="true")所描述的映射的一对一方面。嗯,我想我会为此提出一个问题。 ; - )