我有一个 Spring Data JPA Repository,方法如下:
//@QueryHints({ @QueryHint(name = "org.hibernate.readOnly", value = "true") })
@Transactional(readOnly = true)
Account findByUsername(String username);
当 Account
变脏时,hibernate 会在调用此方法时尝试刷新它——这是我不希望的。我认为将它设置为 @Transactional(readOnly = true)
可以帮助解决这个问题,但事实并非如此。有趣的是,将@QueryHints
与具体的 hibernate 提示一起使用确实 有效。现在我想知道为什么。 @Transactional(readOnly=true)
不应该有同样的效果吗?
最佳答案
如果我们想坚持使用非供应商特定的方式,那么我会尝试:
选项 1
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
Account findByUsername(String username);
这里我们确实在任何事务之外运行查询,因此不会影响持久性上下文的现有状态。好好想想这个案例是否适合这个配置。
选项 2
我假设您在查询用户之前正在对当前事务进行一些其他修改。我建议然后设置刷新模式以提交您的查询(或实体管理器):
EntityManager em;
Account findByUsername(String username){
em.setFlushMode(FlushModeType.COMMIT);
// perform the query
}
或
EntityManager em;
Account findByUsername(String username){
Query query = em.createQuery(..);
query.setFlushMode(FlushModeType.COMMIT);
// perform the query
}
COMMIT 刷新模式告诉持久化提供者查询不会与持久化上下文中的更改数据重叠,因此它不需要做任何事情来获得正确的结果。
在查询本身上设置刷新模式是一种可取的方法。
更新:选项 3
作为最后的手段,您可以在核心配置本身上进行设置:
<property name="org.hibernate.flushMode" value="COMMIT"/>
现在这是在您无法访问实体管理器并手动设置刷新模式时使用。
关于java - @Transactional(readOnly=true) 与@QueryHints,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41780964/