文章目录
Spring—事务处理
-
什么是事务
- mysql中提出事务,事务是指一组sql语句的集合,集合中有多条sql语句
- 可能是insert,update,select,delete,我们希望这些多个sql语句都能成功或者失败,这些sql语句的执行是一致的,作为一个整体执行
-
什么时候想到使用事务
- 当操作涉及到多个表,或者多个sql语句的insert,update,select,delete。需要保证这些语句都是成功才能完成功能,或者都失败,保证操作是符合要求的
- 在Java代码中写程序,控制事务, 此时事务应该放在service类的业务方法上,因为业务方法会调用多个dao方法,执行多个sql语句
-
通常使用JDBC访问数据库,还是mybatis访问数据库,怎么处理事务
- JDBC访问数据库,处理事务 Connection conn;conn.comit();conn.rollback();
- mybatis访问数据库,处理事务,SqlSession.comit();SqlSession.rollback();
- hibernate访问数据库,处理事务,Session.comit();Session.rollback();
-
3中的事务处理方式有什么不足
- 不同的数据库访问技术,处理事务的对象,方法不同,需要了解不同数据库访问技术使用事务的原理
- 掌握多种数据库中事务的处理逻辑。什么时候提交事务,什么时候回滚事务
- 处理事务的多种方法
- 总结:就是多种数据库的访问技术,有不同的事务处理机制,对象,方法
-
怎么解决不足
- spring提供了一种处理事务的统一模型,能使用统一步骤,方式完成多种不同的数据库访问技术的事务处理
- 使用spring的事务处理机制,可以完成 访问数据库的事务处理
- 使用spring的事务处理机制,可以完成hibernate访问数据库的事务处理
- spring的事务处理模型:抽象了事务处理各个事务的处理步骤
- 声明事务:把事务相关的资源和内容都提供给spring,spring就能处理事务提交,回滚了,几乎不用代码
-
处理事务,需要怎么做,做什么
- spring处理事务的模型,使用的步骤都是固定的。把事务使用的信息提供给spring就可以了
(1)事务内部提交,回滚事务,使用的事务管理器对象,代替你完成commit,rollback
事务管理器是一个接口和他的众多实现类,
- 接口: PlatformTransactionManager ,定义了事务重要方法commit , rollback实现类: spring把每一种数据库访问技术对应的事务处理类都创建好了。
- mybatis访问数据库—spring创建好的是DatasourceTransactionManagehibernater访问数据库----spring创建的是HibernateTransactionManager
- 怎么使用:如何告诉spring,你用的那种数据库访问技术
- 声明数据库访问技术对于的事务管理器实现类,在spring的配置文件中使用声明就可以了
- 你要使用mybatis访问数据库,你应该在xml配置文件中<bean id=xxx" class=" . …DatasourceTransactionManager">
- 你的业务方法需要什么样的事务,说明需要事务的类型。说明方法需要的事务:
- 你的业务方法需要什么样的事务,说明需要事务的类型。说明方法需要的事务:
- 事务的隔离级别:有4个值
- DEFAULP:采用DB默认的事务隔离级别。MySql的默认为REPEATABLE_READ;Oracle默认为 READ_COMITTRED.READ
- UNCOMMITTED:读未提交。未解决任何并发问题
- READCOMMITTED:读已提交。解决脏读,存在不可重复读与幻读.
- REPEATABLE READ:可重复读。解决脏读、不可重复读,存在幻读
- SERIAL,1ZABLE:串行化。不存在并发问题。
(2)事务的超时时间:表示一个方法最长的执行时间,如果方法执行时超过了时间,事务就回滚
单位:秒,整数值,默认是-1
-
(重要)事务的传播行为:控制业务方法是不是有事务的,是什么样的事务的
-
7个传播行为,表示你的业务方法调用时,业务在方法之间是如何使用的
- PROPAGATION_REQUIRED
- PROPAGATION_REQUIRES_NEW
- PROPAGATION_SUPPORTS
重点掌握以上三个
- PROPAGATION_MANDATORY
- PROPAGATION_NESTED
- PROPAGATION_NEVER
- PROPAGATION_NOT_SUPPORTED
几乎不用
(3)spring提交事务,回滚事务的时机
-
当你的业务方法,执行成功,没有异常抛出,当方法执行完毕,spring在方法执行后提交事务。事务管理器commit
当你的业务方法抛出运行时异常或ERROR,spring执行回滚,调用事务管理器的rollback
运行时异常的定义:RuntimeException和他的子类都是运行时异常,例如NullPointException ,NumberFormatException
-
当你的业务方法抛出非运行时异常,主要是受查异常时,提交事务
受查异常:在你写代码中,必须处理的异常。例如IOException,SQLException
-
总结spring事务
- 管理事务的是事务管理器和他的实现类
- spring的事务是一个统一模型
- 指定要使用的事务管理器实现类,使用
- 指定那些类,那些方法需要加入事务的功能
- 指定方法需要的隔离级别,传播行为,超时
- 你需要告诉spring,你项目中 类信息,方法名称,方法事务传播行为
一、事务的环境项目步骤
-
新建maven项目
-
加入maven依赖
- spring依赖
- mybatis依赖
- mysql驱动
- spring事务的依赖
- mybatis和spring集成的依赖:mybatis官方用的,用来在spring项目中创建mybatis的SqlSessionFactory,dao对象
-
创建实体类
Sale,Goods
-
创建dao接口和mapper文件
SaleDao接口,GoodsDao接口
SaleDao.xml,GoodsDao.xml
-
创建mybatis主配置文件
-
创建Service接口和实现类,属性是dao
-
创建mybatis的配置文件:声明mybatis的对象交给spring创建
- 数据源
- SqlSessionFactory
- Dao对象
- 声明自定义的service
-
创建测试类,获取Service对象,通过service调用dao完成数据库的访问
二、spring框架中提供的事务 处理方案
1、适合中小项目使用,注解方案
-
spring框架自己用aop实现给业务方法增加事务的功能,使用@Transactional注解增加事务。
-
@Transactional注解是spring框架自己注解,放在public方法的上面,表示当前方法具有事务。
-
可以给注解的属性赋值,表示具体的隔离级别,传播行为,异常信息等
-
@Transactional的步骤
1.声明事务管理器对象
<bean id = "xx" class = "DataSourceTransactionManager"
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--连接数据库,指定数据源--> <property name="dataSource" ref="myDataSource"/> </bean>
2.开启事务注解驱动,告诉spring,要使用注解的方式管理事务
使用aop机制,创建@Transactional所在的类代理对象,给方法加入事务功能
spring给业务加事务:在业务方法之前,先开启事务,在业务方法之后提交或回滚事务,使用aop环绕通知
<!--开启事务注解驱动,告诉spring使用注解管理事务,创建代理对象 transaction-manager:事务管理对象的id --> <tx:annotation-driven transaction-manager="transactionManager"/>
@Around("要增加的事务功能的业务方法名称") Object myAround(){ 开启事务,spring自己开 try{ buy(1001,11); spring的事务管理.commit(); }catch(Exception e){ spring的事务管理.rollback(); } }
3.在public方法上面加入@Transactional
-
必须放在public方法上面
-
rollbackFor:表示发生指定的异常一定回滚
-
处理逻辑:
- 1.spring收首先检查方法抛出的异常是不是在rollbackFor的属性值中,如果异常在rollbackFor列表中,不管是什么类型的异常,一定回滚
- 2.如果抛出的异常不在rollbackFor列表中,spring会判断异常是不是RuntimeException,如果是一定回滚
-
法一:
@Transactional( propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false, rollbackFor = { NullPointerException.class,NotEnoughException.class } )
-
法二:
@Transactional//使用的是事务控制的默认值,默认的传播行为是REQUIRED。隔离级别是DEFAULT,默认抛出运行时异常,回滚事务
-
2.适合大型项目aspecj框架功能
-
有很多的类,方法,需要大量的配置事务,使用aspectj框架功能,在spring配置文件中声明类,方法需要的事务。这种方式业务方法和事务配置完全分离。
-
实现步骤:都是在xml配置文件中实现
-
要使用的是aspectj框架,加入依赖
<!--aspectj代码依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.5.RELEASE</version> </dependency>
-
声明事务管理器对象
<bean id = "xx" class = "DataSourceTransactionManager"
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="myDataSource"/> </bean>
-
声明方法需要的事务类型(配置方法的事务属性{隔离级别,传播行为,超时})
<!-- id:自定义名称,表示 <tx:advice>和</tx:advice>之间的配置内容 transaction-manager:事务管理器对象的id --> <tx:advice id="myAdvice" transaction-manager="transactionManager"> <!-- <tx:attributes>:配置事务属性--> <tx:attributes> <!--<tx:method:给具体的方法配置事务属性,method可以有多个,分别给不同的方法设置事务属性 name:方法名称,(1)完整的方法名称,不带有包和类 (2)方法可以使用通配符,*,表示任何字符 propagation :传播行为,枚举值 isolation :隔离级别 rollback-for :你指定的异常类名,全限定类名。发生异常―定回滚 --> <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT" rollback-for="java.lang.NullPointerException,nuc.gjq.excep.NotEnoughException"/> </tx:attributes> </tx:advice>
-
配置aop:指定那些类要创建代理
<aop:config> <!--配置切入点表达式:指定那些包中类,要使用事务 id:切入点表达式的名称,唯一值 expression:切入点表达式,指定那些类要使用事务,aspectj会创建代理对象 --> <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))" /> <!--配置增强器:关联advice和pointcut advice-ref:通知,上面tx:advice那里的配置 pointcut-ref:切入点表达式的id --> <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt"/> </aop:config>
-