我有一個簡單的代碼,可以將某些內容保存到資料庫,然后拋出例外以查看更改是否回滾。
資源A.java
@Autowire ServiceA serviceA;
@PUT
@Path("/{Id:[0-9] }")
public ObjectA updateSomethingResource(..) {
return serviceA.upateSomethingService(..);
}
服務A.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
}
執行此操作并檢查資料庫時,物件的名稱仍然是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
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
Looking at these logs.. spring is actually telling me it 'is' rolling back the transaction.. but nothing gets changed in the DB ?
Something odd that I just noticed is that right after dao.save(objectA) I can already see the name being changed in the DB.. so somehow MyBatis is auto committing and doesn't look like it is using the same connection has the one I see in the logs
This is how I setup the Databasource and configure MyBatis
(I have 2 datasource this is why I'm using this instead of just using application.properties 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;
}
uj5u.com熱心網友回復:
你的最新更新更清楚了......我認為發生的事情是 Spring 在實體化DataSourceTransactionManager. 它可能正在使用一個BasicDataSource或類似的東西(一個使用您的屬性創建的application.properties
MyBatis 檔案明確規定,要使事務作業,DataSourceTransactionManager 需要具有與您的應用程式的其余部分正在使用的完全相同的資料源,否則它將無法作業。
將此添加到您的配置中,事務應該開始作業
@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://www.uj5u.com/shujuku/355776.html
標籤:spring-boot transactions rollback
