如何避免在 Hibernate 中获取 javassist 惰性实体代理实例
Posted
技术标签:
【中文标题】如何避免在 Hibernate 中获取 javassist 惰性实体代理实例【英文标题】:how to avoid getting javassist lazy Entity proxy instances in Hibernate 【发布时间】:2012-12-11 00:44:10 【问题描述】:为了避免 Hibernate 给我懒惰的 javassist 实例代理而不是真正的实体,我需要做些什么改变?
更新:我正在使用 Spring 3.x 和 Hibernate 4.x
我用来加载实体的 API 是 org.hibernate.internal.SessionImpl#load(Person.class, Id)
并且映射很简单:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.perfectjpattern.example.model">
<class name="Person" table="PERSON_" >
<id name="id">
<generator class="native"></generator>
</id>
<property name="name" update="false" />
<property name="age" update="true" />
</class>
<query name="Person.findByName">
<![CDATA[select p from Person p where p.name = ? ]]>
</query>
<query name="Person.findByAge">
<![CDATA[select p from Person p where p.age = :Age ]]>
</query>
</hibernate-mapping>
【问题讨论】:
使用急切而不是延迟加载。 我可以想象,但是具体什么地方需要配置,这就是OP 如果您向我们展示您的映射实体之一,我们可以为您提供帮助。 几乎 100% 的时间您都想这样做,但这是解决您遇到的问题的错误方法。您可以考虑寻求帮助来解决您的实际问题。 【参考方案1】:您可以在session.load(id)
之后使用Hibernate.initialize(obj)
。
这个方法可以立即初始化你的obj。
【讨论】:
...基本上是using session.get()的更复杂更慢的版本。 您可以在需要时初始化您的 obj,而不是总是初始化它。【参考方案2】:实际上只需将映射更改为(参见default-lazy="false"
)即可解决:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.perfectjpattern.example.model" default-lazy="false">
【讨论】:
这非常危险,因为它将所有实体和集合都设置为非惰性,这意味着您很容易意外地将整个数据库加载到内存中。 感谢您提出这个问题,但是,正如您在 OP 中所指出的那样,我的映射中只定义了一个实体。在我的用例中,我还load
仅一个元素(按 ID)。如果我维护一个更大的项目,每个实体都会有自己的映射文件,我可以在其中决定加载策略应该是什么。还有另一方面,对于不同的用例,我必须调用 load
或 get
从代码可重用性的角度来看这不是一件好事。【参考方案3】:
使用get() 而不是load()。
【讨论】:
+1 以获得更多细节,但我认为load
会更灵活,因为在其他情况下我可能会选择延迟加载。我可以通过这种方式分别为每个实体配置它。
您的应用程序应该选择何时急切地获取东西,何时不急切地获取东西。 IE。必要时使用 get(),其他时候使用 load()。
但还要注意,如果您的应用程序确实需要意识到这一点,那么您几乎可以肯定做错了什么。延迟加载被设计成透明的。以上是关于如何避免在 Hibernate 中获取 javassist 惰性实体代理实例的主要内容,如果未能解决你的问题,请参考以下文章
如何避免 Hibernate ValidationException 上的自动实体更新
如何避免两个不同的线程从DB中读取相同的行(Hibernate和Oracle 10g)