java 使用hibernate延迟加载的主要问题是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4713563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are the main problems when using hibernate lazy loading?
提问by Denys S.
I've heard several times that several problems arise in hibernate (especially when using lazy loading). Which are the most common and what can be done about them?
我曾多次听说 hibernate 中出现了几个问题(尤其是在使用延迟加载时)。哪些是最常见的,可以采取哪些措施?
回答by Péter T?r?k
The most common probably is the n+1 select problem, when lazy loading of a collection results in hitting the DB with n+1 separate queries instead of a single join query.
最常见的可能是n+1 选择问题,当一个集合的延迟加载导致使用 n+1 个单独的查询而不是单个连接查询访问数据库时。
The antidote to such issues is common sense :-) I believe that all relevant sources(first and foremost the Hibernate reference) discuss this (and other related) issues extensively, together with resolutions and workarounds. In brief, you should not copy recipes blindly from the cookbook - measure the performance of your code and tune it accordingly. If you see too many selects issued, you can selectively switch from lazy loading to join or subselect fetching strategy for that specific property/class/query. (Note that both of these have their own potential drawbacks, so again, performance measurement is key.)
解决此类问题的方法是常识:-) 我相信所有相关来源(首先是Hibernate 参考资料)都广泛讨论了这个(和其他相关)问题,以及解决方案和解决方法。简而言之,您不应该盲目地从食谱中复制食谱 - 测量代码的性能并相应地对其进行调整。如果您看到发出的选择过多,您可以有选择地从延迟加载切换到该特定属性/类/查询的连接或子选择获取策略。(请注意,这两者都有其潜在的缺点,因此再次强调,性能测量是关键。)
A different, albet much rarer, problem arises when the client code depends on the actual type of an entity/property (e.g. by testing it with instanceof
. Such code breaks if it encounters a proxy object, which is not an instance of the concrete class it stands for. However, it is not the best idea to write such code anyway, and it should very rarely be necessary. However, sometimes it is inherited with legacy code, thus causing a conflict which may be difficult to work around.
当客户端代码依赖于实体/属性的实际类型时,会出现一个不同的,尽管更为罕见的问题(例如,通过使用instanceof
.代表。然而,无论如何编写这样的代码并不是最好的主意,而且很少有必要这样做。但是,有时它会被遗留代码继承,从而导致可能难以解决的冲突。
回答by Vlad Mihalcea
First of all, EAGER fetching is a much bigger problem. Lazy fetching is the way to go since it allows you to fetch just as much info as you need.
首先,EAGER fetching 是一个更大的问题。延迟获取是一种可行的方法,因为它允许您获取所需的尽可能多的信息。
The only problem you can have is LazyInitializationException
if you don't initialize the lazy associations while the Session
is open, and you attempt to navigate an uninitialized Proxy/Collection after the Persistence Context is closed.
您可能遇到的唯一问题是,LazyInitializationException
如果您没有在Session
打开时初始化惰性关联,并且在持久性上下文关闭后尝试导航未初始化的代理/集合。
The N+1 query problem can arise for both eager (when you execute a JPQL query that doesn't explicitly fetch all the eager associations) and lazy associations, and the solution is the same as with LazyInitializationException
.
N+1 查询问题可能出现在 Eager(当您执行未显式获取所有 Eager 关联的 JPQL 查询时)和惰性关联时,解决方案与LazyInitializationException
.
However, you can detect all N+1 query issues automatically during testing. Check out this datasource-proxy based utility for more details on this topic.
但是,您可以在测试期间自动检测所有 N+1 查询问题。查看此基于数据源代理的实用程序,了解有关此主题的更多详细信息。
回答by 01es
The fetch strategy of HQL can be used to deliberately specify what needs to be loaded. For example (from Hibernate Reference):
HQL 的 fetch 策略可以用来刻意指定需要加载的内容。例如(来自Hibernate 参考):
from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens
from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens
Unfortunately, Hibernate does not support all standard select capabilities of SQL as part of HQL, which depending on the project requirements, could be prohibitive. For example, select from select is not possible, but is frequently required for creating reports or performing data analysis.
不幸的是,Hibernate 不支持 SQL 的所有标准选择功能作为 HQL 的一部分,这取决于项目要求,可能会令人望而却步。例如,select from select 是不可能的,但创建报告或执行数据分析经常需要它。
This can be overcome by Hibernate's capability of executing SQL. However, this approach does not provide object-oriented goodness of HQL (e.g. all joins have to be crafted manually).
这可以通过 Hibernate 执行 SQL 的能力来克服。然而,这种方法没有提供 HQL 的面向对象的优点(例如,所有连接都必须手动制作)。