11

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

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

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

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

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

如何阻止休眠不加载代理,同时仍然允许此属性为空?

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

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

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

4

6 回答 6

9

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

为了提供字段的延迟加载,文档参考了构建时字段的字节码增强:使用延迟属性获取。这是一段摘录:

Hibernate3 支持对单个属性的惰性获取。这种优化技术也称为提取组。请注意,这主要是一种营销功能,因为在实践中,优化行读取比优化列读取更重要。但是,仅加载类的某些属性在极端情况下可能很有用,即遗留表有数百列并且无法改进数据模型。

延迟属性加载需要构建时字节码检测!如果您的持久类没有得到增强,Hibernate 将默默地忽略惰性属性设置并回退到立即获取。

于 2008-10-21T16:50:44.867 回答
2

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

我假设您正在使用 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>
于 2009-08-22T00:23:44.663 回答
2

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

于 2011-02-23T16:16:47.347 回答
0

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

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

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

于 2008-10-21T16:17:21.423 回答
0

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

于 2008-10-21T18:36:05.277 回答
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") 中描述的映射。嗯,我想我会为此提出一个问题。;-)

于 2009-05-08T07:49:51.017 回答