java - @Transactional(readOnly=true) 与@QueryHints

标签 java hibernate transactions spring-data repository

我有一个 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/

相关文章:

java - DatePickerDialog Holo 样式在 Android 7 Nougat 上失败

Hibernate 花费太多时间并执行一些神秘的操作..

java - Hibernate 的恶作剧——我只想要一个非托管副本

sql-server - 无法在快照隔离模式下使用 READPAST

ruby-on-rails - 如何在并行多进程 block 中使用 ActiveRecord 事务?

使用插入忽略(或类似)和唯一 ID 进行 MySQL 事务处理

Java Sockets Eclipse 空白错误弹出窗口

java - 如何测试运行一个非主方法? [Java、IntelliJ]

java - 使用 HTTP 请求下载文件的一部分

java - 如何实现对简单对象集合的排序?