Isolation of JDBC spring transaction from sleep transaction

In spring, the HibernateTransactionManager uses a SessionFactory that was initialized to "bind" the session to the current thread context when creating a new transaction. Then, when the HibernateTemplate is used, it finds the connected session and uses it.

However, today I discovered that HTM also binds its transaction to the underlying data source, as well as to the SessionFactory (if possible). This allows the code to use the JdbcTemplate within the transaction and if the DataSource used by the JdbcTemplate matches the SessionFactory, the Jdbc operations will participate in the transaction (using the same underlying connection).

This spoils me a bit today when I had code in my sleep identifier manager that created the DataSourceTransactionManager and JdbcTemplate to extract identifiers from the high-lo table. I assumed that this is a separate transaction, which will receive the next large number, and then commit the change to the identifier table. However, due to the above behavior, he actually participated in my "external" hibernation transaction and did it even worse before. Enough to say is not good.

I tried playing with transactional proxy settings (using REQUIRES_NEW), but that didn't help.

Does anyone know how best to use JdbcTemplate in a sleep transaction and NOT share the transaction even if they use the same data source?

EDIT:

SessionFactory (S), spring LocalSessionFactoryBean DataSource (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 (), DataSource (D), SessionFactory (S).

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 );
    }
} );

, , , , , , , "" . , / .

+3
3

.

HibernateTransactionManager.

  • "autodetectDataSource", true
  • afterPropertiesSet() DataSource SessionFactory
  • doBegin(), DataSource , SessionFactory DataSource

, DataSourceTransactionManager, - (TransactionSynchronizationManager) , DataSource, txn. , txn /id , , , , .

. hibernate txn DataSourceTransactionManager, REQURES_NEW . HTM → SessionFactory → IdAllocator → HTM.

, , .

, DataSource . DataSource , 100%. DataSource, txn , , .

+2

REQUIRES_NEW - ( HSQLDB), , :

// txManager is a HibernateTransactionManager obtained from the application context
TransactionOperations transactionOperations = new TransactionTemplate( txManager );
transactionOperations.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);

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

DataSourceTransactionManager id. REQUIRES_NEW HibernateTransactionManager.

The allocateBatchTxn()safest way to connect JDBC is with the Spring method DataSourceUtils.getConnection().

+2
source

Source: https://habr.com/ru/post/1786528/


All Articles