Spring5学习随笔-事务属性详解(@Transactional)

打印 上一主题 下一主题

主题 878|帖子 878|积分 2634

学习视频:【孙哥说Spring5:从设计模式到基本应用到应用级底层分析,一次深入浅出的Spring全探索。学不会Spring?只因你未遇见孙哥】
第三章、Spring的事务处理

1.什么是事务?

事务是保证业务操作完整性的一种数据库机制
事务的4特点:ACID

  • A 原子性
  • C 一致性
  • I 隔离性
  • D 持久性
2.如何控制事务

JDBC:
Connection.setAutoCommit(false)
Connection.commit();
Connection.rollback();
Mybatis:
Mybatis自动开启事务
SqlSession(底层还是Connection).commit();
sqlSession(底层还是Connection).rollback();
结论:控制事务的底层 都是Connection对象完成的
3.Spring控制事务的开发

Spring是通过AOP的方式进行事务开发

  • 原始对象
    1. public class XXXUserServiceImpl{
    2.         1.原始对象 ---> 原始方法  --->核心功能(业务处理+DAO调用)
    3.         2.DAO作为Service的成员变量,依赖注入的方式进行赋值
    4. }
    复制代码
  • 额外功能
    1. 下面的额外功能封装在org.springframework.jdbc.datasource.**DataSourceTransactionManager
    2. 应用的过程需要注入DataSource**
    3. 1.MethodInterceptor
    4. public Object invoke(MethodInvocation invocation){
    5.         try{
    6.                 Connection.setAutoCommit(false);
    7.                 Object ret = invocation.proceed();
    8.                 Connection.commit();
    9.                 return ret;
    10.         }catch(Exception e){
    11.                 Connection.rollback();
    12.         }
    13. }
    14. 2. @Aspect
    15.          @Around
    复制代码
  • 切入点
    1. @**Transactional**
    2. 事务的额外功能能加入给那些业务方法
    3. 1. 类上:类中所有的方法都会加入事务
    4. 2. 方法上:这个方法加入事务
    复制代码
  • 组装切面

    • 切入点
    • 额外功能


4.Spring控制事务的编码


  • 搭建开发环境(jar)
  1. <dependency>
  2.     <groupId>org.springframework</groupId>
  3.     <artifactId>spring-tx</artifactId>
  4.     <version>5.1.14.RELEASE</version>
  5. </dependency>
复制代码

  • 编码
  1. <bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="dataSourceTransactionManager" >
  5.     <property name="dataSource" ref="dataSource"/>
  6. </bean>
  7. 3.切入点
  8. @Transactional
  9. public class UserServiceImpl implements UserService {
  10.     private UserDao userDao;
  11. <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
复制代码

  • 细节

    进行动态代理底层实现的切换  proxy-target-class
    默认false:JDK  true: Cglib
第四章、Spring中的事务属性(Transaction Attribute)

1.什么是事务属性

属性:描述物体特征的一系列值
性别 身高 体重…
所谓的事务属性指的是描述事务特征的一系列值

  • 隔离属性
  • 传播属性
  • 只读属性
  • 超时属性
  • 异常属性
2.如何添加事务属性

@Transactional(isolation(隔离属性)=,propagation(传播属性)=,readOnly(只读属性)=,timeout(超时属性)=,rollbackFor=,noRollbackFor=);
3.事务属性详解

1.隔离属性(ISOLATION)


  • 隔离属性的概念
    概念:他描述了事务解决并发问题的特征

    • 什么是并发
      指的是多个事务(用户)在同一时间,访问操作了相同的数据
      重点 同一时间:微小的时间内  0.0000几秒 微小前、后
    • 并发会产生那些问题

      • 脏读
      • 不可重复读
      • 幻影读

    • 并发问题如何解决
      通过隔离属性解决,隔离属性设置不同的值,解决并发处理过程中的问题。

  • 事务并发产生的问题

    • 脏读
      指的是一个事务/用户读取了另外一个事务/用户中没有提交的数据。会在本事务中产生不一致的问题
      解决方案Transactional(isolation=Isolation.READ.COMMITTED)
      本质:只读取已提交的数据
    • 不可重复读
      一个事务中,多次读取相同的数据,但是读取结果不一样,会在本事务中产生数据不一致的问题
      注意:1.不是脏读 2.在一个事务中
      解决方案:@Transactional(isolation=Isolation.REPEATABLE_READ)
      本质:对应数据库底层的行锁(第一个人在读取数据时,其他人都得等第一个人处理完)
    • 幻影读
      一个事务中,多次对整表进行查询统计,但是结果不一样,会在本事务中产生数据不一致的问题。
      解决方案:@Transactional(isolation=Isolation.SERIALIZABLE)
      本质对应数据库底层的表锁
    • 总结
      并发安全:SERIALIZABLE>REPEATABLE_READ>READ.COMMITTED
      运行效率:READ.COMMITTED>REPEATABLE_READ>SERIALIZABLE

  • 数据库对于隔离属性的支持
    隔离属性的值MySQLOracleIsolation.READ.COMMITTED✔️✔️Isolation.REPEATABLE_READ✔️❌Isolation.SERIALIZABLE✔️✔️Oracle不支持REPETABLE_READ值  采用的是多版本比对的方式 解决不可重复读的问题
  • 默认隔离属性
    ISOLATION_DEFAULT:会调用不同数据库所设置的默认隔离属性
    例如:如果使用MYSQL 默认隔离属性:REPEATABLE_READ,Oracle:READ_COMMITTED

    • 查看数据库默认隔离属性

      • MySQL
        1. 8.0版本以前:select @@tx_isolation
        2. 8.0版本之后:select @@transaction_isolatio
        复制代码


  • 隔离属性在实战中的建议
    推荐使用Spring指定的ISOLATION——DEFALUT

    • MySQL   repeatbale_read
    • Oracle READ_COMMITED
    未来中的实战中,并发访问情况 很低(前提就是海量用户
    如果真遇到并发问题,可以使用乐观锁
    Hibernate(JPA) Version
    MyBatis  通过拦截器自定义开发

2.传播属性(PROPAGATION)


  • 传播属性的概念
    概念:他描述了事务解决嵌套问题的特征
    什么叫做事物的嵌套:他指的是一个大的事务中,包含若干个小的事务
    问题:大事务中融入了很多小的事务,他们彼此影响,最终导致外部大的事务,丧失了事务的原子性
  • 传播属性的值及其用法
    不管属性是什么,其中心思想是保证同一时间只会有一个事务的存在
    传播属性的值外部不存在事务外部存在事务用法备注REQUIRED开启新的事务融合到外部事务中@Transactional(propagation=Propagation.REQUIRED主要应用于增删改方法SUPPORTS不开启新的事务融合到外部事务中@Transactional(propagation=Propagation.SUPPORTS一般应用查询方法中REQUIRES_NEW开启新的事务挂起外部事务,创建新的事务@Transactional(propagation=Propagation.REQUIRES_NEW日志记录方法中NOT_SUPPORTED不开启新的事务挂起外部事务@Transactional(propagation=Propagation.NOT_SUPPORTED极其不常用NEVER不开启新的事务抛出异常@Transactional(propagation=Propagation.NEVER极其不常用MANDATORY抛出异常融合到外部事务中@Transactional(propagation=Propagation.MANDATORY极其不常用
融合指的是:放弃自己的事务,以外部的事务为准

  • 默认的传播属性
    REQUIRED是传播属性的默认值
  • 推荐传播属性的使用方式
    增删改 方法:直接使用默认值REQUIRED
    查询  操作:显示指定传播属性的值SUPPORTS
3.只读属性(readOnly)

针对于只进行查询操作的业务方法,可以加入只读属性,提供运行效率
默认值:false
4.超时属性(timeout)

指定了事务等待的最长时间

  • 为什么事务要进行等待呢?
    因为在当前事务访问数据时,有可能访问的数据是被别的事务进行加锁的处理,那么此时本事务就必须进行等待
  • 等待时间:秒
  • 如何应用 @Transactional(timeout=2)
  • 超时属性的默认值:-1
    最终由对应的数据库来指定默认值,一般使用默认值
5.异常属性

Spring事务处理过程中
默认 对于RuntimeException及其子类 采用的是回滚的策略
默认 对于Exception及其子类 采用的是提交的策略
想要改变默认的策略,可以设置两个属性

  • rollbackFor(回滚) ={java.lang.Exception,xxx,……};
  • noRollbackFor(不回滚)=
  1. @Transactional(rollbackFor = {Exception.class},noRollbackFor = {RuntimeException.class})
复制代码
建议:实战中使用RuntimeException及其子类 使用事务异常属性的默认值,实际开发很少改变策略
4.事务属性常见配置总结


  • 隔离属性  默认值
  • 传播属性  Required(默认值)增删改   Supports 查询操作
  • 只读属性  readOnly false 增删改   查询用true
  • 超时属性  默认值:-1
  • 异常属性  默认值
后续实战当中的建议:增删改操作 @Transactional
而对于查询操作  @Transactional(propagation=Propagation.SUPPORTS,readOnly=true)
5.基于标签的事务配置方式(事务开发的第二种形式)


  • 基于注解 @Transaction的事务配置回顾
  1. <bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="dataSourceTransactionManager" >
  5.     <property name="dataSource" ref="dataSource"/>
  6. </bean>
  7. 3.切入点
  8. @Transactional
  9. public class UserServiceImpl implements UserService {
  10.     private UserDao userDao;
  11. <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
复制代码

  • 基于标签的事务配置
  1. <bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="dataSourceTransactionManager" >
  5.     <property name="dataSource" ref="dataSource"/>
  6. </bean>
  7. <tx:advice id="txAdvice" transacation-manager="dataSourceTransactionManager">
  8.                 <tx:attributes>
  9.                                 <tx:method name="register" isolation="DEFAULT" propagation=""/>
  10.                                 <tx:method name="login"...../>
  11.                 </tx:attributes>
  12. </tx:advice>
  13. <aop:config>
  14.                 <aop:pointcut id="pc" expression="execution(* com.baizhi.service.UserServiceImpl.register(..))"/>
  15.                 <aop:advisor advice-ref="" pointcut-ref="">
  16. </aop:config>
复制代码

  • 基于标签的事务配置在实战中的应用方式
    1. <bean id="userService" >
    2.     <property name="userDao" ref="userDao"/>
    3. </bean>
    4. <bean id="dataSourceTransactionManager" >
    5.     <property name="dataSource" ref="dataSource"/>
    6. </bean>
    7. **编程的时候 service 负责进行增删改操作的方法 都以modify开头
    8.                                                 查询操作 命名无所谓  用*号代替
    9. 可以将特殊事务的事务放在前面**
    10. <tx:advice id="txAdvice" transacation-manager="dataSourceTransactionManager">
    11.                 <tx:attributes>
    12.                                 <tx:method name="register" />
    13.                                 <tx:method name="modify*"/>
    14.                                 <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
    15.                 </tx:attributes>
    16. </tx:advice>
    17. 使用包切入点,应用的过程中 service放置到service包中
    18. <aop:config>
    19.                 <aop:pointcut id="pc" expression="execution(* com.baizhi.service..*.*(..))"/>
    20.                 <aop:advisor advice-ref="" pointcut-ref="">
    21. </aop:config>
    复制代码

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

耶耶耶耶耶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表