Hibernate:一对一延迟加载,可选= false

时间:2013-08-01 07:24:59

标签: hibernate jpa lazy-loading one-to-one

我遇到了一对一延迟加载在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注释如何帮助实现延迟加载。

PS 我已阅读帖子post1post2,并了解为什么简单的OneToOne不能懒惰,但我仍然无法抓住{{1}魔术。

2 个答案:

答案 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)注释。