我们如何使用 JPA 和 Hibernate 设置 Read Uncommitted 隔离级别?

How can we set the Read Uncommitted isolation level with JPA and Hibernate?

在他的名著《Java persistence with Hibernate》中我们可以读到以下内容:

“持久上下文是持久实体实例的缓存....自动脏检查是这种缓存的好处之一。另一个好处是实体的可重复读取和工作范围缓存单元...您无需执行任何特殊操作即可启用持久性上下文缓存。它始终处于打开状态,并且由于所示原因无法关闭.

这是否意味着 Hibernate 永远无法达到“Read uncommitted”事务隔离级别?

事实上,正如书中引用的那样,hibernate 确实通过其一级缓存(持久性上下文)提供可重复读取

"Transactions and concurrency control" by Vlad Mihalcea.

如下:

一些 ORM 框架(例如 JPA/Hibernate)提供应用程序级可重复读取。任何检索到的实体的第一个快照都缓存在当前 运行 持久性上下文中。返回相同数据库行的任何连续查询都将使用先前缓存的完全相同的对象。这样,即使在 Read Committed 隔离级别也可以防止模糊读取。

但是,根据上面的同一本书,似乎使用 Spring 和 JPA / hibernate 允许自定义事务隔离级别。

在上面的书中我们还可以阅读以下内容:

Spring 在使用 JpaTransactionManager 时支持事务级隔离级别。对于 JTA 事务,JtaTransactionManager 遵循 Java EE 标准并且不允许覆盖默认隔离级别。作为解决方法,Spring 框架提供了扩展点,因此应用程序开发人员可以自定义默认行为并实现一个 基于事务设置隔离级别的机制.

Does this mean that one can never achieve a transaction isolation level "Read uncommitted" with Hibernate?

不,不是。 Hibernate 提供适用于任何查询的 application-level repeatable reads for entities. That's different than DB-level repeatable reads

因此,如果您想要一个自定义隔离级别,例如 REPEATABLE_READ 用于给定事务执行的所有查询,而不仅仅是用于获取实体,那么您可以这样设置:

@Transactional(isolation = Isolation.REPEATABLE_READ)
public void orderProduct(Long productId) {  
    ...
}     

现在,您的问题标题是:

(How) can we achieve isolation level Read Uncommitted with Hibernate / JPA?

如果您使用的是 Oracle 和 PostgreSQL,则不能这样做,因为 Read Uncommitted 不受支持,您将得到 READ_COMMITTED

对于SQL服务器和MySQL,设置如下:

@Transactional(isolation = Isolation.READ_UNCOMMITTED)