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事务。原因是我把异常抓住了,消化掉了。
来源:CSDN
作者:梦缘七分
链接:https://blog.csdn.net/weixin_43879532/article/details/103456998