spring事务详解(基于注解和声明的两种实现方式)
Spring事务( Transaction )
事务的概念
事务是一些sql语句的集合,作为一个整体执行,一起成功或者一起失败。
使用事务的时机
一个操作需要多天sql语句一起完成才能成功
程序中事务在哪里说明
加在业务类的方法上面(public方法上面),表示业务方法执行时,需要事务的支持。
不同的事务管理器
不同的数据库访问技术,处理事务是不同的
使用
jdbc访问数据库,事务处理public void updateAccount(){
Connection con = .....;
con.setAutoCommit(false);
state.insert();
state.update();
state.commit();
con.setAutoCommit(true);
}
MyBatis执行数据库,处理事务
public void updateAccount(){
SqlSession sqlSession = SqlSessionFactory.openSession(false);
try{
sqlSession.insert(...);
sqlSession.update(...);
sqlSession.commit();
}catch(Exception e){
sqlSession.rollback();
}
}
spring统一管理事务,把不同的数据库访问技术的事务处理统一起来
使用spring的事务管理器,管理不同数据库访问技术的事务处理。开发人员只需要掌握spring的事务处理一个方案,就可以实现使用不同数据库访问技术的事务管理。
尽管事务面向的是spring,有spring管理事务,做事务提交和回滚。
spring事务管理器
spring框架使用事务管理器对象,管理所有的事务。
事务管理器接口: PlatFormTransactionManager
作用 :定义了事务的操作,主要是commit() , rollback()
事务管理器有很多的实现类:一种数据库访问计数有一个实现类。由实现类具体完成事务的提交,回滚。
这意味着:JDBC或者MyBatis访问数据库有自己的事务管理实现类:DataSourceTransactionManager
hibernate框架,他的事务管理器实现类:HibernateTransactionManager
事务管理器的工作方式
spring集中统一管理事务,分配管理事务给具体的事务管理器对象。
事务提交和回滚的时机
当业务正常执行的时候,没有异常,事务是提交的。如果业务代码中出现了运行时异常,事务会发生回滚。
异常的分类:
- Error : 错误,回滚事务
- Exception:
- 运行时异常:RuntimeException和他的子类都是运行时异常,在程序执行过程中抛出的异常
- 受查异常:在编写代码时需要处理的异常(编译都无法通过),会提交事务。
方法抛出运行时异常事务回滚,其他的情况都是执行事务。
spring事务管理的实现方式:AOP中的环绕通知
环绕通知:在目标方法的前后都可以增加功能,不需要修改代码。
// spring给业务方法在执行时,增加事务的切面功能(一下为大致的实现步骤,不是真正的执行代码)
@Around("execution(* com.wang.*.*(..))")
public Object myAround(ProceedingJoinPoint pjp){
try{
PlatformTransactionManager.beginTransaction(); // 使用spring的事务管理器,开启事务
pjp.proceed(); // 执行目标方法
PlatformTransactionManager.commit(); // 业务方法正常执行,事务提交
}catch(Exception e){
PlatformTransactionManager.roolback(); // 业务方法非正常执行,事务回滚
}
}
事务定义接口(TransactionDefinition )
事务定义接口TransactionDefinition中定义了事务描述相关的三类常量:事务隔离级别,事务传播行为,事务默认超时时限,及他们的操作。
给业务方法说明事务的属性。
隔离级别
定义
控制事务之间的影响速度
具体值
DEFAULT:采用DB默认的事务隔离级别。Mysql的默认为REPEATABLE_READ,Oracle默认为READ_COMMITTEDREAD_UNCOMMITTED:读未提交。未解决任何并发问题READ_COMMITTER:读已提交。解决脏读,存在不可重复读和幻读REPETABLE_READ:可重复读。解决脏读,不可重复读,存在幻读SERIALIZABLE:串行化。不存在并发问题。
事务超时时间
以秒为单位,整数值,默认为-1
超时时间:表示一个业务方法最长的执行时间,到达时间没有执行完毕,spring会回滚事务。
传播行为
传播行为有7个值
定义:业务方法在调用的时候,事务在方法之间的传递和使用。
使用传播行为,表示方法有无事务。
PROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEWPROPAGATION_SUPPORTS以上三个需要掌握
PROPAGATION_MANDATORYPROPAGATION_NESTEDPROPAGATION_NEVERPROPAGATION_NOT_SUPPORTED
- PROPAGATION_REQUIRED:spring默认传播行为,方法在调用的时候,如果存在事务就是用当前的事务,如果没有事务,就新建一个事务,方法在新事务中执行。
- PROPAGATION_SUPPORTS: 方法有事务可以正常执行,没有事务也可以正常执行。(查询操作)
- PROPAGATION_REQUIRES_NEW:方法需要一个新事务。如果调用方法的时候,存在一个事务,则原来的事务暂停,知道新事务执行完毕。如果方法调用的时候,没有事务,则新建一个事务,在新事务中执行代码。
spring框架使用自己的注解@Transactional控制事务
@Transactional注解,使用注解的属性控制事务(隔离级别,传播行为,超时)
其中的属性:
propagation:事务的传播行为,他使用的Propagation类的枚举值,例如:Propagation.REQUIRED;isolation:表示隔离级别,使用Isolation类的枚举值,表示隔离级别,默认是:Ioslation.DEFAULT;readOnly:boolean类型的值,表示数据库操作是不是只读的,默认为falsetimeout:事务超时,默认是-1,整数值,单位是秒,例如:timeout=20;rollbackFor:表示回滚的异常类列表,他的值是一个数组,每个值是异常类型的class。rollbackForClassName:表示回滚的异常类列表,是String类型的值noRollbackFor:不需要回滚的异常类列表,是class类型的noRollbackForClassName:不需要回滚的异常类列表,是String类型的值
该注解放置的位置:
- 在业务方法上面,实在public方法上面(大多数)
- 在类的上面(几乎见不到)
注解的使用步骤
在spring配置文件中,声明事务的内容;
声明事务管理器,说明使用哪个事务管理器对象;
声明使用注解管理事务,开启注解驱动
在类的源代码中,加入
@Transactional
事务的控制模式:
- 编程式,在代码中编程控制事务
- 声明式事务,不用编码
步骤一:
<!--声明事务管理器(连接到数据库,做事务提交,事务回滚)-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<!--指定数据源-->
<property name="dataSource" ref="myDataSource"/>
</bean>
<!--开启事务注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--最后导入的包是以tx结尾-->
步骤二:
在具体的方法上加上@Transactional注解
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT,
readOnly = false,
timeout = 20,
rollbackFor = {NullPointerException.class}
)
@Override
public void buy(Integer goodId, Integer amount) throws Exception {
System.out.println("buy方法的执行");
Sale sale = new Sale();
sale.setGid(goodId);
sale.setNums(amount);
// 生成销售记录
saleDao.insertSale(sale);
// 查询商品
Good good = goodDao.selectById(goodId);
if (good == null){
throw new Exception("商品不存在");
}else if (good.getAmount() < amount){
throw new Exception("库存不足");
}
// 更新库存
Good good1 = new Good();
good1.setId(goodId);
good1.setAmount(amount);
goodDao.updateGood(good1);
System.out.println("buy方法的完成");
}
rollbackFor说明
- 框架首先检查方法抛出的异常是不是在rollbackFor数组中,如果在一定会发生回滚;
- 如果方法抛出的异常不在rollbackFor数组中,框架会继续检查抛出的异常是不是RuntimrException,如果是
RuntimeException,一定会发生回滚。
使用rollbackFor可以实现发生受检查异常时让其发生回滚。
注解的使用特点
直接使用@Transactional会使用默认值
- spring框架自己提供的事务控制
- 适合中小型项目,注解都放置在了源代码中,不利于优化
- 使用方便效率高
使用Aspectj框架在spring配置文件中,声明事务控制
使用aspectj的aop,声明事务控制叫做声明式事务
使用步骤
- 加入
spring-aspectj的依赖 - 在
spring的配置文件声明事务属性- 声明事务管理器
- 声明业务方法需要的事务属性
- 声明切入点表达式
步骤
基本上是模板化的方法
<!--声明式事务-->
<!--1.声明事务管理器-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager2">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!--2.声明业务方法的事务属性(隔离级别,传播行为,超时)
id:给业务方法配置事务段代码起个名字,唯一值
transaction-manager:事务管理器的id
-->
<tx:advice id="serviceAdvice" transaction-manager="transactionManager2">
<!--给具体的业务方法增加事务的说明-->
<tx:attributes>
<!-- 给具体的业务方法,说明他需要的事务属性
name:业务方法名称,配置name的值 1.业务方法的名称(类中的某一个方法) 2.带有部分通配符的方法名称 3.使用*
propagation:指定传播行为
isolation:隔离级别
read-only:是否只读,默认为false
timeout:超时时间
rollback-for:指定回滚的异常类列表,使用的异常类的全限定名称(多个异常时用都好分割)
-->
<tx:method name="buy"
isolation="DEFAULT"
propagation="REQUIRED"
timeout="20"
rollback-for="java.lang.NullPointerException"
/>
<!--在业务方法有命名规则的时候,可以对一些方法使用事务-->
<tx:method name="add*" propagation="REQUIRED" timeout="20" isolation="DEFAULT"/>
<tx:method name="delete*" propagation="REQUIRED" timeout="20" isolation="DEFAULT"/>
<!--以上方法以外的-->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!--通过上述方法的声明,但是我们并不知道是哪个类的方法,让上述声明生效的方法:切入点表达式-->
<!--声明切入点表达式:表示哪些包中的哪些类的方法参与事务-->
<aop:config>
<!--声明切入点表达式
expression:切入点表达式,表示哪些类中的哪些方法要参与事务
id:切入点表达式的名称,唯一值
-->
<aop:pointcut id="servicePointCut" expression="execution(* *..service..*.*(..))"/>
<!-- 关联切入点表达式和事务的通知-->
<aop:advisor advice-ref="serviceAdvice" pointcut-ref="servicePointCut"/>
</aop:config>
优缺点
缺点:理解难,配置复杂
优点:代码和事务分开。控制事务源代码不用修改。
能快速的了解和掌握项目的全部事务。适合大型项目。
spring事务详解(基于注解和声明的两种实现方式)的更多相关文章
- spring事务详解(二)简单样例
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...
- spring事务详解(三)源码详解
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...
- spring事务详解(一)初探事务
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 引子 很多 ...
- spring事务详解(五)总结提高
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.概念 ...
- spring事务详解(四)测试验证
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...
- spring事务详解(二)实例
在Spring中,事务有两种实现方式: 编程式事务管理: 编程式事务管理使用底层源码可实现更细粒度的事务控制.spring推荐使用TransactionTemplate,典型的模板模式. 申明式事务管 ...
- Spring、Spring事务详解;使用XML配置事务
@Transactional可以设置以下参数: @Transactional(readOnly=false) // 指定事务是否只读的 true/false @Transactional(rollba ...
- 【转】Spring事务详解
1.事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交,那在没有Spring帮我们管理事务 ...
- Spring 事务详解
实现购买股票案例: 一.引入JAR文件: 二.开始搭建分层架构---创建账户(Account)和股票(Stock)实体类 Account: ? 1 2 3 4 5 6 7 8 9 10 11 12 1 ...
随机推荐
- Java--面向对象设计
[转载自本科老师上课课件] 问题一: 在一个软件的功能模块中,需要一种图像处理的功能.该图像处理的策略(如何处理)与图像的内容是相关的.如:卫星的运行图片,使用策略A处理方式,如果是卫星内云图片,则需 ...
- 微服务技术栈简单介绍,Eureka和Ribbon的引入和使用
一.了解微服务架构 1.微服务技术栈 整体框架 整体学习规划路线2.微服务与单体架构的区别 单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署 优势 结构简单 部署成本低 缺点 耦合度高, ...
- Diary -「CSP 2019 J/S」 游记
\(\text{Day 0}\) 试机, 总体感觉不错, 至少不像初一时候的紧张, 毕竟是中青年选手了 ( ? ) 当晚睡得挺好, 虽然是冲着一等奖去的, 但还是没有给自己过多的思想包 ...
- 用 Beep 函数让主板“唱”《生日歌》
用 Beep 函数,让你的主板也会"唱歌".Beep 可以通过控制主板扬声器的发声频率和节拍来演奏美妙的旋律.本文就通过C#演示,调用Beep函数,演奏生日快乐歌.首先我们来看下 ...
- 今天你花里胡哨了吗 --- 定制属于自己的linux ssh迎宾信息
请开始你的表演 linux-oz6w:~ # cat << 'eof' > /etc/profile.d/ssh-login-info.sh #!/bin/sh # 输出一个图像 e ...
- MySQL架构原理之存储引擎InnoDB线程模型
如下图示,为InnoDB线程模型示意图: 1.IO Thread 在InnoDB中使用了大量的AIO(Async IO)来做读写处理,这样可以极大提高数据库的性能.其提供了write/read/ins ...
- JAVA8学习——深入浅出方法引用(学习过程)
方法引用:method reference 先简单的看一下哪里用到了方法引用: public class MethodReferenceTest { public static void main(S ...
- CobaltStrike逆向学习系列(2):Stageless Beacon 生成流程分析
这是[信安成长计划]的第 2 篇文章 关注微信公众号 [信安成长计划] 0x00 目录 0x01 Patch Beacon 0x02 Patch Loader 0x03 文件对比 0x04 流程图 C ...
- yaml语法及格式校验
基本语法 1.yml文件以缩进代表层级关系 2.缩进不允许使用tab只能使用空格 3.空格的个数不重要,只要相同层级的元素左对齐即可 4.大小写敏感 5.数据格式为,名称:(空格)值 也就是说,如果冒 ...
- kali Linux openvas忘记密码的解决方法
1.先删除默认的admin帐号root@xxs:~# openvasmd --delete-user=admin User deleted. 2.创建admin帐号,默认会生成密码root@xxs:~ ...