文章目录
从外在要求的视角
Propagation可以分为两大类,一类对于当前transaction有要求,一类没有要求,其中前者又可以分为要求有和要求无两个小类,第一个小类就是MANDATORY,而第二个小类就是NEVER.
其中无要求又可以分为2*2=4种情况,其中有->无,无->有这种情况太奇怪就没有了
从相应策略上看
对于当前情况有两种,一种是有事务,一种是无事务。那么每种情况都有三种响应方式:转换成有事务,转换成无事务,报错。
有->有 | 有->无 | 有->异常 | |
---|---|---|---|
无->有 | required/required_new/nested | ||
无->无 | supported | not_supported | never |
无->异常 | mandatory |
上面表的使用方式是先找到Propagation在表中位置,然后向上看就知道它如何处理有事务的情况,向左看就知道它如何无事务的情况。其中左上角的情况比较复杂,又分为了三类:使用老的事务(required),使用新的事务(required_new),使用内嵌的事务(nested)
从当前状态来看
required、required_new、nested
supported
这种情况感觉和没有加@Transaction的效果是一样的
not_supported
mandatory
never
required、required_new、nested
这三个都是在没有transaction的时候创建,在有transaction的表现会有不一样,但最终都会有一个transaction。三者的区别在于新旧的两个transaction的关系如何。对于required而言,新旧两个事务都是同一个,所以会相互影响。而required_new是没有关联的两个,应该不会相互影响,但是由于java 的Exception会抛上去,所以被调用的方法抛出异常时还是有可能影响到调用者的。
而nested的机制复杂一些,可以参见其他博客的详细解释,也就是说,在nested的情况下调用者的异常必然影响被调用方法,而被调用方法的异常不一定影响调用者,取决于调用者是否捕获了异常。那就是在reuqired_new和nested的情况下调用方可以通过捕获异常来避免自己回滚。
有->有 专项研究
当调用方法和被调用方法都有事务的时候,二者的相互影响各有两种情况,有影响(即异常会导致对方回滚)和无影响(异常发生时对方也会执行成功)。
public void outter(){
//operation A
inner();
//operation C
}
public void inner(){
//operation B
}
上面的outter和inner都添加有 @Transaction,显而易见的是如果operationA发生异常的时候inner根本不会执行,而inner抛出异常而outter没有捕获则outter也会抛出异常从而回滚。抛开这两种情况,下面我们研究更复杂的情况
public void outter(){
try{
inner();
}catech(EXception e){
//不在抛出异常
}
//operation C
}
public void inner(){
//operation B
}
首先outter和inner内各自的异常会导致各自方法内数据库操作的回滚是毫无疑问的,下面就是看operation C是否导致inner回滚和operation B是否导致outter回滚。
operation C影响inner | operation C不影响inner | |
---|---|---|
operation B影响outter | reuqired、supported、mandatory | |
operation B不影响outter | nested | required_new |
左上角三种情况本质上inner和outter采用的是同一个事务
右上角的是不存在的