78

我遇到了一对一延迟加载在休眠中不起作用的问题。我已经解决了它,但仍然不能正确理解会发生什么。

我的代码(延迟加载在这里不起作用,当我拉人时 - 地址也被提取):

@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;
}

但是:如果我添加optional=falseOneToOne 关系,延迟加载工作正常

@OneToOne(mappedBy="person", cascade=CascadeType.ALL, optional = false, fetch = FetchType.LAZY)
private Adress address;

问题/恳求:请向我解释一下optional=false注解如何帮助实现延迟加载。

PS我看过帖子post1post2,明白为什么简单的 OneToOne 不能偷懒,但我仍然无法掌握optional=false魔法。

4

2 回答 2

102

如果关联是可选的,Hibernate 无法在不发出查询的情况下知道给定人员的地址是否存在。所以它不能用代理填充地址字段,因为可能没有引用该人的地址,也不能用 填充它null,因为可能有一个引用该人的地址。

当您使关联成为强制性(即optional=false)时,它信任您并假定地址存在,因为关联是强制性的。所以它直接用代理填充地址字段,知道有一个地址引用这个人。

于 2013-08-01T07:29:52.090 回答
12

最简单的一种是伪造一对多的关系。这将起作用,因为集合的延迟加载比单个可空属性的延迟加载要容易得多,但是如果您使用复杂的 JPQL/HQL 查询,通常这种解决方案非常不方便。

另一种是使用构建时字节码检测。有关更多详细信息,请阅读 Hibernate 文档:19.1.7。使用惰性属性获取。请记住,在这种情况下,您必须为@LazyToOne(LazyToOneOption.NO_PROXY)一对一关系添加注释以使其变得懒惰。将 fetch 设置为 LAZY 是不够的。

最后一个解决方案是使用运行时字节码检测,但它仅适用于在成熟的 JEE 环境中使用 Hibernate 作为 JPA 提供程序的人(在这种情况下,将“ hibernate.ejb.use_class_enhancer”设置为 true 应该可以解决问题:实体管理器配置)或将 Hibernate 与Spring 配置为执行运行时编织(这在某些较旧的应用程序服务器上可能难以实现)。在这种情况下@LazyToOne(LazyToOneOption.NO_PROXY),还需要注释。

于 2016-04-11T05:22:04.407 回答