Hibernate.initialize()的工作原理
我知道在会话之外使用延迟加载对象/集合,我们执行Hibernate.initialize(Object obj)
以便初始化作为参数传递给initialize()方法的对象,并且可以在会话范围之外使用。
但我无法理解这是如何工作的。 我的意思是,如果我们这样做,那么我们最终会有急切的提取,所以为什么我们在配置中做了懒惰,最终在运行时进行了急切的提取。
换句话说,我想知道使用Hibernate.initialize()
和eagerly
加载该对象之间的区别。
我弄错了还是错过了什么?
不同之处在于应用范围。
使集合关联变得懒惰的原因是,如果您不真正需要它,则每次加载父对象时都要避免加载集合。
如果您正在懒惰加载集合,但是对于特定用途,您需要确保在会话关闭之前已加载集合,您可以使用Hibernate.initialize(Object obj)
。
如果你实际上总是需要加载集合,你应该确实加载它。 但在大多数软件中,情况并非如此。
请考虑以下示例:
我有一个实体LoanApplication(在这种情况下是一个非常重的对象),它内部有各种字段(也可能很大)。 例如,考虑LoanApplication中的SubLoan字段。
@OneToMany(fetch = FetchType.LAZY) @JoinColumn(name = "application_fk") @Index(name = "appl_fk_idx_subloansLoanApp") private Set subLoans;
在此示例中,FetchType为LAZY。 现在,如果在执行某些操作时某些控制器的方法中遇到LoanApplication,则除非您希望使用它,否则subLoans集最初将为null。 在这种情况下,你使用Hibernate.initialize如下:
Hibernate.initialize(loanApplication.getSubLoans());
这有助于主要提高性能,因为每次检索LoanApplication时,除非您真的需要,否则大量对象即’subLoan’最初将为空。
考虑一下@Don Ruby的回答
下一个区别是Hibernate.initialize
生成并执行其他sql以获取数据。 因此,您可以在会话结束后使用它。 当您在实体中使用Eager
fetch时,它总是在数据库中查找数据(在连接会话下)时获取该集合,而不是在它之后。
实际上,如果你使用EAGER,当你有大量的collections时,它确实会影响你的表现。 因此,在使用Hibernate.initialize
这样的情况下,这是一个好主意。
看看这个: Hibernate Lazy Fetch vs Eager Fetch Type
考虑你有一个表可能与其他4个表有关系。 在这种情况下,如果您使用eager,那么将在每次获取操作中获取所有四个相关表中的所有对应关系。
但是考虑到您可能需要相关表中只有一个表的数据,因此在这种情况下,您只能获取所需的关系,而不是使用Hibernate.initialize工具提取整个四个相关表的数据。 。