事务的传播经常用到的是这两种
@Component
public class UserService {
@Autowired
private UserService userService;
@Autowired
private JdbcTemplate jdbcTemplate;
@Transactional
public void test(){
// TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
// @Override
// public void suspend() {
// System.out.println("test对应的事务挂起");
// }
//
// @Override
// public void resume() {
// System.out.println("test对应的事务恢复");
// }
//
// @Override
// public void beforeCommit(boolean readOnly) {
// System.out.println("test对应的事务,在事务提交之前(在“完成之前”)调用");
// }
//
// @Override
// public void beforeCompletion() {
// System.out.println("test对应的事务,在事务提交/回滚之前调用。可以在事务完成之前执行资源清理。");
// }
//
// @Override
// public void afterCommit() {
// System.out.println("test对应的事务,在事务提交后调用。在主事务成功提交后,可以立即执行进一步的操作。成功提交后应执行的进一步操作,如确认消息或电子邮件。");
// }
//
// @Override
// public void afterCompletion(int status) {
// System.out.println("test对应的事务,在事务提交/回滚后调用。可以在事务完成后执行资源清理。");
// }
// });
jdbcTemplate.execute("insert into user ('1','张三','男')");
jdbcTemplate.execute("insert into user ('2','李四','男')");
try {
userService.a();
}catch (Exception e){
}
jdbcTemplate.execute("insert into user ('4','李四1','男')");
}
// @Transactional
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void a(){
jdbcTemplate.execute("insert into user ('3','王五','女')");
throw new NullPointerException();
}
}
像@Transactional(propagation = Propagation.REQUIRES_NEW)这种事务传播,具体执行流程图
这种事务的传播时,a中抛异常,a事务回滚,test事务不受影响,照样提交。
而a与test都是@Transactional这个的时候,就说明a并未开启新的事务,还是用的test的事务,这时候,如果事务管理器并未设置部分异常全局回滚为false时,默认是true
transactionManager.setGlobalRollbackOnParticipationFailure(false);
两个方法的sql都会回滚。
另外一点,就是下面这种情况,因为将异常try了,所以事务还是会提交的,但是按理说应该不能提交
@Transactional
public void test(){
jdbcTemplate.execute("insert into user ('2','李四','男')");
try {
throw new NullPointerException();
}catch (Exception e){
return 返回给前端比较友好的对象(处理后的对象)
}
}
所以这种情况,在commit方法中会有一个判断
`
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
processRollback(defStatus, false);
return;
}
就在catch 中加一个强制回滚,就可以回滚了
@Transactional
public void test(){
jdbcTemplate.execute("insert into user ('2','李四','男')");
try {
throw new NullPointerException();
}catch (Exception e){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return 返回给前端比较友好的对象(处理后的对象)
}
}
mysql中的savepoint:(前面执行3个sql,创建savepoint,在执行2个sql,然后报错,这是回滚就只回滚到savepoint的位置,也就是后2条sql回滚,前面3个sql不回滚)
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
}
//回滚到上一个savepoint位置
status.rollbackToHeldSavepoint();
}
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback");
}
//如果当前执行的方法是新开了一个事务,那么就直接回滚
doRollback(status);
}