zoukankan      html  css  js  c++  java
  • 理解spring对事务的处理:传播性

    所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。Spring 支持 7 种事务传播行为:

    • PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
    • PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
    • PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
    • PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
    • PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    • PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
    • PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作。

    Spring 默认的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。假设 ServiveX#methodX() 都工作在事务环境下(即都被 Spring 事务增强了),假设程序中存在如下的调用 链:Service1#method1()->Service2#method2()->Service3#method3(),那么这 3 个服务类的 3 个方法通过 Spring 的事务传播机制都工作在同一个事务中。

    spring 管理事务一般配置在service层、曾经用struts把事务配置在action层 导致系统并发卡死特别严重 分析了下原因:action层并发量过大、数据库经常锁死在某一块;

    spring 配置在service层研究:

    测试方法:查询---》更新-----》查询   分析数据在什么时候提交至数据库

     一  在同一个service中 互相调本类中的方法

    @Service
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class})  // 当标于类前时, 标示类中所有方法都进行事物处理
    public class LoginService extends BaseServiceImpl implements ILoginService {

        @Autowired
        private ILoginDao loginDao;

        @Override
        @Transactional(propagation = Propagation.NOT_SUPPORTED)
        public ResultBase login(SysUser sysUser) {
            ResultBase res=new ResultBase();
            SysUser user=(SysUser) loginDao.get(SysUser.class,sysUser.getUuid());
            res.setObj(user);
            res.setResult(ResultBase.RESULT_SUCC);
            res.setMessage("成功");
            return res;
        }
        @Transactional(propagation = Propagation.REQUIRED)
        public ResultBase update(SysUser sysUser) {
            ResultBase res=new ResultBase();
            loginDao.update(sysUser);
            res.setResult(ResultBase.RESULT_SUCC);
            res.setMessage("成功");
            return res;
        }
        @Transactional(propagation = Propagation.SUPPORTS)  //此方法用于测试 结果 数据库中在此方法走完才更新至数据库
        public ResultBase searchAndUpdate(SysUser sysUser) {
            ResultBase res=new ResultBase();
            res=login(sysUser);
            sysUser=(SysUser) res.getObj();
            sysUser.setLoginname("123");
            update(sysUser);
            res.setMessage("成功");
            return res;
        }

    二  在不同service中 互相调别的service中的方法:第一层事务传播使用NOT_SUPPORTED

    @Service
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class})  // 当标于类前时, 标示类中所有方法都进行事物处理
    public class OperateService extends BaseServiceImpl implements IOperateService {

        @Autowired
        private ILoginService loginService;
        
        /**
         * 事务测试:一个service 调另一个 service 何时更新数据
         * @param sysUser
         * @return
         */
        @Override
        @Transactional(propagation = Propagation.NOT_SUPPORTED)
        public ResultBase TransactionTset(SysUser sysUser) {
            ResultBase res=new ResultBase();
            res=loginService.login(sysUser);
            sysUser=(SysUser) res.getObj();
            sysUser.setLoginname("123");
            loginService.update(sysUser);
            res=loginService.login(sysUser);
            res.setMessage("成功");
            return res;
        }

    结果:方法执行完    loginService.update(sysUser);后数据已经提交  注意:TransactionTset方法@Transactional(propagation = Propagation.NOT_SUPPORTED)设置不使用事务

    三  在不同service中 互相调别的service中的方法:第一层事务传播使用REQUIRED

    @Service
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class})  // 当标于类前时, 标示类中所有方法都进行事物处理
    public class OperateService extends BaseServiceImpl implements IOperateService {

        @Autowired
        private ILoginService loginService;
        
        /**
         * 事务测试:一个service 调另一个 service 何时更新数据
         * @param sysUser
         * @return
         */
        @Override
        @Transactional(propagation = Propagation.REQUIRED)
        public ResultBase TransactionTset(SysUser sysUser) {
            ResultBase res=new ResultBase();
            res=loginService.login(sysUser);
            sysUser=(SysUser) res.getObj();
            sysUser.setLoginname("123");
            loginService.update(sysUser);
            res=loginService.login(sysUser);
            res.setMessage("成功");
            return res;
        }

    结果:方法执行到最后数据才提交 说明事务已经传播到到下一个service 而且属于同一事务  注意:TransactionTset方法@Transactional(propagation = Propagation.REQUIRED)设置使用REQUIRED事务

    结论:在同一个事务中 前者改变了数据(新增或者更新) 下面service或者自身的方法再次查询 数据是已经改变了、但是service没有走到最后 数据库的数据还是没变化的

    TUser user1=(TUser) operateDao.get(TUser.class, sysUser.getId());
            user1.setPassword("12222");
            operateDao.update(user1);
            user1=(TUser) operateDao.get(TUser.class, sysUser.getId());
            
            Map<String,Class> classMap=new HashMap<String,Class>();
            StringBuffer sql=new StringBuffer("select u.* from t_user as u where id='"+sysUser.getId()+"'");
            PageModel pm=operateDao.searchResultBySql(sql.toString(),null, 0, 0);
    /*        StringBuffer sql=new StringBuffer("select {u.*} from t_user as u where id='"+sysUser.getId()+"'");
            classMap.put("u", TUser.class);
            PageModel pm=operateDao.searchResultBySql(sql.toString(),null, classMap, 0, 0);
    */        System.out.println("11");
            System.out.println("11");
            System.out.println("11");
            System.out.println("11");
            return res;

    为了测试 同一事务中先更新再查询 结果:

           映射对象查询到update后的数据、虽然事务未提交

            纯sql查询的是事务未提交前的数据

         数据在service介绍提交至数据库

  • 相关阅读:
    Rainmeter 雨滴桌面 主题分享
    行人检測之HOG特征(Histograms of Oriented Gradients)
    const和readonly差别
    ADB命令解析
    Java实现 蓝桥杯VIP 算法训练 接水问题
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
  • 原文地址:https://www.cnblogs.com/lykxqhh/p/5703626.html
Copyright © 2011-2022 走看看