//以下self()均看做AopContext.currentProxy()–》走代理路线!!,为的是在同一类两个事务方法生效(最后有说明)
/**REQUIRED方法调用REQUIRED方法*/
//1.子方法抛出异常,父方法不处理,都会回滚----》updateA()回滚,updateB()回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
updateA();
self().updateSon();
}
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateSon() throws Exception {
updateB();
throw new Exception("手动给子方法抛出异常");
}
//2.子方法抛出异常,父方法处理异常,都会回滚---》updateA()回滚,updateB()回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
updateA();
try{
self().updateSon();
}catch(Exception e){
logger.info("对子事务异常进行处理,但不抛出")
}
}
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateSon() throws Exception {
updateB();
throw new Exception("手动给子方法抛出异常");
}
//3.子方法无异常,父方法有异常但不处理,都会回滚---》updateA()回滚,updateB()回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
updateA();
self().updateSon();
throw new Exception("手动给父方法抛出异常");
}
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateSon() throws Exception {
updateB();
}
总结:REQUIRED总是会在一个事务中,无论哪个位置抛出异常,均会全部回滚,即使对子方法异常进行了处理,还是会全部回滚。另外,如果在子方法中对异常进行了处理,相当于没有异常,事务均不会回滚。因为异常只有在抛出去后才会触发事务,如果进行了处理是不会触发事务的,如下:
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
updateA();
self().updateSon();
}
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateSon() throws Exception {
updateB();
//以下try catch相当于没有异常,不会触发事务
try{
throw new Exception("手动给子方法抛出异常");
}catch(Exception e){
logger.info("对子事务异常进行了处理") ;
}
}
/**REQUIRED调用NESTED*/
//1.子方法第二次抛出异常,父方法未处理该异常,均会回滚---》 updateA(),updateB(),updateC()回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
updateA();
for(int i=0;i<2;i++){
self().updateSon(i);
}
}
@Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
public void updateSon(int i) throws Exception {
if(i=0){
updateB();
}
if(i=1){
updateC();
throw new Exception("手动给子方法抛出异常");
}
}
//2.子方法第二次抛出异常,父方法处理异常,已经执行的不会回滚---》updateA(),updateB()不会回滚,updateC()回滚。
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
updateA();
for(int i=0;i<2;i++){
try{
self().updateSon(i);
}catch(Exception e){
logger.info("处理子事务异常但不抛出");
}
}
@Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
public void updateSon(int i) throws Exception {
if(i=0){
updateB();
}
if(i=1){
updateC();
throw new Exception("手动给子方法抛出异常");
}
}
//3.子方法无异常,父方法在第二次循环的时候抛出异常,均会回滚---》updateA(),updateB(),updateC()均回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
updateA();
for(int i=0;i<2;i++){
self().updateSon(i);
if(i==1){
throw new Exception("执行第二次循环的时候在父方法抛出异常");
}
}
}
@Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
public void updateSon(int i) throws Exception {
if(i=0){
updateB();
}
if(i=1){
updateC();
}
}
总结:NESTED会跟随父事务一起提交,如果父事务一旦出现异常,均会回滚,但如果NESTED子方法事务出现异常,父事务对其进行了处理,已经执行的不会回滚(如代码2)。
/**REQUIRED调用REQUIRES_NEW*/
//1.子方法第二次抛出异常,父方法未处理该异常,部分回滚---》 updateA(),updateC()回滚,updateB()不回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
updateA();
for(int i=0;i<2;i++){
self().updateSon(i);
}
}
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void updateSon(int i) throws Exception {
if(i=0){
updateB();
}
if(i=1){
updateC();
throw new Exception("手动给子方法抛出异常");
}
}
//2子方法第二次抛出异常,父方法处理异常--》updateA()不回滚,updateB(),updateC()回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
updateA();
for(int i=0;i<2;i++){
try{
self().updateSon(i);
}catch(Exception e){
logger.info("处理子事务异常但不抛出");
}
}
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void updateSon(int i) throws Exception {
if(i=0){
updateB();
}
if(i=1){
updateC();
throw new Exception("手动给子方法抛出异常");
}
}
//3.子方法无异常,父方法在第二次循环的时候抛出异常---》updateA()回滚,updateB(),updateC()不回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
updateA();
for(int i=0;i<2;i++){
self().updateSon(i);
if(i==1){
throw new Exception("执行第二次循环的时候在父方法抛出异常");
}
}
}
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void updateSon(int i) throws Exception {
if(i=0){
updateB();
}
if(i=1){
updateC();
}
}
总结:REQUIRES_NEW新开一个事务,与父事务相互隔离,互不影响。
另外::如果同一个类中有两个事务方法A,B,事务方法A调用事务方法B,B事务方法是不会生效的,因为这样是不走代理类调用的,要想事务奏效必须使用代理类调用。针对此问题有两种方法可以解决
1.将B事务方法放到另外一个类中,通过注入类来进行调用
2.使用AopContext.currentProxy()来进行调用,即在A事务方法中调用B事务方法代码为:(该类名)AopContext.currentProxy().B();(以上self()就是 AopContext.currentProxy()!!,)