即使它们被声明为Lazy,集合也会被加载

时间:2011-05-26 12:03:50

标签: hibernate jpa

@Entity 
public class User {

    @ManyToMany(cascade = { MERGE, PERSIST, CascadeType.REFRESH }, fetch = LAZY)
    @Cache(usage = READ_WRITE)
    @UserRoles
    private List<Role> roles = new ArrayList<Role>(0);

}

即使将它们声明为Lazy,它们也会被加载,即使它被声明为Lazy,它也可能被加载的原因

1 个答案:

答案 0 :(得分:2)

根据JPA 2.0规范,延迟提取是对持久性提供程序的暗示。

第11.1.6节说:

  

EAGER战略是一项要求   持久性提供程序运行时   必须急切地获取数据。懒人   战略是对持久性的暗示   应该是数据的提供者运行时   它是第一次懒洋洋地取出来   访问。实施是   允许急切地获取数据   这是LAZY战略的暗示   指定。

在某些情况下,提供程序可能会确定懒惰地获取某些内容是没有意义的,或者提供程序可能甚至没有实现延迟提取。

PersistenceUtil.isLoaded方法可用于确定实体的加载状态 及其属性,与实体关联的持久性单元无关。

为确保您遇到此类问题,您应该使用此方法。当然,如果一个实体脱离了分支,那么对这个懒惰的领域的简单检查也会有所帮助。

除此之外,基于发布的代码为什么您的收藏品没有被懒惰地取出,我看不出特定的原因。我想也许你使用二级缓存的事实可能会影响到这种情况,但这是我尚未验证的,它只是一种预感。

<强> [EDIT-1]

如果您使用的是最终类,则延迟加载也存在问题。 Hibernate文档在persistent classes

下说
  

Hibernate的核心功能,   代理,取决于持久性   上课要么是非最终的,要么是   实现一个接口   声明所有公共方法。

     

你可以坚持最后的课程   没有实现接口   休眠。但是,你不会   能够使用代理进行懒惰   关联取得哪个会   最终限制你的选择   性能调整。

     

你也应该避免宣布公开   关于非决赛的最终方法   类。如果你想使用一个类   用公共最终方法,你必须   通过设置显式禁用代理   懒惰= “假”。

<强> [EDIT-2]

除此之外,2.1节中的JPA 2.0规范规定实体不得是最终的:

  

实体类不能是最终的。没有   方法或持久化实例   实体类的变量可以是   最终

稍后在2.5节中为嵌入式规定了同样的要求。

我无法访问JPA 1.0规范,但我相信这个要求也适用于它。试一试,看看是不是这个原因让我们知道。