Hibernate性能最佳实践? [英] Hibernate Performance Best Practice?

查看:93
本文介绍了Hibernate性能最佳实践?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Hibernate 3编写Web应用程序。

因此,过了一段时间,我发现有些东西很慢。所以我测试了hibernate profiler,发现hibernate会为简单操作做出不合理的多个db调用。原因是我加载一个对象(这个对象有几个父母),这些父母有其他父母。所以基本上hibernate加载它们,即使我只需要基本对象。
好​​吧,所以我看着懒加载。这导致我进入Lazyloading-exception,因为我有一个MVC webapp。



所以现在我对我最好的方法是什么感到困惑。
基本上我需要的是更新对象上的单个字段。我已经有了对象键。



我应该:
1.挖掘延迟加载。然后重写我的应用程序以获得开放会话视图?
2.挖掘延迟加载。然后重写我的道是更具体。例如。编写DAO方法,这些方法只返回每个用例所需的对象的实例?可能是很多额外的方法...
3.从头开始休眠并自己做?
4.现在无法真正想到其他解决方案。有什么建议?



最佳做法是什么?

解决方案


  • 除非确实需要,否则不要使用连接。他们不会允许您使用延迟加载,也不使用二级缓存进行关联。

  • 对于大集合使用lazy =extra,它不会检索所有元素,直到您问一下,你也可以使用size()方法来实例化,而不需要从DB获取元素
  • 如果可能的话,使用load()方法,因为它不会发出select查询这是必需的。例如。如果你有一本书和一个作者,并且你想将它们联系在一起,这将不会发出任何选择,只有一个插入:


      Book b =(Book)session.load(Book.class,bookId); 
    作者a =(作者)session.load(Author.class,authorId);
    b.setAuthor(a);
    session.save(b);



  • 使用命名查询(在您的hbm文件或@NamedQuery),以便在每个查询期间不会分析它们。在这种情况下不要使用Criteria API(在这种情况下无法使用PreparedStatement缓存)

  • 在您的web应用程序中使用OSIV,因为它只会在/如果需要的话
  • 使用只读模式进行只选择: session.setReadOnly(object,true)。这将使Hibernate不会在持久性上下文中保留所选实体的原始快照以进行进一步的脏检查。
  • 用户第二级缓存和查询缓存用于读取主要数据和只读数据。

  • 使用FlushMode.COMMIT而不是AUTO,这样Hibernate在更新之前不会发出select,但要准备好这可能会导致陈旧的数据被写入(尽管乐观锁定可以帮助您)。
  • 查看批量抓取(批量大小),以便一次选择多个实体/集合,而不是为每个实体/集合分别查询。

  • 执行查询,如'从实体中选择新的实体(id,someField)'以便只检索必需的字段。查看结果转换器。

  • 如果需要,使用批处理操作(如删除)如果您使用本机查询,请明确指定哪些缓存区应该无效(默认情况下为全部)。
  • 查看物化路径和树状结构的嵌套集。
  • 设置 c3p0.max_statements ,以便启用池中的PreparedStatment缓存并启用数据库的语句缓存(如果默认关闭)。
  • 使用StatelessSession如果可能的话,它会克服脏检查,级联,拦截等。
  • 不要使用分页( setMaxResults() setFirstResult())以及包含集合连接的查询,这将导致从数据库中提取所有记录,并且分页将由Hibernate在内存中发生。如果你想分页,理想情况下你不应该使用连接。如果你不能逃避它 - 再次使用批量抓取。



其实有很多技巧,但是我不能现在回忆更多。


Im writing a Web application using Hibernate 3.

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. 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.

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. And then rewrite my app for a open-session-view? 2. Dig into lazy-loading. And then rewrite my dao's to be more specific. E.g. writing DAO-methods that will return objects instanciated with only whats necessary for each use-case? Could be a lot of extra methods... 3. Scratch hibernate and do it myself? 4. Cant really think of other solutions right now. Any suggestions?

What is the best practice?

解决方案

  • Don't use joins unless really needed. They won't allow you to use neither lazy loading, nor using 2nd level cache for associations
  • Use lazy="extra" for large collections, it won't retrieve all the elements until you ask it, you can also use size() method for instance without getting elements from DB
  • Use load() method if it's possible since it doesn't issue a select query until it's required. E.g. 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 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. Don't use Criteria API until it's required (it makes impossible to use PreparedStatement cache in this case)

  • Use OSIV in your web app since it will load data only when/if it's needed
  • Use read-only modes for selects-only: 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.
  • User 2nd level cache and Query Cache for read-mostly and read-only data.
  • Use FlushMode.COMMIT instead of AUTO so that Hibernate doesn't issue select before updates, but be ready that this may lead to stale data being written (though Optimistic Locking can help you out).
  • Take a look at batch fetching (batch-size) in order to select several entities/collections at one time instead of issuing separate queries for each one.
  • Do queries like 'select new Entity(id, someField) from Entity' in order to retrieve only required fields. Take a look at result transformers.
  • Use batch operations (like delete) if needed
  • If you use native queries, specify explicitly what cache regions should be invalidated (by default - all).
  • Take a look at materialized path and nested sets for tree-like structures.
  • Set 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.
  • Use StatelessSession if it's possible, it overcomes dirty checks, cascading, interceptors, etc.
  • Do not use pagination (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. 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.

这篇关于Hibernate性能最佳实践?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆