按请求可变事务隔离级别

我正在编写一个小的拍卖应用程序,确定地记录我的出价非常重要。毕竟,拍卖的最后几秒钟是买家的关键时刻,我不能让他们同时竞标和竞争条件。

当然,这就是事务隔离的用途。我可以将隔离级别设置为可序列化,并且我们都已设置完毕。

但是所有其他请求呢?如果人们正在查看配置文件或发送消息,则这些请求不需要接近这种事务隔离。对于这些请求,读取提交的隔离级别是完全可以接受的。

我正在将我的事务级别设置为我的休眠属性的一部分,但我真的希望能够执行类似每个请求之类的操作。hibernate.connection.isolationsession.setTransactionIsolation(newIsolation)


答案 1

如果你正在使用Spring,你可以使用这样的东西:

@Transactional(isolation = Isolation.SERIALIZABLE)

它适用于JpaTransactionManager。如果您使用的是 JtaTransactionManager,则不会传播请求范围的事务隔离,因为这是缺省的 JTA 行为。

由于 JTA 不支持事务范围的隔离级别,因此 Spring 提供了 IsolationLevelDataSourceRouter,以克服使用应用程序服务器 JTA DataSources 时的这一缺点。

由于大多数 DataSource 实现只能采用默认的事务隔离级别,因此我们可以有多个这样的数据源,每个数据源都为特定的事务隔离级别提供连接。

逻辑事务(例如 @Transactional)隔离级别设置由 IsolationLevelDataSourceRouter 进行内省,因此连接获取请求被委托给特定的 DataSource 实现,该实现可以为具有相同事务隔离级别设置的 JDBC 连接提供服务。

因此,即使在 JTA 环境中,事务隔离路由器也可以提供独立于供应商的解决方案,用于在每个事务的基础上覆盖缺省数据库隔离级别。

Java EE 不支持方法级事务隔离配置。

可序列化隔离级别将保护您免受非可重复读取和幻像读取的影响,甚至 SERIALIZABLE 也无法防止跨多请求逻辑事务丢失更新。

使用分离的实体时,乐观锁定6 的缩放效果更好(从逻辑事务启动时加载实体算起)。


答案 2
Session session = getSession(dataSource, sessionFactory, Connection.TRANSACTION_SERIALIZABLE);

public Session getSession(DataSource dataSource, SessionFactory sessionFactory, int isolationLevel){

  // Get connection from current dataSource and set new isolation
  Connection connectionWithNewIsolation = dataSource.getConnection();
  connectionWithNewIsolation.setTransactionIsolation(isolationLevel);

  // Get session from current sessionFactory with the new isolation
  Session session = sessionFactory.openSession(connectionWithNewIsolation);

  // Hibernate 4.3
  //SessionFactory.openStatelessSession(Connection connection)
  // Hibernate 3.6
  //SessionFactory.openSession(Connection connection)
  //SessionFactory.openStatelessSession(Connection connection)

  return session;
}

推荐