我遇到了一对一延迟加载在hibernate中不起作用的问题。我已经解决了,但不正确了解会发生什么。
我的代码(延迟加载在这里不起作用,当我拉人 - 地址也被提取):
@Entity
public class Person{
@Id
@SequenceGenerator(name = "person_sequence", sequenceName = "sq_person")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_sequence")
@Column(name = "id")
private long personID;
@OneToOne(mappedBy="person", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private Adress address;
//.. getters, setters
}
@Entity
public class Address {
@Id
@Column(name="id", unique=true, nullable=false)
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="person"))
private long personID;
@PrimaryKeyJoinColumn
@OneToOne
private FileInfo person;
}
但是:如果我在OneToOne关系中添加 optional=false
,则延迟加载正常工作!
@OneToOne(mappedBy="person", cascade=CascadeType.ALL, optional = false, fetch = FetchType.LAZY)
private Adress address;
问题/恳求:请向我解释optional=false
注释如何帮助实现延迟加载。
答案 0 :(得分:76)
如果关联是可选的,则Hibernate无法在不发出查询的情况下知道给定人员是否存在地址。所以它不能用代理填充地址字段,因为可能没有引用该人的地址,并且它不能用null填充它,因为可能有一个地址引用该人。
当您强制关联时(即optional=false
),它会信任您并假定存在地址,因为关联是强制性的。所以它直接用代理填充地址字段,知道有一个引用该人的地址。
答案 1 :(得分:8)
最简单的就是伪造一对多的关系。这将起作用,因为延迟加载集合比单个可空属性的延迟加载容易得多,但是如果使用复杂的JPQL / HQL查询,通常这个解决方案非常不方便。
另一个是使用构建时字节码检测。有关更多详细信息,请阅读Hibernate文档:19.1.7。使用lazy属性获取。请记住,在这种情况下,您必须将@LazyToOne(LazyToOneOption.NO_PROXY)
注释添加到一对一关系中以使其变得懒惰。将提取设置为LAZY是不够的。
最后一个解决方案是使用运行时字节码检测,但它只适用于在完整的JEE环境中使用Hibernate作为JPA提供程序的人(在这种情况下设置" hibernate.ejb.use_class_enhancer
"到是真的应该做的伎俩:实体管理器配置)或使用Hibernate与Spring配置进行运行时编织(这可能很难在一些较旧的应用程序服务器上实现)。在这种情况下,还需要@LazyToOne(LazyToOneOption.NO_PROXY)
注释。