Spring嵌套事物的简单测试

整体项目很简单,为了方便,用了Spring Boot和Mybatis集成的方式对数据库进行操作,事物的传播属性是默认的PROPAGATION_REQUIRED.这里最主要是Service外层和Service内层的嵌套,大概看看都能看懂(注:for循环从0开始了,没做修改,忽略数据库id不能为0的无用数据,操作过程中已删除)。

下面分情况介绍异常:

Application层(没用这个,直接用了Junit测试类)

---------------------------------------------------------------------------------------------------------------------------------

 

package com.sh.springboot;

 

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

/**

 * Created by sh on 18/4/28.

 */

@SpringBootApplication

@MapperScan("com.sh.springboot.dao")

publicclassSpringbootApplication{

 

    publicstaticvoid main(String[] args) {

        SpringApplication.run(SpringbootApplication.class, args);

    }

 

    /*

     * @Autowired private ServiceWaiCeng s;

     *

     * @RequestMapping("/") String home()throws Exception {

     * System.out.println("controller 正常执行"); s.insertWaiCeng();;

     *

     * return " 正常返回Hello World!"; }

     */

}

Test测试类

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot;

 

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

 

import com.sh.springboot.servicewaiceng.ServiceWaiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@RunWith(SpringJUnit4ClassRunner.class)

@SpringBootTest(classes = SpringbootApplication.class)

publicclassPersonDaoTest {

    @Autowired

    private ServiceWaiCeng servicewaiceng;

   

    @Test

    publicvoid test() {

        servicewaiceng.insertWaiCeng();

        System.out.println("Controller正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

Service外层

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.servicewaiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

import com.sh.springboot.servicewaiceng.ServiceWaiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Component

publicclassServiceWaiCengImpl implements ServiceWaiCeng {

 

    @Autowired

    private ServiceNeiCeng snc;

 

    @Transactional

    publicvoid insertWaiCeng() {

            for (intj = 0; j < 8; j++) {

                snc.insertNeiCeng(j, j + "姓名");

            }

        System.out.println("外层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

Service内层

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.serviceneiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.bean.Person;

import com.sh.springboot.dao.PersonDao;

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Service

publicclassServiceNeiCengImpl implements ServiceNeiCeng {

 

    @Autowired

    PersonDaopersondao;

 

    @Transactional

    publicvoid insertNeiCeng(intid, String name) {

        Personperson= newPerson();

        person.setId(id);

        person.setName(name);

        persondao.insertPerson(person);

        System.out.println(id + "内层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

一、内外都无Try Catch

         1.外部有异常,内部无异常

                   修改Service外层代码如下:

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.servicewaiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

import com.sh.springboot.servicewaiceng.ServiceWaiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Component

publicclassServiceWaiCengImpl implements ServiceWaiCeng {

 

    @Autowired

    private ServiceNeiCeng snc;

 

    @Transactional

    publicvoid insertWaiCeng() {

            for (intj = 0; j < 8; j++) {

                snc.insertNeiCeng(j, j + "姓名");

                if (j == 4) {

                    inti = 2 / 0;// 此处会产生异常

                }

            }

        System.out.println("外层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

打印执行结果:0~4内层正常执行

     

数据库结果:全部回滚

总结:内外都无try Catch的时候,外部异常,全部回滚。

 

 

 

2.外部无异常,内部有异常

                   注掉Service外层的异常部分,修改Service内层代码如下:

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.serviceneiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.bean.Person;

import com.sh.springboot.dao.PersonDao;

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Service

publicclassServiceNeiCengImpl implements ServiceNeiCeng {

 

    @Autowired

    PersonDaopersondao;

 

    @Transactional

    publicvoid insertNeiCeng(intid, String name) {

        Personperson= newPerson();

        person.setId(id);

        person.setName(name);

        persondao.insertPerson(person);

        if (id == 4) {

            inti = 2 / 0;// 此处会产生异常

        }

        System.out.println(id + "内层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

打印执行结果:0~3内层正常执行

数据库结果:全部回滚

总结:内外都无try Catch的时候,内部异常,全部回滚。

         内外都有异常,由1和2可得,内部先异常,不用考虑外部异常也都是全部回滚。

二、内外都有Try Catch

         1.外部有异常,内部无异常

                   修改Service内层和外层代码如下:

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.servicewaiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

import com.sh.springboot.servicewaiceng.ServiceWaiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Component

publicclassServiceWaiCengImpl implements ServiceWaiCeng {

 

    @Autowired

    private ServiceNeiCeng snc;

 

    @Transactional

    publicvoid insertWaiCeng() {

            try {

                for (intj = 0; j < 8; j++) {

                    snc.insertNeiCeng(j, j + "姓名");

                    if (j == 4) {

                        inti = 2 / 0;// 此处会产生异常

                    }

                }

            }catch(Exception e) {

                System.out.println("外层异常处理");

            }

        System.out.println("外层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.serviceneiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.bean.Person;

import com.sh.springboot.dao.PersonDao;

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Service

publicclassServiceNeiCengImpl implements ServiceNeiCeng {

 

    @Autowired

    PersonDaopersondao;

 

    @Transactional

    publicvoid insertNeiCeng(intid, String name) {

        try {

            Personperson= newPerson();

            person.setId(id);

            person.setName(name);

            persondao.insertPerson(person);

//          if(id == 4) {

//              inti = 2 / 0;// 此处会产生异常

//          }

        }catch(Exception e) {

            System.out.println(id + "内部异常日志处理");

        }

        System.out.println(id + "内层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

打印执行结果:0~4内层正常打印,外层异常处理并且正常执行

数据库结果:插入四条数据,没有回滚

总结:内外都有tryCatch,外部异常,事物失败(走一半)

 

        

         2.外部无异常,内部有异常

                   修改Service内层和外层代码如下:

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.servicewaiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

import com.sh.springboot.servicewaiceng.ServiceWaiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Component

publicclassServiceWaiCengImpl implements ServiceWaiCeng {

 

    @Autowired

    private ServiceNeiCeng snc;

 

    @Transactional

    publicvoid insertWaiCeng() {

            try {

                for (intj = 0; j < 8; j++) {

                    snc.insertNeiCeng(j, j + "姓名");

//                  if(j == 4) {

//                      inti = 2 / 0;// 此处会产生异常

//                  }

                }

            }catch(Exception e) {

                System.out.println("外层异常处理");

            }

        System.out.println("外层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.serviceneiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.bean.Person;

import com.sh.springboot.dao.PersonDao;

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Service

publicclassServiceNeiCengImpl implements ServiceNeiCeng {

 

    @Autowired

    PersonDaopersondao;

 

    @Transactional

    publicvoid insertNeiCeng(intid, String name) {

        try {

            Personperson= newPerson();

            person.setId(id);

            person.setName(name);

            persondao.insertPerson(person);

            if (id == 4) {

                inti = 2 / 0;// 此处会产生异常

            }

        }catch(Exception e) {

            System.out.println(id + "内部异常日志处理");

        }

        System.out.println(id + "内层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

打印执行结果:0~7内层打印正常,4内层异常处理,

数据库结果:

总结:内外都有tryCatch,内部异常,事物失败(数据全部插入)

 

         内外都有异常,由1和2可得,先走内部异常,再外部异常,数据结果同1

三、外层有Try Catch,内层无Try Catch

         1.外部有异常,内部无异常

                   修改Service内层和外层代码如下:

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.serviceneiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.bean.Person;

import com.sh.springboot.dao.PersonDao;

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Service

publicclassServiceNeiCengImpl implements ServiceNeiCeng {

 

    @Autowired

    PersonDaopersondao;

 

    @Transactional

    publicvoid insertNeiCeng(intid, String name) {

            Personperson= newPerson();

            person.setId(id);

            person.setName(name);

            persondao.insertPerson(person);

//          if(id == 4) {

//              inti = 2 / 0;// 此处会产生异常

//          }

        System.out.println(id + "内层正常执行");

    }

}

package com.sh.springboot.servicewaiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

import com.sh.springboot.servicewaiceng.ServiceWaiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Component

publicclassServiceWaiCengImpl implements ServiceWaiCeng {

 

    @Autowired

    private ServiceNeiCeng snc;

 

    @Transactional

    publicvoid insertWaiCeng() {

            try {

                for (intj = 0; j < 8; j++) {

                    snc.insertNeiCeng(j, j + "姓名");

                    if (j == 4) {

                        inti = 2 / 0;// 此处会产生异常

                    }

                }

            }catch(Exception e) {

                System.out.println("外层异常处理");

            }

        System.out.println("外层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

打印执行结果:0~4内层正常执行,外层异常处理继续正常执行流程到结束

数据库结果:4条数据正常插入

总结:外部有try Catch、内部无try Catch的时候,外部异常,不能回滚(事物错误)

 

 

2.外部无异常,内部有异常

              修改Service内层和外层代码如下:

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.serviceneiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.bean.Person;

import com.sh.springboot.dao.PersonDao;

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Service

publicclassServiceNeiCengImpl implements ServiceNeiCeng {

 

    @Autowired

    PersonDaopersondao;

 

    @Transactional

    publicvoid insertNeiCeng(intid, String name) {

            Personperson= newPerson();

            person.setId(id);

            person.setName(name);

            persondao.insertPerson(person);

            if (id == 4) {

                inti = 2 / 0;// 此处会产生异常

            }

        System.out.println(id + "内层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.servicewaiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

import com.sh.springboot.servicewaiceng.ServiceWaiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Component

publicclassServiceWaiCengImpl implements ServiceWaiCeng {

 

    @Autowired

    private ServiceNeiCeng snc;

 

    @Transactional

    publicvoid insertWaiCeng() {

            try {

                for (intj = 0; j < 8; j++) {

                    snc.insertNeiCeng(j, j + "姓名");

//                  if(j == 4) {

//                      inti = 2 / 0;// 此处会产生异常

//                  }

                }

            }catch(Exception e) {

                System.out.println("外层异常处理");

            }

        System.out.println("外层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

打印执行结果:0~3内层正常打印执行

数据库结果:无数据,全部回滚

总结:外部有try Catch、内部无try Catch的时候,内部异常,全部回滚

 

    内外都有异常,由1和2推理得结果也是事物失败。

 

 

 

四、外层无Try Catch,内层有Try Catch

         1.外部有异常,内部无异常

                   修改Service内层和外层代码如下:

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.serviceneiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.bean.Person;

import com.sh.springboot.dao.PersonDao;

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Service

publicclassServiceNeiCengImpl implements ServiceNeiCeng {

 

    @Autowired

    PersonDaopersondao;

 

    @Transactional

    publicvoid insertNeiCeng(intid, String name) {

        try {

            Personperson= newPerson();

            person.setId(id);

            person.setName(name);

            persondao.insertPerson(person);

//          if(id == 4) {

//              inti = 2 / 0;// 此处会产生异常

//          }

        }catch(Exception e) {

            System.out.println(id + "内部异常日志处理");

        }

        System.out.println(id + "内层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.servicewaiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

import com.sh.springboot.servicewaiceng.ServiceWaiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Component

publicclassServiceWaiCengImpl implements ServiceWaiCeng {

 

    @Autowired

    private ServiceNeiCeng snc;

 

    @Transactional

    publicvoid insertWaiCeng() {

                for (intj = 0; j < 8; j++) {

                    snc.insertNeiCeng(j, j + "姓名");

                    if (j == 4) {

                        inti = 2 / 0;// 此处会产生异常

                    }

                }

        System.out.println("外层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

打印执行结果:0~4内层打印正常,外层不打印

数据库结果:

总结:外部无try Catch、内部有try Catch的时候,外部异常,全部回滚

 

 

 

         2.外部无异常,内部有异常

                   修改Service内层和外层代码如下:

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.serviceneiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.bean.Person;

import com.sh.springboot.dao.PersonDao;

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Service

publicclassServiceNeiCengImpl implements ServiceNeiCeng {

 

    @Autowired

    PersonDaopersondao;

 

    @Transactional

    publicvoid insertNeiCeng(intid, String name) {

        try {

            Personperson= newPerson();

            person.setId(id);

            person.setName(name);

            persondao.insertPerson(person);

            if (id == 4) {

                inti = 2 / 0;// 此处会产生异常

            }

        }catch(Exception e) {

            System.out.println(id + "内部异常日志处理");

        }

        System.out.println(id + "内层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

package com.sh.springboot.servicewaiceng.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Transactional;

 

import com.sh.springboot.serviceneiceng.ServiceNeiCeng;

import com.sh.springboot.servicewaiceng.ServiceWaiCeng;

 

/**

 * Created by sh on 18/4/28.

 */

@Component

publicclassServiceWaiCengImpl implements ServiceWaiCeng {

 

    @Autowired

    private ServiceNeiCeng snc;

 

    @Transactional

    publicvoid insertWaiCeng() {

                for (intj = 0; j < 8; j++) {

                    snc.insertNeiCeng(j, j + "姓名");

//                  if(j == 4) {

//                      inti = 2 / 0;// 此处会产生异常

//                  }

                }

        System.out.println("外层正常执行");

    }

}

---------------------------------------------------------------------------------------------------------------------------------

打印执行结果:0~7内层打印执行正常,4内层有异常、被处理了,外层也正常打印

数据库结果:全部插入,无回滚

总结:外部无try Catch、内部有try Catch的时候,内部异常,事物失败(全部没有回滚)

    内外都异常:不用测了,结果是全部回滚,原因在后面有说明。

汇总以上8条(内外都异常自己思考,在此不做过多解释,后面的解释对内外都异常的情况也是有效的):

1.内外都无try Catch的时候,外部异常,全部回滚;

2.内外都无try Catch的时候,内部异常,全部回滚;

3.内外都有try Catch,外部异常,事物失败(走一半);

4.内外都有try Catch,内部异常,事物失败(数据全部插入);

5.外部有try Catch、内部无try Catch的时候,外部异常,不能回滚(事物错误);

6.外部有try Catch、内部无try Catch的时候,内部异常,全部回滚;

7.外部无try Catch、内部有try Catch的时候,外部异常,全部回滚;

8.外部无try Catch、内部有try Catch的时候,内部异常,事物失败(全部没有回滚)。

实际上,Service外层的insertWaiCeng()调用Service内层的 insertNeiCeng(int id, String name),由于spring事物的传播属性为默认的PROPAGATION_REQUIRED,所以执行Service外层的 insertWaiCeng() 的时候spring已经起了事务,这时调用Service内层的 insertNeiCeng(int id, Stringname),Service内层的insertNeiCeng(intid, String name)看到自己已经运行在 Service外层的insertWaiCeng()的事务内部,就不再起新的事务。假如Service内层的insertNeiCeng(int id, String name)运行的时候发现自己没有在事务中,他就会为自己分配一个事务。这样,在Service外层的insertWaiCeng()或者在Service内层的insertNeiCeng(int id, String name)内的任何地方出现异常,事务都会被回滚。

 

 

上面8条中的1、2、6、7事物可以成功。1很好理解,外部无try Catch且有异常直接全部回滚;2是内部异常抛给了调用者即外层,和1同理;6是外部有try Catch,所以内部自己分配一个事物,有异常则回滚;7同1。

 

3是内部不起事物,外部异常,无法回滚;4是异常全被处理了,所以数据会全部插入(事务失败);5和3一样,内部本身无异常,处理不处理都一样;8是内部的异常全被内部的try Catch处理了,所以事务失败。

附:外层方法中调取其他接口或者另外开启线程的操作,由于调取接口不能回滚,一定要放到最后来处理。

 

 

项目git地址:https://github.com/scarlett-8/springTransactional-

猜你喜欢

转载自blog.csdn.net/scarlett08/article/details/80864314