[英]Hibernate Performance Best Practice?
Im writing a Web application using Hibernate 3.我使用 Hibernate 3 编写 Web 应用程序。
So, after a while i noticed that something was slow.所以,过了一会儿,我注意到有些东西很慢。 So i tested hibernate profiler and found that hibernate will make unreasonably many db-calls for simple operation.所以我测试了 hibernate profiler,发现 hibernate 会为简单的操作进行不合理的多次数据库调用。 The reason is ofcourse that i load an Object (this object has several "parents") and these "parents" have other "parents".原因当然是我加载了一个对象(这个对象有几个“父母”),而这些“父母”还有其他“父母”。 So basicly hibernate loads them all, even though i just need the basic object.所以基本上休眠加载它们,即使我只需要基本对象。 Ok, so i looked into lazy-loading.好的,所以我研究了延迟加载。 Which lead me into the Lazyloading-exception, because i have a MVC webapp.这让我进入了 Lazyloading-exception,因为我有一个 MVC webapp。
So now i'm a bit confused as to what is my best approach to this.所以现在我有点困惑我最好的方法是什么。 Basicly all I need is to update a single field on an object.基本上我需要的只是更新对象上的单个字段。 I already have the object-key.我已经有了对象键。
Should I: 1. Dig into Lazy-loading.我应该: 1. 深入研究延迟加载。 And then rewrite my app for a open-session-view?然后重写我的应用程序以打开会话视图? 2. Dig into lazy-loading. 2. 深入研究延迟加载。 And then rewrite my dao's to be more specific.然后将我的 dao 重写为更具体。 Eg writing DAO-methods that will return objects instanciated with only whats necessary for each use-case?例如,编写将返回实例化的对象的 DAO 方法,这些对象仅具有每个用例所需的内容? Could be a lot of extra methods... 3. Scratch hibernate and do it myself?可能有很多额外的方法... 3.从头开始休眠并自己做? 4. Cant really think of other solutions right now. 4.现在真的想不出其他解决方案。 Any suggestions?有什么建议么?
What is the best practice?最佳做法是什么?
Use load() method if it's possible since it doesn't issue a select query until it's required.如果可能,请使用 load() 方法,因为它在需要之前不会发出选择查询。 Eg if you have a Book and an Author and you want to associate them together, this will won't issue any selects, only single insert:例如,如果您有 Book 和 Author 并且您想将它们关联在一起,则不会发出任何选择,只会发出单个插入:
Book b = (Book) session.load(Book.class, bookId); Author a = (Author) session.load(Author.class, authorId); b.setAuthor(a); session.save(b);
Use named queries (in your hbm files or in @NamedQuery) so that they are not parsed during each query.使用命名查询(在您的 hbm 文件或 @NamedQuery 中),以便在每次查询期间不会解析它们。 Don't use Criteria API until it's required (it makes impossible to use PreparedStatement cache in this case)在需要之前不要使用 Criteria API(在这种情况下不可能使用 PreparedStatement 缓存)
session.setReadOnly(object, true)
.对仅选择使用只读模式: session.setReadOnly(object, true)
。 This will make Hibernate not to keep an original snapshot of the selected entity in the persistent context for further dirty checks.这将使 Hibernate 不会在持久上下文中保留所选实体的原始快照以进行进一步的脏检查。c3p0.max_statements
in order to enable PreparedStatment cache in the pool and enable the statement cache of your DB if it's switched off by default.设置c3p0.max_statements
以启用池中的 PreparedStatment 缓存,并在默认情况下关闭数据库的语句缓存时启用它。setMaxResults()
, setFirstResult()
) along with queries that contain joins to collections, this will result in all the records pulled from database and pagination will happen in memory by Hibernate.不要将分页( setMaxResults()
、 setFirstResult()
)与包含连接到集合的查询一起使用,这将导致从数据库中提取所有记录,并且 Hibernate 将在内存中进行分页。 If you want pagination, ideally you shouldn't use joins.如果你想要分页,理想情况下你不应该使用连接。 If you can't escape it, again - use batch fetching.如果你不能逃脱它,再次 - 使用批量提取。Actually there are a lot of tricks, but I can't recall more at the moment.其实有很多技巧,但一时想不起来了。
There are many things you can do to speed-up Hibernate performance, like:你可以做很多事情来加速 Hibernate 的性能,比如:
@OneToMany
instead of unidirectional one, using @MapsId
for @OneToOne
, using Set
for @ManyToMany
使用正确的关系:双向@OneToMany
而不是单向关系,对@OneToOne
使用@MapsId
,对@ManyToMany
使用Set
I believe you want to review this section in the Hibernate manual .我相信您想查看Hibernate 手册中的这一部分。
I expect that your original problem of "...unreasonably many db-calls..." is an instance of what they call the "N+1 selects problem".我希望您的原始问题“......不合理的许多 db-calls......”是他们所谓的“N+1 选择问题”的一个实例。 If so, they've got options on how to deal with it.如果是这样,他们可以选择如何处理。
The first two can be specified at the association level, and fetch type can be overridden at the query level.前两个可以在关联级别指定,获取类型可以在查询级别覆盖。 You should be able to get your query to do only what you need, no more, and do it with a 'good' SQL query with these tools.您应该能够让您的查询仅执行您需要的操作,而不是更多,并使用这些工具通过“良好”的 SQL 查询来执行此操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.