我有一个类似的问题,我想在事务开始后立即记录 Oracle 会话 ID,以便调查我们遇到的一些问题。
最后我发现,由于 Spring 使用PlatformTransactionManager
,您可以通过自定义访问所有信息。
首先要做的是确定您正在使用哪个实现。在我们的例子中,它是一个类中的简单JpaTransactionManager
声明@Configuration
,因此相当容易。
完成此操作后,请注意您可以在此类上启用调试或跟踪日志记录,如果您的目标是调试问题,它已经提供了大量事务状态信息。
如果这还不够,很容易将其子类化并替换前一个。然后只需覆盖您要拦截的方法,例如doBegin()
or prepareSynchronization()
。
例如看我的实现:
@Slf4j
public class LoggingJpaTransactionManager extends JpaTransactionManager {
@Autowired
private EntityManager entityManager;
LoggingJpaTransactionManager(EntityManagerFactory emf) {
super(emf);
}
@Override
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
super.prepareSynchronization(status, definition);
if (status.isNewTransaction() && log.isInfoEnabled()) {
Query query = entityManager.createNativeQuery("select sys_context('USERENV','SID') from dual");
Object sessionId = query.getSingleResult();
log.info("Started a new transaction on session id {}", sessionId);
TransactionSynchronizationManager.registerSynchronization(…);
}
}
}
注意:我选择覆盖prepareSynchronization()
而不是doBegin()
因为它允许使用TransactionSynchronizationManager
,我认为通知提交/回滚事件仍然更清晰。doBegin()
无论如何,此方法会立即被调用。