所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。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介绍提交至数据库

最新文章

  1. 谈谈php里的IOC控制反转,DI依赖注入
  2. Design6:选择合适的数据类型
  3. jquery满屏滚动代码
  4. Hibernate入门学习(二)
  5. Delphi开发的IP地址修改工具
  6. linux的SVN搭建与同步
  7. Asp.Net 之 缓存机制
  8. java集合简介
  9. ASP.net与SQLite数据库通过js和ashx交互(连接和操作)
  10. juce AsyncUpdaterMessage 分析
  11. 21. leetcode 492
  12. JS判断不同操作系统显示不同样式css
  13. Coursera, Big Data 3, Integration and Processing (week 5)
  14. RedHat 6配置yum源为网易镜像(转)
  15. thinkphp3.2升级至thinkphp5.0.24
  16. TOPWAY智能彩色TFT液晶显示模块
  17. Python isspace() 方法检测字符串是否只由空格组成。
  18. ES6必知必会 (三)—— 数组和对象的拓展
  19. BZOJ2034 【2009国家集训队】最大收益
  20. group by 并且 count(1)的linq写法

热门文章

  1. linux 10201 ocfs RAC 安装+升级到10205
  2. MySQL中好用的GROUP_CONCAT函数
  3. 菜鸟之路——Java并发(二)ThreadLocal
  4. amlogic M8操作gpio bank
  5. Split Shape by Plane in OpenCASCADE
  6. 比MD5 和HMAC还要安全的加密 - MD5 加时间戳
  7. js02---字符串
  8. JS --- 延迟加载的几种方式
  9. 英语 用on还是/at/还是in
  10. Kinect 开发 —— 面部追踪