11

我有一个简单的休眠查询,例如:

from MyEntity where name = ?

没什么花哨的,但它在相当大的事务中被多次调用(持续一秒钟,可能加载数十或数百个实体)。Profiler 显示大量时间花在:

org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1185)
org.hibernate.internal.SessionImpl.list(SessionImpl.java:1240)
org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)

换句话说 - 在运行实际查询之前刷新更改。

我可以以某种方式阻止 Hibernate 执行此刷新吗?

如果没有,我该怎么做才能让它更快?

4

2 回答 2

18

默认情况下,hibernate 在会话期间发出查询之前会刷新(FlushMode.AUTO),并且会占用大量 CPU 时间。如果您有一个会话,其中许多查询和更新交替运行,那就特别痛苦。

如果查询可能会选择您在当前会话期间插入/更新/删除的数据,那么您需要这些刷新。即使您没有修改当前事务中的任何内容,但使用了诸如未提交的事务隔离级别,也可能出现这种情况。

假设您不想要未提交的读取等,我知道有两种解决方法:

  1. 在进行任何修改之前选择您在会话期间需要的所有内容(即重新排序,以便在进行任何修改之前发出所有查询)。
  2. 如果您确定要选择在此会话中未修改的数据,则可以将刷新模式显式设置为不会触发刷新的内容,如下所示:

    Query query = session.getNamedQuery(SOME_QUERY_NAME);
    query.setFlushMode(FlushMode.COMMIT);
    
于 2013-01-22T08:30:29.567 回答
-1

Hibernate 在 3.3 版本中改变了它的刷新逻辑。

现在它会一直刷新,即使设置为FlushMode.MANUAL,如果它检测到您正在查询有脏实体的表。

我能想到的一些解决方法:

  • 重新排序操作以不查询脏表并设置FlushMode.COMMIT或降低。
  • 在修改之前分离实体并稍后重新附加,这样 Hibernate 就不会知道它们已被更改。
  • 提供AutoFlushEventListener具有不同行为的自定义。这将需要一些低级的摆弄,并且可能会破坏其他东西。
于 2021-05-07T11:13:17.343 回答