在 Spring ,HibernateTransactionManager使用初始化时使用的SessionFactory在创建新事务时将Session“绑定”到当前线程上下文。然后,当使用HibernateTemplate时,找到该绑定的Session并使用它。

但是,我今天发现,HTM还将其事务绑定到基础数据源以及SessionFactory(如果可能)。这允许代码在事务范围内使用JdbcTemplate,并且如果JdbcTemplate使用的DataSource与SessionFactory使用的相同,则Jdbc操作将参与事务(使用相同的基础Connection)。

今天,当我的休眠ID分配器中有一些代码正在创建DataSourceTransactionManager和JdbcTemplate来从高低表中分配ID时,这让我非常不高兴。我打算这是一个独立的事务,它将获取下一个较高的数字,然后将更改提交到id表。但是由于上述行为,它实际上参与了我的“外部”休眠事务,甚至更早地提交了它。可以说不好。

我尝试使用交易传播设置(使用了REQUIRES_NEW),但这没有帮助。

有谁知道在休眠事务中使用JdbcTemplate的最佳方法,并且即使他们共享相同的DataSource也不要让他们共享事务?

编辑:

我有一个SessionFactory(S),它是由Spring LocalSessionFactoryBean使用数据源(D)创建的。 HibernateTransactionManager是使用该SessionFactory(S)创建的。

一些业务逻辑代码将如下所示。

hibernateTransactionOperations.execute( new TransactionCallbackWithoutResult()
{
    @Override
    protected void doInTransactionWithoutResult( TransactionStatus status )
    {
        // some transactional code here using a HibernateTemplate

        // will include calls to id allocation when doing hibernateTemplate.save(obj)
    }
} );

我的ID分配执行了此操作(解释),下面的数据源与SessionFactory(S)中使用的数据源相同(D)。
PlatformTransactionManager txManager = new DataSourceTransactionManager( dataSource );
TransactionOperations transactionOperations = new TransactionTemplate( txManager );

return transactionOperations.execute( new TransactionCallback<Long>()
{
    public Long doInTransaction( TransactionStatus status )
    {
        return allocateBatchTxn( idKey, batchSize );
    }
} );

当transactionOperations在上面执行完毕时,它将提交基础事务,该事务似乎与“外部”休眠事务相同。我已经通过检查数据库中的锁/事务确认了这一点。

最佳答案

不要在您的ID分配代码中创建新的DataSourceTransactionManager。而是使用REQUIRES_NEW和HibernateTransactionManager。

allocateBatchTxn()中,获取JDBC连接的最安全方法是通过Spring的DataSourceUtils.getConnection()方法。

08-25 12:08
查看更多