我有一个简单的代码,它将一些内容保存到DB中,然后抛出一个异常,看看这些更改是否会回滚。
ResourceA.java
@Autowire ServiceA serviceA;
@PUT
@Path("/{Id:[0-9]+}")
public ObjectA updateSomethingResource(..) {
return serviceA.upateSomethingService(..);
}ServiceA.java
@Transactional(rollbackFor=Exception.class)
public ObjectA upateSomethingService(EntitlementRequest entitlementRequest) throws ServiceException {
ObjectA objectA = getObjectFromDB(..);
objectA.setName("New Name");
dao.save(objectA)
throw new ServiceException("error"); //ServiceException extends Exception
}在执行此操作时,我检查了DB,对象的名称仍然是New Name。我会期望它回滚到它最初的样子。
为了理解发生了什么,我试着看看我可以启用什么日志,我唯一成功启用的是logging.level.org.springframework.transaction.interceptor=TRACE
这就给出了:
TRACE o.s.t.i.TransactionInterceptor - Getting transaction for [xxxxx.upateSomethingService]
TRACE o.s.t.i.TransactionInterceptor - Completing transaction for [xxxxx.upateSomethingService] after exception: xxx.ServiceException 因此,事务管理器确实看到了异常,但没有任何内容被回滚。
是否需要在某个地方启用某些功能才能使回滚真正工作?我还可以启用哪些日志来准确地显示正在发生的情况?
更新:我已经设法用logging.level.org.springframework=DEBUG展示了ore日志
DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
DEBUG o.s.j.s.JdbcTransactionManager - Creating new transaction with name [xxx.service.upateSomethingService]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Exception
DEBUG o.s.j.s.JdbcTransactionManager - Acquired Connection [1091371323, URL=jdbc:mysql://localhost:3306/table?allowMultiQueries=true, UserName=root@localhost, MySQL Connector/J] for JDBC transaction
DEBUG o.s.j.s.JdbcTransactionManager - Switching JDBC Connection [1091371323, URL=jdbc:mysql://localhost:3306/table?allowMultiQueries=true, UserName=root@localhost, MySQL Connector/J] to manual commit
DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
DEBUG o.s.j.s.JdbcTransactionManager - Initiating transaction rollback
DEBUG o.s.j.s.JdbcTransactionManager - Rolling back JDBC transaction on Connection [1091371323, URL=jdbc:mysql://localhost:3306/table?allowMultiQueries=true, UserName=root@localhost, MySQL Connector/J]
DEBUG o.s.j.s.JdbcTransactionManager - Releasing JDBC Connection [1091371323, URL=jdbc:mysql://localhost:3306/table?allowMultiQueries=true, UserName=root@localhost, MySQL Connector/J] after transaction 看看这些日志..spring实际上告诉我它“正在”回滚事务..但在数据库中什么都不会改变?
奇怪的是,我刚刚注意到的是,在dao.save(objectA)之后,我已经可以在DB中看到名称正在更改。因此,不知何故,MyBatis是自动提交的,并且看起来它使用的连接与我在日志中看到的连接不同
这就是我设置数据库源和配置MyBatis的方法
(我有两个数据源,这就是为什么我使用它,而不是仅仅使用application.properties属性。)
@Bean(name = MYBATIS_DATASOURCE_ONE, destroyMethod = "")
public DataSource dataSource(....) throws SQLException {
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver(driverclassname);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
[...]
return dataSource;
}
@Bean(name = A_SESSION_FACTORY, destroyMethod = "")
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier(MYBATIS_DATASOURCE_A) DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/mapper/*.xml"));
final SqlSessionFactory sqlSessionFactory = factoryBean.getObject();
return sqlSessionFactory;
}发布于 2021-11-10 21:08:30
你的最新更新让它变得更加清晰...我认为发生的情况是,Spring在实例化DataSourceTransactionManager时没有使用您手动定义的DataSource。它可能正在使用BasicDataSource或类似的东西(使用application.properties中的属性创建的your
将它添加到您的配置中,事务就应该开始工作了
@Bean
public DataSourceTransactionManager transactionManager(@Qualifier(MYBATIS_DATASOURCE_A) DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}通常,您不需要手动定义此Bean,因为Spring会自动为您定义。但由于您使用的是自己的DataSource,因此需要这样做。
如果你想验证这一点。不要声明此bean并在DataSourceTransactionManager构造函数中放置断点。您应该注意到,DataSource与您自己声明的实例不是同一个实例。
https://stackoverflow.com/questions/69918403
复制相似问题