我有一段简单的代码,将一些东西保存到数据库,然后抛出异常,以查看更改是否被回滚。
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
}
执行此操作并检查数据库时,对象名称仍为
新名称
。我本来期望它会回滚到原始状态。为了理解发生的情况,我尝试查看可以启用的日志记录,并且唯一成功启用的是
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
显示更多日志。
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)
之后,我已经可以看到名称在数据库中被更改了..所以不知怎么回事,MyBatis自动提交并且似乎没有使用与日志中看到的连接相同的连接。
以下是我设置Databasource和配置MyBatis的方式:
(我有两个datasource,所以我使用这个方法而不是仅使用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;
}
DEBUG o.s.j.s.JdbcTransactionManager - 将 JDBC 连接 [1091371323, URL=jdbc:mysql://localhost:3306/table?allowMultiQueries=true, UserName=root@localhost, MySQL Connector/J] 切换到手动提交
- Alexandre