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