Весной HibernateTransactionManager использует SessionFactory, с которой он был инициализирован, чтобы "привязать" сеанс к текущему контексту потока при создании новой транзакции. Затем, когда используется HibernateTemplate, он находит связанный Session и использует его.
Однако сегодня я обнаружил, что HTM также связывает свою транзакцию с базовым источником данных, а также с SessionFactory (если это возможно). Это позволяет коду использовать JdbcTemplate в области транзакции и, при условии, что DataSource, используемый JdbcTemplate, такой же, как SessionFactory, операции Jdbc будут участвовать в транзакции (используя то же базовое соединение).
Это меня очень огорчило сегодня, когда в моем распределителе идентификаторов гибернации был какой-то код, который создавал DataSourceTransactionManager и JdbcTemplate для распределения идентификаторов из таблицы высокого уровня. Я намеревался, что это будет автономная транзакция, которая получит следующее большое число и затем передаст изменения в таблицу идентификаторов. Однако из-за описанного выше поведения он фактически участвовал в моей «внешней» транзакции гибернации И еще хуже, совершая ее рано. Достаточно сказать не хорошо.
Я пытался поиграть с настройками распространения транзакции (использовал REQUIRES_NEW), но это не помогло.
Кто-нибудь знает лучший способ использовать JdbcTemplate в транзакции гибернации и НЕ заставлять их совместно использовать транзакцию, даже если они совместно используют один и тот же источник данных?
EDIT:
У меня есть SessionFactory (S), который создается пружинным 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)
}
} );
мое распределение идентификаторов делает это (перефразировано), источник данных ниже тот же (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 );
}
} );
Когда транзакция транзакции, выполненная выше, завершается, он фиксирует основную транзакцию, которая выглядит так же, как и «внешняя» транзакция гибернации. Я подтвердил это, проверив блокировки / транзакции в БД.