@Transactional 无事务a()方法中调用同一个类的有事务b()方法问题
程序员文章站
2022-05-31 15:35:21
...
1. 事务的4种特性
序号 | 参数 | 含义 |
1 | 原子性(Atomicity) | 事务是数据库的逻辑工作单位,它对数据库的修改要么全部执行,要么全部不执行。 |
2 | 一致性(Consistemcy) | 事务前后,数据库的状态都满足所有的完整性约束。 |
3 | 隔离性(Isolation) | 并发执行的事务是隔离的,一个不影响一个。通过设置数据库的隔离级别,可以达到不同的隔离效果 |
4 | 持久性(Durability) | 在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。 |
2.Transactional()控制事务传播的配置项目(默认Propagation.REQUIRED)
@Transactional(propagation=Propagation.REQUIRED) //控制事务传播。默认是Propagation.REQUIRED
@Transactional(isolation=Isolation.DEFAULT) //控制事务隔离级别。默认跟数据库的默认隔离级别相同
@Transactional(readOnly=false) //控制事务可读写、只可读。默认可读写
@Transactional(timeout=30) //控制事务的超时时间,单位秒。默认跟数据库的事务控制系统相同
@Transactional(rollbackFor=RuntimeException.class) //控制事务遇到哪些异常会回滚。默认是RuntimeException
@Transactional(rollbackForClassName=RuntimeException) //同上
@Transactional(noRollbackFor=NullPointerException.class) //控制事务遇到哪些异常不会回滚。默认遇到RuntimeException回滚
@Transactional(noRollbackForClassName=NullPointerException)//同上
3.事务的7中传播特性4. 事务的传播案例:
序号 | 传播行为 | 含义 |
1 | REQUIRED | 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 |
2 | SUPPORTS | 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行 |
3 | MANDATORY | 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。 |
4 | NESTED | 如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行 |
5 | NEVER | 总是非事务地执行,如果存在一个活动事务,则抛出异常 |
6 | REQUIRES_NEW | 总是开启一个新的事务。如果一个事务已经存在,则将这个已经存在的事务挂起 |
7 | NOT_SUPPORTED | 总是非事务地执行,并挂起任何存在的事务 |
4.举个上手的按例:事务在A类的a()方法中调用B类的b()方法的传播案例
A.a() | B.b()的事务配置 | a()没有事务的结果 | a()有事务的结果 |
REQUIRED | b()创建自己的事务; | b()接受a()的事务 | |
SUPPORTS | b()不创建自己的事务; | b()接受a()的事务 | |
MANDATORY | b()报异常 | b()接受a()的事务 | |
NESTED | b()创建自己的事务; | b()接受a()的事务,成为a()嵌套的子事务 | |
NEVER | b()不创建自己的事务; | b()报异常 | |
REQUIRES_NEW | b()创建自己的事务; | b()不接受a()的事务,b()先执行,内层事务失败不会影响外层事务 | |
NOT_SUPPORTED | b()不创建自己的事务; | b()不接受a()的事务,b()先执行 |
Java案例:
public class PropagationTest extends BaseServerTest {
private static final Logger logger = Logger.getLogger(PropagationTest.class);
@Test
@Transactional()
public void a() {
try {
PropagationTestB classb = new PropagationTestB();
classb.b();
} catch (Exception e) {
throw new RuntimeException();
}
}
}
class PropagationTestB {
@Autowired
TRSMapper trsMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, rollbackFor = RuntimeException.class)
public void b() {
try {
trsMapper.saveNews(new JSONArray());
} catch (Exception e) {
throw new RuntimeException();
}
}
}
5.特殊案例分析:
Java案例:无事务a()方法中调用同一个类的有事务b()方法问题案例
public class PropagationTest extends BaseServerTest {
private static final Logger logger = Logger.getLogger(PropagationTest.class);
@Autowired
TRSMapper trsMapper;
@Test
public void a() {
try {
b();
} catch (Exception e) {
throw new RuntimeException();
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, rollbackFor = RuntimeException.class)
public void b() {
try {
trsMapper.saveNews(new JSONArray());
} catch (Exception e) {
throw new RuntimeException();
}
}
}
声明式事务基于Spring AOP实现,将具体业务逻辑与事务处理解耦,在 Spring 的 AOP 代理下,只有目标方法由外部调用,目标方法才由 Spring 生成的代理对象来管理,这会造成自调用问题。
即:
同一类中a()方法没有@Transactional 注解,在其内部调用有@Transactional 注解的方法,有@Transactional 注解的方法b()的事务被忽略,不会发生回滚。
上一篇: 水果出现哪些味道就不能吃了 水果有这味千万别吃易中毒
下一篇: Android 隐藏桌面图标