@Transactional(readOnly = true)vs @QueryHints

时间:2017-01-21 15:14:42

标签: hibernate transactions repository spring-data

我有一个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和具体的休眠提示 可以正常工作。现在我想知道为什么。 @Transactional(readOnly=true)不应该有同样的效果吗?

1 个答案:

答案 0 :(得分:0)

如果我们想坚持非供应商特定的方式,那么我会尝试:

选项1

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
Account findByUsername(String username);

这里我们在任何事务之外运行查询,因此不会影响持久化上下文的现有状态。如果这种情况适合这种配置,请考虑好。

选项2

我假设您在查询用户之前在当前事务中进行了一些其他修改。我建议然后设置刷新模式以提交您的查询(或实体管理器):

EntityManager em;
Account findByUsername(String username){
   em.setFlushMode(FlushModeType.COMMIT);

  // perform the query
}

OR

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"/>

现在,当您无法访问实体管理器并手动设置刷新模式时,可以使用此功能。