我有一个Person类,它有一个名为autos的惰性初始化集合。从数据库中获取人员后,我调用了两个名为isInitialized(autos)和isPropertyInitialized(personObject,autos)的休眠方法,第一个显示为false,第二个显示为true。为什么?
@Entity
public class Person {
@OneToMany(mappedBy="person",fetch=FetchType.LAZY)
private List<Auto> autos;
}
@Entity
public class Auto {
@ManyToOne
@JoinColumn(name = "person_id", nullable = false)
private Person person;
}
测试代码:
Person p = personRepository.findAll().get(0);
System.out.println(Hibernate.isInitialized(p.getAutos()));
System.out.println(Hibernate.isPropertyInitialized(p,"autos"));
控制台:
false
true
答案 0 :(得分:1)
我相信在这种情况下使用Hibernate.isPropertyInitialized
可能是不正确的。
根据documentation Hibernate.isPropertyInitialized
,应用于验证属性或状态的惰性,例如"name"
对象的Person
。要验证子实体的惰性,应使用Hibernate.isInitialized
boolean personInitialized = Hibernate.isInitialized(person);
boolean personBooksInitialized = Hibernate.isInitialized(person.getBooks());
boolean personNameInitialized = Hibernate.isPropertyInitialized(person, "name");
或者最好是在文档javax.persistence.PersistenceUtil.isLoaded
PersistenceUtil persistenceUnitUtil = Persistence.getPersistenceUtil();
boolean personInitialized = persistenceUnitUtil.isLoaded(person);
boolean personBooksInitialized = persistenceUnitUtil.isLoaded(person.getBooks());
boolean personNameInitialized = persistenceUnitUtil.isLoaded(person, "name");
现在为什么有Hibernate.isPropertyInitialized
,为什么总是返回true
我相信主要原因是Bytecode enhancement和惰性属性加载。
通常,在获取实体时,所有属性都会加载,例如"name"
,"age"
等
在获取实体时,所有属性都将作为 好。这是因为每个实体属性都隐式标记为 @Basic批注,其默认提取策略为FetchType.EAGER。 source
但是,通过字节码增强,我们可以定义哪些属性应该是惰性的。当我们有一些大的属性(例如斑点图像)时,这很有用。我相信对于这种特殊情况,我们需要Hibernate.isPropertyInitialized
在您的情况下,为什么总是返回true
。如果我们看一下该方法的Java文档,就会发现它期望
@param proxy The potential proxy
如果它是HibernateProxy
,则将检查它是否未初始化。如果是,您将收到false
,因为对于代理懒惰,所有属性都急于初始化,因此代理未初始化,因此属性也是如此。另一方面,我们有一条声明
@return true if the named property of the object is not listed as uninitialized; false otherwise
因此,在您的情况下,由于Person
已经初始化,因此您没有使用惰性属性提取机制,也没有传递代理对象。无法检查该属性是否被列为未初始化,因此返回true
。