好玩Spring之同一個類中的巢狀事務試驗
阿新 • • 發佈:2020-12-21
試驗
/**
* 情形一:methodA: PROPAGATION_REQUIRED methodB: PROPAGATION_REQUIRED(相當於一個事務)
* 異常條件:無
* methodA / methodB 均未加try-catch
*
* 結果:A_table / B_table 均可以插入資料
*
*/
/**
* 情形二:methodA: 沒有加@Transactional methodB: PROPAGATION_REQUIRED
* 異常條件:無
*
* 結果:A_table / B_table 均沒有插入資料
*
* 原因:在呼叫A的時候只建立一個代理類,呼叫B的時候,不是呼叫的代理類,所以@Transactional不生效
*
*/
/**
* 情形三:methodA: PROPAGATION_REQUIRED methodB: 沒有加@Transactional
* 異常條件:無
*
* 結果:A_table / B_table 均可以插入資料
*
* 原因:在呼叫A的時候只建立一個代理類,開啟了事務,呼叫B時,直接使用這個事務
*
*/
/**
* 情形四:methodA: PROPAGATION_REQUIRED methodB: PROPAGATION_REQUIRED(相當於一個事務)
* 異常條件:B中有 1/0 異常
* methodA / methodB 均未加try-catch
*
* 結果:A_table / B_table 均沒有插入資料
*
*/
/**
* 情形五:methodA: PROPAGATION_REQUIRED methodB: PROPAGATION_REQUIRED
* 異常條件:B中有 1/0 異常
* methodB 加try-catch
*
* 結果:A_table / B_table 均可以插入資料
*
*/
/**
* 情形六:methodA: PROPAGATION_REQUIRED methodB: PROPAGATION_REQUIRED
* 異常條件:B中有 1/0 異常
* methodA 加try-catch
*
* 結果:A_table / B_table 均沒有插入資料
*
*/
public class JdbcFooRepository {
private DataSource dataSource;
public JdbcFooRepository(DataSource dataSource) {
this.dataSource = dataSource;
}
@Transactional(transactionManager = "txManager")
public void methodA() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
Connection connection = DataSourceUtils.getConnection(dataSource);
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
try {
jdbcTemplate.execute("insert into A_table(title, author) values('A_title1', 'A_author1')");
methodB(jdbcTemplate);
} catch (DataAccessException e) {
e.printStackTrace();
}
}
public void methodB(JdbcTemplate jdbcTemplate) {
jdbcTemplate.execute("insert into B_table(title, author) values('B_title1', 'B_author1')");
int i = 1/0;
}
}
結論
前提:methodA和methodB處於同一個類中,事務的傳播屬性均為:PROPAGATION_REQUIRED
題目
// 有個面試題如下:
// B_title中,id=100的記錄沒有,問insert語句是否可以執行成功?
// 答:可以執行成功,id=100的記錄沒有,但語句可以正常執行,不會報錯
@Transactional(transactionManager = "txManager")
public void C() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
Connection connection = DataSourceUtils.getConnection(dataSource);
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
try {
jdbcTemplate.execute("insert into A_table(title, author) values('A_title1', 'A_author1')");
jdbcTemplate.execute("update B_table set title = 'B_title111' where id=100");
} catch (DataAccessException e) {
e.printStackTrace();
}
}