赞
踩
准备接口
import java.util.List;
public interface IOperate<T> {
void add(T t);
List<T> selectALl();
}
接口实现类
@Component public class LogdtfService implements IOperate<LOGDTF> { @Autowired private LOGDTFMapper logdtfMapper; @Transactional(rollbackFor = Exception.class) @Override public void add(LOGDTF logdtf) { logdtfMapper.insert(logdtf); } @Override public List<LOGDTF> selectALl() { // TODO return null; } }
@Component public class KorekfService implements IOperate<KOREKF> { @Autowired private KOREKFMapper korekfMapper; @Transactional(rollbackFor = Exception.class) @Override public void add(KOREKF korekf) { korekfMapper.insert(korekf); // ❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗手动模拟异常❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗ int a = 1 / 0; } @Override public List<KOREKF> selectALl() { // TODO return null; } }
⏹logser.add()
和korser.add()
方法均被添加了事务,我们在korser.add()
中模拟了异常,由于这两个事务方法被test()
方法调用,且test()
方法也被添加了事务,也就是说logser.add()
和korser.add()
中的事务是子事务,从属于test()
中的总事务,当总事务方法或者任何一个子事务方法出现异常的时候,整体都会回滚.
public class A { @Autowired private LogdtfService logser; @Autowired private KorekfService korser; @Transactional(rollbackFor = Exception.class) public void test( ) { LOGDTF logdtf = new LOGDTF(); logdtf.setPgid("jmw1"); logser.add(logdtf); KOREKF korekf = new KOREKF(); korekf.setKorTantono(new BigDecimal(33)); korekf.setKorKaisyacd(new BigDecimal(118)); korekf.setKorTekinen(new BigDecimal(202203)); korekf.setKorKaisyanm("jmw0321"); korser.add(korekf); } }
public class A { @Autowired private LogdtfService logser; @Autowired private KorekfService korser; @Transactional(rollbackFor = Exception.class) public void test( ) { LOGDTF logdtf = new LOGDTF(); logdtf.setPgid("jmw1"); logser.add(logdtf); // 捕获子事务异常 try { KOREKF korekf = new KOREKF(); korekf.setKorTantono(new BigDecimal(33)); korekf.setKorKaisyacd(new BigDecimal(118)); korekf.setKorTekinen(new BigDecimal(202203)); korekf.setKorKaisyanm("jmw0321"); korser.add(korekf); } catch (Exception e) { System.out.println(e); } // 进行其他操作...... } }
在test()
方法中调用korser.add()
方法时,添加try...catch
,当korser.add()
出现异常时,会出现Transaction rolled back because it has been marked as rollback-only
异常,此时整体都会回滚
korser.add()
方法使用了propagation = Propagation.NESTED
事务传播行为
@Component public class KorekfService implements IOperate<KOREKF> { @Autowired private KOREKFMapper korekfMapper; // ❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗使用Propagation.NESTED事务传播行为 @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED) @Override public void add(KOREKF korekf) { korekfMapper.insert(korekf); // ❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗手动模拟异常❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗ int a = 1 / 0; } @Override public List<KOREKF> selectALl() { // TODO return null; } }
korser.add()
方法添加了try...catch
public class A { @Autowired private LogdtfService logser; @Autowired private KorekfService korser; @Transactional(rollbackFor = Exception.class) public void test( ) { LOGDTF logdtf = new LOGDTF(); logdtf.setPgid("jmw1"); logser.add(logdtf); try { KOREKF korekf = new KOREKF(); korekf.setKorTantono(new BigDecimal(33)); korekf.setKorKaisyacd(new BigDecimal(118)); korekf.setKorTekinen(new BigDecimal(202203)); korekf.setKorKaisyanm("jmw0321"); korser.add(korekf); } catch (Exception e) { System.out.println(e); } // 进行其他操作...... } }
korser.add()
外部的try...catch
去掉,则整体回滚Propagation.NESTED
可以让事务部分回滚savepoint
。 如果这个嵌套事务失败, 我们将回滚到此 savepoint
。 嵌套事务是外部事务的一部分, 只有外部事务结束后它才会被提交。logser.add()
方法执行完毕时,会生成一个savepoint
,此savepoint
中存储着logser.add()
的执行结果(向数据库中插入了X条数据),当korser.add()
嵌套事务的方法执行失败时,我们回滚到生成的savepoint
中,由于我们对其进行了try...catch
,因此异常并不会被抛到主方法中,所以logser.add()
会执行成功,从而实现了事务的部分回滚.参考资料:
1.Spring事务管理报错:Transaction rolled back because it has been marked as rollback-only
2.spring 事务传播行为之嵌套事务NESTED细节
3.Spring嵌套事务
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。