我有一个简单的Hibernate查询,如:
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完成这个冲洗吗?
如果没有,我该怎么做才能让它更快?
答案 0 :(得分:13)
默认情况下,hibernate会在会话期间发出查询(FlushMode.AUTO)之前刷新,并且会占用大量的CPU时间。如果您的会话中交替运行许多查询和更新,则会特别痛苦。
如果查询可能选择在当前会话期间插入/更新/删除的后退数据,则需要这些刷新。即使您没有修改当前事务中的任何内容,但使用的是事务隔离级别(如read-uncommitted),也可能出现 。
假设您不想要未提交的读取等,我知道有两种解决方法:
如果您确定选择了此会话中尚未修改的数据,则可以将flush-mode明确设置为不会触发刷新的内容,如下所示:
Query query = session.getNamedQuery(SOME_QUERY_NAME);
query.setFlushMode(FlushMode.COMMIT);
答案 1 :(得分:-1)
Hibernate 在 3.3 版本中改变了它的刷新逻辑。
现在它会一直刷新,即使设置为 FlushMode.MANUAL
,如果它检测到您正在查询一个有脏实体的表。
我能想到的一些解决方法:
FlushMode.COMMIT
或更低。AutoFlushEventListener
。这将需要一些低级别的摆弄,并且可能会破坏其他东西。