理解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介绍提交至数据库
理解spring对事务的处理:传播性的更多相关文章
- 通俗的讲法理解spring的事务实现原理
拿房屋买卖举例,流程:销售房屋 -- 接待员 -- 销售员 -- 财务 售楼处 存放着所有待售和已售的房屋数据(数据源 datasource) 总经理 带领一套自己的班底,下属员工都听自己的,服务于售 ...
- 深入理解 Spring 事务原理
本文由码农网 – 吴极心原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 一.事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供 ...
- 深入理解 Spring 事务原理【转】
本文转自码农网 – 吴极心原创 连接地址:http://www.codeceo.com/article/spring-transactions.html 一.事务的基本原理 Spring事务的本质其 ...
- 理解 Spring 事务原理
转载:https://www.jianshu.com/p/4312162b1458 一.事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事 ...
- 深入理解Spring事务的那点事
Spring事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行: 获 ...
- Spring事务专题(四)Spring中事务的使用、抽象机制及模拟Spring事务实现
Spring中事务的使用示例.属性及使用中可能出现的问题 前言 本专题大纲如下: 对于专题大纲我又做了调整哈,主要是希望专题的内容能够更丰富,更加详细,本来是想在源码分析的文章中附带讲一讲事务使用中的 ...
- Spring的事务传播性与隔离级别以及实现事物回滚
一.事务的四个特性(ACID) 原子性(Atomicity):一个事务中所有对数据库的操作是一个不可分割的操作序列,要么全做,要么全部做. 一致性(Consistency): 数据不会因为事务的执行而 ...
- 理解 spring 事务传播行为与数据隔离级别
事务,是为了保障逻辑处理的原子性.一致性.隔离性.永久性. 通过事务控制,可以避免因为逻辑处理失败而导致产生脏数据等等一系列的问题. 事务有两个重要特性: 事务的传播行为 数据隔离级别 1.事务传播行 ...
- Spring事务的5种隔离级别和7种传播性
隔离级别 isolation,5 种: ISOLATION_DEFAULT,ISOLATION_READ_UNCOMMITTED,ISOLATION_READ_COMMITTED,ISOLATION_ ...
随机推荐
- SQL传数组到存储过程中
方法一 CREATE PROC D_t_Base_Employee @str varchar(100) as declare @sql varchar(1000) set @sql='DELETE E ...
- Nginx安装与升级(包括虚拟主机)
Nginx WEB服务器最主要就是各种模块的工作,模块从结构上分为核心模块.基础模块和第三方模块,其中三类模块分别如下: 核心模块:HTTP模块.EVENT模块和MAIL模块等: 基础模块:HTTP ...
- 【福利】微信小程序130个精选Demo合集
小编最近在开发小程序,也读到了不少优秀的小程序源码,项目中有些需求可以直接从源码里粘贴复制过来,虽然这样做不利于自己独立编写代码,但比较是给公司做项目啊,秉着效率第一的原则,简直没有什么比ctrl+c ...
- VM虚拟机全屏显示
在虚拟机中使用全屏界面会有更强的用户体验.在编辑该文章的时候就是在使用虚拟机windows2008 R2系统.我的笔记本是苹果双系统.虚拟机安装在win7 64位系统下 1.首先查看主机的屏幕分辨率 ...
- mongodb适用和不适用的应用场景
近期考虑把订单历史数据从Oracle数据库迁移到Nosql数据库做历史数据查询和分析,一天千万级数据.打算使用mongodb数据库.使用nodejs做查询和统计API,对并发请求量要求低,不知道有没有 ...
- Css盒模型有哪几部分,标准盒模型和IE盒模型有哪些区别
首先介绍Css的盒模型也就是标准盒模型(BOX Model) 包含了 内容(content) 内边距(padding) 边框(border) 外边框(margin) 这是大家经常用到的,也是现在的标准 ...
- BZOJ 1571 DP
思路: 预处理出在能力值为i的时候 滑雪一次的最小时间 f[i][j]表示i时间 j的能力值 最多的滑雪次数 我先用vector 把课程按起点push进去 1. for(int k=0;k<ve ...
- Exercise: PCA in 2D
Step 0: Load data The starter code contains code to load 45 2D data points. When plotted using the s ...
- Windows学习总结(1)——win10系统最新快捷键汇总
Win10新增功能快捷键大全: 贴靠窗口:Win + 左/右 > Win + 上/下 > 窗口可以变为 1/4 大小放置在屏幕 4 个角落. 切换窗口:Alt + Tab(不是新的,但任 ...
- Effective C++ 条款43
学习处理模板化基类里的名称 本节作者编写的意图在我看来能够总结成一句话,就是"怎样定义并使用关于模板类的派生过程,怎样处理派生过程出现的编译不通过问题". 以下我们看一段说明性的代 ...