我正在使用Hibernate 3编写Web应用程序。
所以,过了一会儿我注意到事情很慢。所以我测试了hibernate profiler,发现hibernate会为简单的操作做出无理的多次db调用。原因是我加载一个Object(这个对象有几个“父母”),这些“父母”有其他“父母”。所以基本上hibernate会加载它们,即使我只需要基本对象。 好的,所以我看着懒加载。这导致我进入Lazyloading-exception,因为我有一个MVC webapp。
所以现在我对我最好的方法有点困惑。 基本上我只需要更新对象上的单个字段。我已经拥有了对象密钥。
我应该: 1.挖掘懒惰负载。然后重写我的应用程序以获得开放会话视图? 2.挖掘延迟加载。然后重写我的dao更具体。例如。编写DAO方法,这些方法将返回仅与每个用例所必需的内容相关联的对象?可能是很多额外的方法...... 3.刮擦休眠并自己动手做? 4.现在不能想到其他解决方案。有什么建议吗?
最佳做法是什么?
答案 0 :(得分:26)
如果可能,请使用load()方法,因为在需要之前它不会发出选择查询。例如。如果你有一本书和一个作者,并且你想将它们关联在一起,这将不会发出任何选择,只有一个插入:
Book b = (Book) session.load(Book.class, bookId); Author a = (Author) session.load(Author.class, authorId); b.setAuthor(a); session.save(b);
使用命名查询(在您的hbm文件或@NamedQuery中),以便在每次查询期间不解析它们。在需要之前不要使用Criteria API(在这种情况下无法使用PreparedStatement缓存)
session.setReadOnly(object, true)
。这将使Hibernate不在持久化上下文中保留所选实体的原始快照,以进行进一步的脏检查。c3p0.max_statements
以启用池中的PreparedStatment缓存,并在默认情况下关闭数据库时启用数据库的语句缓存。setMaxResults()
,setFirstResult()
)以及包含联接到集合的查询,这将导致从数据库中提取的所有记录和分页将由Hibernate在内存中发生。如果你想分页,理想情况下你不应该使用连接。如果你再也无法逃避它 - 请使用批量提取。实际上有很多技巧,但我现在想不起更多。
答案 1 :(得分:5)
正如我在this article或我的High-Performance JavaPersistence book中所解释的那样,您可以采取许多措施来加速Hibernate的性能,例如:
@OneToMany
instead of unidirectional one,使用@MapsId
for @OneToOne
,using Set
for @ManyToMany
答案 2 :(得分:1)
我相信您要查看此section in the Hibernate manual。
我希望您的原始问题“......无理的多次db调用...”是他们称之为“N + 1选择问题”的实例。如果是这样,他们就可以选择如何处理它。
可以在关联级别指定前两个,并且可以在查询级别覆盖提取类型。您应该能够让您的查询只执行您需要的操作,而不是更多,并使用这些工具进行“良好”的SQL查询。