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

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

问题描述

我正在使用 Hibernate 3 编写 Web 应用程序.

所以,过了一会儿,我注意到有些东西很慢.所以我测试了 hibernate profiler,发现 hibernate 会为简单的操作进行不合理的多次数据库调用.原因当然是我加载了一个对象(这个对象有几个父母"),而这些父母"还有其他的父母".所以基本上休眠加载它们,即使我只需要基本对象.好的,所以我研究了延迟加载.这让我进入了 Lazyloading-exception,因为我有一个 MVC webapp.

所以现在我有点困惑我对此的最佳方法是什么.基本上我需要的只是更新对象上的单个字段.我已经有了对象键.

我应该:1. 深入研究延迟加载.然后重写我的应用程序以打开会话视图?2. 深入研究延迟加载.然后将我的 dao 重写为更具体.例如.编写将返回实例化的对象的 DAO 方法,这些对象仅具有每个用例所需的内容?可能有很多额外的方法......3.从头开始休眠并自己做?4.现在真的想不出其他解决方案.有什么建议吗?

最佳实践是什么?

解决方案

  • 除非确实需要,否则不要使用连接.它们不允许您既不使用延迟加载,也不使用二级缓存进行关联
  • 对于大型集合使用 lazy="extra",它不会在您询问之前检索所有元素,例如您也可以使用 size() 方法而无需从 DB 获取元素
  • 如果可能,请使用 load() 方法,因为它在需要之前不会发出选择查询.例如.如果您有 Book 和 Author 并且您想将它们关联在一起,则不会发出任何选择,只会发出单个插入:

    <块引用>

    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 缓存)

  • 在您的网络应用程序中使用 OSIV,因为它只会在需要时/如果需要时加载数据
  • 对仅选择使用只读模式:session.setReadOnly(object, true).这将使 Hibernate 不会在持久上下文中保留所选实体的原始快照以进行进一步的脏检查.
  • 用户二级缓存和查询缓存,主要用于读取和只读数据.
  • 使用 FlushMode.COMMIT 而不是 AUTO,这样 Hibernate 就不会在更新之前发出选择,但要准备好这可能会导致写入过时的数据(尽管乐观锁定可以帮助您).
  • 看看批量提取(批量大小),以便一次选择多个实体/集合,而不是为每个实体/集合发出单独的查询.
  • 执行诸如从实体中选择新实体(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天全站免登陆