在我们正在开发的这个应用程序中,我们注意到一个视图特别慢。我对视图进行了分析,并注意到hibernate执行的一个查询花费了10秒,即使数据库中只有两个对象需要获取。所有“一对多”和“多对多”关系都是懒惰的,所以这不是问题所在。在检查实际执行的SQL时,我注意到查询中有超过80个连接。

进一步检查这个问题,我注意到这个问题是由实体类之间一对一和多对一关系的深层层次结构引起的。所以,我想,我只要把它们设为lazy,就能解决问题了。但是注释@OneToOne(fetch=FetchType.LAZY)或@ManyToOne(fetch=FetchType.LAZY)似乎都不起作用。要么我得到一个异常,要么它们实际上没有被代理对象替换,从而变得懒惰。

你知道我要怎么做吗?注意,我没有使用persistence.xml来定义关系或配置细节,一切都是在java代码中完成的。


当前回答

如果关系必须不是双向的,那么@ElementCollection可能比使用惰性的One2Many集合更容易。

其他回答

As already perfectly explained by ChssPly76, Hibernate's proxies don't help with unconstrained (nullable) one-to-one associations, BUT there is a trick explained here to avoid to set up instrumentation. The idea is to fool Hibernate that the entity class which we want to use has been already instrumented: you instrument it manually in the source code. It's easy! I've implemented it with CGLib as bytecode provider and it works (ensure that you configure lazy="no-proxy" and fetch="select", not "join", in your HBM).

我认为这是真正的(我是说自动的)插装的一个很好的替代方案,当您只有一个一对一的可空关系时,您想让它变得懒惰。主要的缺点是这个解决方案依赖于你正在使用的字节码提供程序,所以准确地注释你的类,因为你将来可能不得不改变字节码提供程序;当然,您还因为技术原因修改了您的模型bean,这是不好的。

对于Kotlin开发者:为了允许Hibernate继承你想要惰性加载的@Entity类型,它们必须是可继承/开放的,而在Kotlin中它们默认不是这样的。为了解决这个问题,我们可以使用完全开放的编译器插件,并通过添加到我们的build.gradle来指导它处理JPA注释:

allOpen {
   annotation("javax.persistence.Entity")
   annotation("javax.persistence.MappedSuperclass")
   annotation("javax.persistence.Embeddable")
}

如果你像我一样使用Kotlin和Spring,你很可能也在使用Kotlin -jpa/no-args和Kotlin - Spring /all-open编译器插件。但是,您仍然需要添加上面的代码行,因为插件的组合不会打开这样的类。

阅读Léo Millon的文章,了解更多的解释。

Hibernate中xtoone的基本思想是它们在大多数情况下都不是懒惰的。

一个原因是,当Hibernate必须决定放置一个代理(带id)或null时, 无论如何,它都必须查看另一个表才能加入。访问数据库中另一个表的代价是巨大的,所以它最好在那个时刻为那个表获取数据(非懒惰行为),而不是在以后的请求中获取数据,这将需要对同一个表进行第二次访问。

编辑:具体请参考ChssPly76的回答。这一个不那么准确和详细,它没有提供任何东西。谢谢ChssPly76。

如果关系必须不是双向的,那么@ElementCollection可能比使用惰性的One2Many集合更容易。

在原生Hibernate XML映射中,可以通过将受约束的属性设置为true来声明一个一对一的映射来实现这一点。我不确定Hibernate/JPA注释等价于它是什么,快速搜索文档也没有提供答案,但希望这能给您一个线索。