Spring(五) spring事务处理

Spring(五) spring事务处理

源码下载

一、spring的事务管理

1.1 什么是事务

​ 事务是指一组sql语句的集合, 集合中有多条sql语句
​ 可能是insert , update ,select ,delete, 我们希望这些多个sql语句都能成功,
​ 或者都失败, 这些sql语句的执行是一致的,作为一个整体执行

1.2 什么时候使用事务

当我的操作,涉及得到多个表,或者是多个sql语句的insert,update,delete。需要保证
  这些语句都是成功才能完成我的功能,或者都失败,保证操作是符合要求的。

注意: java中事务代码应该放在service类的业务方法上,因为业务方法会调用多个dao方法,执 行多个sql语句

1.3 JDBC与mybatis如何处理事务

​ jdbc访问数据库,处理事务 Connection conn ; conn.commit(); conn.rollback();
​ mybatis访问数据库,处理事务, SqlSession.commit(); SqlSession.rollback();
​ hibernate访问数据库,处理事务, Session.commit(); Session.rollback();

1.4 不同数据库中的事务处理方式的缺点

  1. 不同的数据库访问技术,处理事务的对象,方法不同,
    需要了解不同数据库访问技术使用事务的原理
  2. 掌握多种数据库中事务的处理逻辑。什么时候提交事务,什么时候回顾事务
  3. 处理事务的多种方法。

总结: 就是多种数据库的访问技术,有不同的事务处理的机制,对象,方法。

1.5 怎么解决不同技术的缺点

spring提供一种处理事务的统一模型, 能使用统一步骤,方式完成

​ 多种不同数据库访问技术的事务处理。

使用spring的事务处理机制,可以完成mybatis访问数据库的事务处理
使用spring的事务处理机制,可以完成hibernate访问数据库的事务处理。

二、spring如何处理事务

2.1 事务管理器

接口:PlatformTransactionManager ,定义了事务重要方法 commit ,rollback

实现类:spring把每一种数据库访问技术对应的事务处理类都创建好了。

​ 主要用到两个接口实现类:

  1. mybatis访问数据库—spring创建好的是DataSourceTransactionManager
  2. hibernate访问数据库----spring创建的是HibernateTransactionManager

使用方式:你需要告诉spring 你用是那种数据库的访问技术

​ 声明数据库访问技术对于的事务管理器实现类, 在spring的配置文件中使用声明

例如:你要使用mybatis访问数据库,你应该在xml配置文件中

  <!--声明式事务处理:和源代码完全分离-->
    <!--1.声明事务管理器对象-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="myDataSource"/>
    </bean>

2.2 说明事务类型

需要说明的事务属性有:

  1. 事务的隔离级别:有4个值。

    1. DEFAULT:采用 DB 默认的事务隔离级别。MySql 的默认为 REPEATABLE_READ; Oracle默认为 READ_COMMITTED。
    2. READ_UNCOMMITTED:读未提交。未解决任何并发问题。
    3. READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。
    4. REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读
    5. SERIALIZABLE:串行化。不存在并发问题。
  2. 事务的超时时间:表示一个方法最长的执行时间,如果方法执行时超过了时间,事务就回滚。
    单位是秒, 整数值, 默认是 -1. (一般不做修改

  3. 事务的传播行为: 控制业务方法是不是有事务的, 是什么样的事务的。
    7个传播行为,表示你的业务方法调用时,事务在方法之间是如何使用的。

    1. PROPAGATION_REQUIRED(常用,默认

      指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中

    2. PROPAGATION_REQUIRES_NEW(常用)

      总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕。

    3. PROPAGATION_SUPPORTS(常用)

      指定的方法支持当前事务,但若当前没有事务,也可以以非事务方式执行。

    4. PROPAGATION_MANDATORY

    5. PROPAGATION_NESTED

    6. PROPAGATION_NEVER

    7. PROPAGATION_NOT_SUPPORTED

2.3 事务提交事务,回滚事务的时机

  1. 当你的业务方法,执行成功,没有异常抛出,当方法执行完毕,spring在方法执行后提交事务。事务管理器commit

  2. 当你的业务方法抛出运行时异常或ERROR, spring执行回滚,调用事务管理器的rollback
    运行时异常的定义: RuntimeException 和他的子类都是运行时异常,

    ​ 例如:NullPointException , NumberFormatException

  3. 当你的业务方法抛出非运行时异常, 主要是受查异常时,提交事务
    受查异常:在你写代码中,必须处理的异常。例如IOException, SQLException

2.4 总结spring的事务

  1. 管理事务的是 事务管理和他的实现类
  2. spring的事务是一个统一模型
    1. 指定要使用的事务管理器实现类,使用
    2. 指定哪些类,哪些方法需要加入事务的功能
    3. 指定方法需要的隔离级别,传播行为,超时

需要为spring指定:项目中类的信息,方法的名称,方法的事务传播行为

三、spring框架中提供的两种事务处理方案

有两种方式:

  1. 使用 Spring 的事务注解管理事务(掌握)
  2. 使用 AspectJ 的 AOP 配置管理事务(掌握)

3.1 使用 Spring 的事务注解管理事务

适合中小项目使用的, 注解方案。

spring框架自己用aop实现给业务方法增加事务的功能, 使用@Transactional注解增加事务。
@Transactional注解是spring框架自己注解,放在public方法的上面,表示当前方法具有事务。
可以给注解的属性赋值,表示具体的隔离级别,传播行为,异常信息等等

使用 @Transactional 的步骤:

  1. 声明事务管理器(要指定dataSource,即之前声明数据源)

       <!--声明事务管理器-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!--连接数据库信息,指定数据源-->
            <property name="dataSource" ref="myDataSource"/>
        </bean>
    
  2. 开启事务注解驱动 tx结尾的driven(赋值事务管理器id)

    <!--开启事务注解驱动,告诉spring使用注解管理事务,创建代理对象
                  transaction-manager:事务管理器的id-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    
  3. service层在需要开启事务的public方法上加**@Transactional注解**

    /**
         * rollbackFor:表示发生指定的异常一定回滚.
         * 处理逻辑是:
         * 1) spring框架会首先检查方法抛出的异常是不是在rollbackFor的属性值中
         * 如果异常在rollbackFor列表中,不管是什么类型的异常,一定回滚。
         * 2) 如果你的抛出的异常不在rollbackFor列表中,spring会判断异常是不是RuntimeException,
         * 如果是一定回滚。
         */
    
    //使用的是事务控制的默认值, 默认的传播行为是REQUIRED,默认的隔离级别DEFAULT
    //默认抛出运行时异常,回滚事务
    //    @Transactional(
    //            propagation = Propagation.REQUIRED,
    //            isolation = Isolation.DEFAULT,
    //            readOnly = false,
    //            rollbackFor = {NullPointerException.class,
    //                    NotEnoughException.class}
    //    )
    @Transactional
    @Override
    public void buy(Integer goodId, Integer nums) {
    }
    

原理:spring使用aop机制,创建@Transactional所在的类代理对象,给方法加入事务的功能。

在你的业务方法执行之前,先开启事务,在业务方法之后提交或回滚事务,使用aop的环绕通知

 @Around("你要增加的事务功能的业务方法名称")
		 Object myAround(){
           开启事务,spring给你开启
			  try{
			     buy(1001,10);
				  spring的事务管理器.commit();
			  }catch(Exception e){
             spring的事务管理器.rollback();
			  }
			 
		 }

3.2 使用 AspectJ 的 AOP 配置管理事务(掌握)

​ 适合大型项目,有很多的类,方法,需要大量的配置事务,使用aspectj框架功能,

​ 在spring配置文件中声明类,方法需要的事务。这种方式业务方法和事务配置完全分离。

实现步骤:在xml配置文件中实现。

  1. 要使用的是aspectj框架,需要在pom文件中加入依赖

    pom.xml

    <!--aspectj依赖-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>5.2.15.RELEASE</version>
            </dependency>
    
  2. 声明事务管理器对象

      <!--声明式事务处理:和源代码完全分离-->
        <!--1.声明事务管理器对象-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="myDataSource"/>
        </bean>
    
  3. 配置事务通知:

    声明方法需要的事务类型(配置方法的事务属性【隔离级别,传播行为,超时】)

    <!--2.声明业务方法它的属性(隔离级别,传播行为,超时时间)
            id:自定义名称,表示 <tx:advice>和</tx:advice>之间的配置内容
            transaction-manager:事务管理器的id
        -->
        <tx:advice id="myAdvice" transaction-manager="transactionManager">
            <!--<tx:attributes>:配置事务属性-->
            <tx:attributes>
                <!--<tx:method name=""/>表示要给剧痛的方法配置事务属性,method可以有多个,分别给不同的方法配置事务属性
                    name:方法名称 , (1) 完整的方法名称,不带有包和类
                                   (2) 方法可以使用通配符,*表示任意字符
                    propagation: 传播行为,枚举值
                    isolation: 隔离级别
                    rollback: 你指定的异常类名,全限定类型,发生异常一定回滚
                -->
                <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
                           rollback-for="java.lang.NullPointerException,com.excep.NotEnoughException"/>
    
                <!--使用通配符,指定很多的方法-->
                <tx:method name="add*" propagation="REQUIRES_NEW"/>
                <!--指定修改方法-->
                <tx:method name="modify*"/>
                <!--指定删除方法-->
                <tx:method name="remove*"/>
                <!--查询方法,query,search,find-->
                <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
            </tx:attributes>
        </tx:advice>
    
  4. 配置增强器:

    指定将配置好的事务通知,织入给谁

    <!--配置aop-->
    <aop:config>
        <!--配置切入点表达式:指定哪些包中类,要使用事务,
                id:切入点表达式的名称,唯一值
                expression:切入点表达式,指定哪些类要使用事务 aspectj会创建代理对象
            -->
        <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/>
    
        <!--配置增加器,关联adivce和pointcut
                advice-ref:通知,上面的tx:advice那里的配置
                pointcut-ref=切入点表达式
            -->
        <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt"/>
    </aop:config>
    

四、思维导图

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LvhaoIT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值