最近在項目中會使用到多數(shù)據(jù)源,數(shù)據(jù)源太多了简十,所以采用的配置DataSource的方式檬某,然后代碼中使用JdbcTempate(dataSource)
的方式。但是最近遇到一個問題螟蝙,在使用jt.batchUpdate(sqls)
時恢恼,發(fā)現(xiàn)如果有sql
有誤,jdbctempalte
并不會回滾胰默。由于代碼框架很老场斑,不再適合對每個數(shù)據(jù)源都配置DataSourceTransactionManager
。最終在網(wǎng)上看見下面的方法牵署,紀(jì)錄一下:
public static void batchExecute(JdbcTemplate jt, List<String> sqlList) throws SQLException{
if(sqlList.size() == 0) return;
DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
DataSourceTransactionManager dm = new DataSourceTransactionManager(jt.getDataSource());
TransactionStatus tmp = dm.getTransaction(transactionDefinition);
String[] sqls = new String[sqlList.size()];
sqlList.toArray(sqls);
try{
jt.batchUpdate(sqls);
dm.commit(tmp);
} catch (Exception e) {
dm.rollback(tmp);
throw new SQLException(e.getMessage());
}
}
注意
由于spring的事務(wù)處理是按照 LIFO/stack behavior的方式進(jìn)行的漏隐,所以在多個事務(wù)進(jìn)行提交時必須按照上述規(guī)則進(jìn)行,否則就會報上面異常
當(dāng)你寫了多個數(shù)據(jù)源事務(wù)時要遵循后進(jìn)先出
奴迅。否則會報出下面的錯誤
spring tranaction: Cannot deactivate transaction synchronization - not active
修改后代碼
try{
jt.batchUpdate(sqls);
jt2.batchUpdate(sqls2);
dm2.commit(tmp2);
dm.commit(tmp);
} catch (Exception e) {
dm.rollback(tmp);
dm2.rollback(tmp2);
}