记录次spring的事务问题

孤人 提交于 2019-12-09 18:12:36

1.问题出现

1.代码如下:

@Override
@Transactional
public void addUser2(String name, String password) {

    userNoteMapper.addUser(name,password);
    System.out.println(1/0);
}

2.现象是:

事务无论怎么样,都不进行事务的回滚,数据正常插入
数据库图

3.问题排查:

1.首先进行方法的模拟,在dao测试,service测试,controller测试,接口测试,添加事务对插入无任何影响。排除在外???
2.检查是否是类方法中的调用,只是单一的调用。排除在外???
3.检查是否是数据库表的设计,mysql中引擎是否支持事务。在mysql中,innerdb是支持事务,而myisam不支持事务。我的错误正是数据表的引擎为myisam。
数据库表的设计

2.模拟spring事务的各种现象

1.李子

@Override
@Transactional
public void addUser2(String name, String password) {

    userNoteMapper.addUser(name,password);
    System.out.println(1/0);//此处抛出异常,事务回滚,因此add不会生效
}

该事务肯定生效。

2.李子

2.1 同类都有事务

    @Override
    @Transactional
    public void addUser2(String name, String password) {

        userNoteMapper.addUser(name,password);
        test();
    }

    @Override
    @Transactional
    public void test(){
        System.out.println(1/0);
    }

该事务肯定生效。

2.2 同类都有事务,父类捕获

@Override
@Transactional
public void addUser2(String name, String password) {

    userNoteMapper.addUser(name,password);
    try {
        test();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
@Transactional
public void test(){
    System.out.println(1/0);
}

事务不会生效。

因为addPerson有事务,所以editById理论上也有事务应该回滚才对,但是由于上层方法给catch住了,所以是没有回滚的,所以持久化生效。

2.3 同类,非事务方法调用事务方法

@Override
public void addUser2(String name, String password) {

     userNoteMapper.addUser(name,password);   
     test();
 }

 @Override
 @Transactional
 public void test(){
     System.out.println(1/0);
 }

事务不会生效

所以在同一个类中一个无事务的方法调用另一个有事务的方法,事务是不会起作用的。因为aop失效了。

3.李子

3.1 不同类调用,都添加事务

@Override
@Transactional
public void addUser2(String name, String password) {

    userNoteMapper.addUser(name,password);

    personService.addUser();

}

@Override
@Transactional
public void addUser() {
    System.out.println(1/0);
}

事务生效。

不会发生异常

3.2 不同类调用,父级抓取

 @Override
 @Transactional
 public void addUser2(String name, String password) {

     userNoteMapper.addUser(name,password);
     try {
         personService.addUser();
     } catch (Exception e) {
         e.printStackTrace();
     }
 }

@Override
@Transactional
 public void addUser() {
     System.out.println(1/0);
 }

事务生效,but

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
翻译:事务已回滚,因为它被标记成了只回滚

3.3 不同类调用,父级没有事务抓取

@Override
public void addUser2(String name, String password) {
    try {
        personService.addUser();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
@Transactional
public void addUser() {
    userNoteMapper.addUser("vdstygbhnjkm","vsdgbhmk,");
    System.out.println(1/0);
}

事务生效 ,不会抛Transaction rolled back because it has been marked as rollback-only

异常抓取,但是因为上级没有事务,所有不会产生rollback-only

3.4 不同类调用,都有事务,抛出异常

@Override
public void addUser2(String name, String password) {
    try {
        personService.addUser();
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
}

@Override
@Transactional
public void addUser() {
    userNoteMapper.addUser("vdstygbhnjkm","vsdgbhmk,");
    System.out.println(1/0);
}

事务生效 ,不会抛Transaction rolled back because it has been marked as rollback-only

异常抓取,但是因为又将异常抛出,所以事务失效,不会产生rollback-only错误

4. 综上所述

因此我们可以得出结论,rollback-only异常,是发生在异常本身才有可能出现,发生在子方法内部是不会出现的。因此这种现象最多是发生在事务嵌套里。
备注一点:如果你catch住后继续向上throw,也是不会出现这种情况的。

总结一句话:当我想commit事务时,事务已经标记为rollback-only,而我也没有看到异常,无法commit事务。原因是我把异常抓住了,消化掉了。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!