我多次听说过hibernate中出现了几个问题(特别是在使用延迟加载时)。哪些是最常见的,可以做些什么呢?
答案 0 :(得分:9)
最常见的可能是n+1 select problem,当延迟加载集合导致使用n + 1个单独的查询而不是单个连接查询命中数据库时。
解决这些问题的方法是常识:-)我认为all relevant sources(首先是Hibernate reference)广泛讨论这个(和其他相关的)问题,以及决议和解决方法。简而言之,您不应盲目地从食谱中复制食谱 - 衡量代码的性能并相应地进行调整。如果您看到发出的选择太多,则可以有选择地从延迟加载切换到该特定属性/类/查询的加入或子选择提取策略。 (请注意,这两者都有其潜在的缺点,因此,性能测量也是关键。)
当客户端代码依赖于实体/属性的实际类型时(例如,通过使用instanceof
进行测试),会出现一个不同的,更加罕见的问题。如果遇到代理对象,这样的代码会中断不是它所代表的具体类的实例。但是,无论如何编写这样的代码并不是最好的想法,并且它很少是必要的。但是,有时它会继承遗留代码,从而导致冲突,可能是难以解决。
答案 1 :(得分:1)
首先,EAGER fetching is a much bigger problem。懒惰提取是一种可行的方法,因为它允许您根据需要获取尽可能多的信息。
如果您在LazyInitializationException
打开时未初始化延迟关联,并且您尝试在持久性上下文后导航未初始化的代理/集合,则唯一的问题是Session
已关闭。
对于eager(当你执行不明确获取所有渴望关联的JPQL查询)和延迟关联时,都会出现N + 1查询问题,并且解决方案与{{1}相同}。
但是,您可以在测试期间自动检测所有N + 1查询问题。看看这个datasource-proxy based utility for more details on this topic。
答案 2 :(得分:0)
HQL的提取策略可用于故意指定需要加载的内容。例如(来自Hibernate Reference):
from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens
不幸的是,Hibernate不支持SQL的所有标准选择功能作为HQL的一部分,这取决于项目要求,可能会令人望而却步。例如,从选择中选择是不可能的,但经常需要创建报告或执行数据分析。
这可以通过Hibernate执行SQL的能力来克服。但是,这种方法不能提供面向对象的HQL优点(例如,所有连接都必须手动制作)。