zoukankan      html  css  js  c++  java
  • 关于spring事务提交的传播行为

    保持事务一致性

    首先我们的spring配置文件的配置如上图,除了指定方法外其他都是受事务控制,在某个aop切面配置路径下,如果方法有异常 则进行回滚,并且还是方法内涉及到增删改的回滚;

    关于事务的使用:

    为了保证整体方法的事务一致性,方法内如果有多处对数据进行增删改,那么最好提取成一个service进行事务控制,如果全成功,则全部提交,否则全部回滚;

    以下主要是在工作中遇到的实际问题:

    Service层test()方法:

    while(条件){
        // 满足条件,则对数据库增删改
    }

    由于公司限制,不允许贴代码

    这里我在Service中进行一个wile循环,如果满足条件,我就对满足条件的这一条数据进行多次增删改;

    这里有个问题,不论是否出现异常,我都catch处理了,导致了事务的大量堆积,因为while循环没跑完,test()方法没执行完,事务并不会进行提交,如果while循环中的数据量过大,很有可能造成锁库锁表的可能,会造成很多问题;

    实际工作中的解决方案:

    方案一:向上抽取,分割成多个独立事务

    我们将test()方法中的while(条件)循环向上抽取,抽取至Controller层中,然后对满足while条件的每一条数据处理时放至一个service中,这样每次循环一次时,就整体对while中的处理提交一次事务,完美解决;

    方案二:事务传播,嵌套事务,创建新的事务

    带有注解@Transactional(propagation=Propagation.REQUIRES_NEW)的方法走完之后,数据就会被提交入库

     while循环中如果对数据库的交互仅有一次,其他都为查询时,我建议使用这个注解,也就是说 service方法中嵌套另一个service方法,第二个service方法加上此注解,那么第二个servie方法就是新创建的事务,并进行独立提交入库;

    另外需要注意方法内部调用@Transactional(propagation=Propagation.REQUIRES_NEW)注解不生效,比如A和B都在同一个方法中,A调用B,B方法是此注解,则不生效。同样,AOP拦截也拦截不到B

    ----REQUIRES_NEW传播说明-----------------------------------------------------------------------------------------
    @Service
    public class TestUserImpl implements TestUser {
    
        @Transactional(propagation=Propagation.REQUIRED )
        public void saveUserAll(){
            //1、保存用户--
            this.saveUser();
            //2--情况一、记录日志的方法在本service-新事务
            this.saveUserLog();
            //2--情况二、记录日志的方法在另一个LogService-新事务
            logService.saveUserLog();
    
             int a=1/0;//异常
        }
       
        public void saveUser() {
            User user = new User();
            userDao.save(user);
    
        }
    
        @Transactional(propagation= Propagation.REQUIRES_NEW)
        public void  saveUserLog() {
            UserLog log = new UserLog();
            UserLogDao.save(log);
        }
    }
    ------------------------------saveUserAll在位置一,出异常,执行结果------------------------------------
           情况一、记录日志的方法在本service,saveUser回滚,saveUserLog回滚
           情况二、记录日志的方法在另一个LogService-新事务,saveUser回滚,saveUserLog不回滚
    总结:要想总的方法的异常不影响 新事务方法REQUIRES_NEW的提交,新事务的方法,要写在另一个service里

    以上是个人工作中的一些见解和想法,如有错误,欢迎指正。

  • 相关阅读:
    给文章生成二维码
    用HTML5 Canvas做一个画图板
    失败多少次不要紧,人们只会记住你成功的那一次
    关于读大学的意义
    卸载Anaconda
    Anaconda基本命令
    plt.imshow()
    matplotlib不显示图片
    在Anaconda环境下使用Jupyter Notebook
    join()
  • 原文地址:https://www.cnblogs.com/AlanWilliamWalker/p/11254393.html
Copyright © 2011-2022 走看看