1.Spring中的事务
spring中的事务分为两类
- 声明式事务:就是使用AOP实现事务【推荐使用,因为不会修改源代码】
- 编程式事务:需要在原代码中实现事务的管理,需要修改原来的代码
2.使用
- 开启事务
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
即通过有参构造获取事务管理器,有了事务管理器对象,我们就可以管理事务了,就等同于开启了事务
这里我们可以思考一下:为什么配置事务,需要传入数据源呢?
- 首先,数据源对应的就是我们数据库中的一个数据库,以及与这个数据库的连接对象
- 其次,事务是数据库中的概念,它的特性ACID就是为了保障数据的一致性
- 所以,所以我们装配了一个事务管理器之后,应该指定它管理的是哪一个数据库的事务,
否则我们使用这个事务管理器的时候它根本不知道自己管理的事务是哪一个数据库的
- 使用事务
我们一般使用AOP的方式将事务横切入CRUD操作中
- 首先我们要在配置文件中导入事务的约束,导入方法还是在原有的基础上直接复制粘贴+修改,事务的缩写为tx
<?xml version="1.0" encoding="UTF8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd">
- 配置事务
<!--1、配置事务--> <tx:advice id="txadvice" transaction-manager="transactionManager"> <!--给哪些方法配置事务--> <!--配置事务的传播特性,propagation传播,就是表示打算对这些方法怎么使用事务,是用还是不用 一般我们就只使用REQUIRED REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是spring中默认的选择--> <tx:attributes> <tx:method name="add" propagation="REQUIRED"/><!--name属性用于指定这个事务在哪些方法上有用,propagation属性用于指定具体怎么用--> <tx:method name="delete"/> <tx:method name="update"/> <tx:method name="query"/> <tx:method name="*"/><!--*就是通配符,就是所有的方法都要使用事务来包裹执行--> </tx:attributes> </tx:advice>
- 配置切面
<!--2、配置AOP,即规定事务切入点--> <aop:config> <!--切入点--> <aop:pointcut id="pointcut" expression="execution(* com.thhh.mapper.*.*(..))"/> <!--增强设置--> <aop:advisor advice-ref="txadvice" pointcut-ref="pointcut"/> </aop:config>
- 测试
我们将有错的delete关键字修改过来,看看能不能成功执行
3.分析
上面我们使用了声明式事务,即使用AOP实现了横向业务增强,在上面的操作步骤中,我们并没有修改源代码,我们只是在spring的容器中
- 开启事务
- 配置事务
- 配置切面
通过以上3步,我们就实现了对mybatis中所有操作的事务管理,或者说这就是spring中的声明式事务的用法,可以发现spring中声明式事务的用法就是将事务当作一个切面,按照AOP的方式将它嵌入指定的执行中,由于我们在AOP配置中指定的是aop:advisor(环绕),所以事务是在方法执行之前开启,在方法执行之后关闭的
<!--配置声明式事务-->
<!--1、开启事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" /><!--通过有参构造获取事务管理器,有了事务管理器对象,我们就可以管理事务了,就等同于开启了事务-->
</bean>
<!--1、配置事务-->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<!--配置事务的传播特性,propagation传播,就是表示打算对这些方法怎么使用事务,是用还是不用
一般我们就只使用REQUIRED
REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是spring中默认的选择-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/><!--name属性用于指定这个事务在哪些方法上有用,propagation属性用于指定具体怎么用-->
<tx:method name="delete"/>
<tx:method name="update"/>
<tx:method name="query"/>
<tx:method name="*"/><!--*就是通配符,就是所有的方法都要使用事务来包裹执行-->
</tx:attributes>
</tx:advice>
<!--2、配置AOP,即规定事务切入点-->
<aop:config>
<!--切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.thhh.mapper.*.*(..))"/>
<!--增强设置-->
<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut"/>
</aop:config>
4.思考
为什么需要事务?
- 因为事务保障了ACID原则
- 在spring中推荐使用声明式事务
- 事务在项目开发中很重要,涉及到数据的一致性和完整性,所以千万要小心涉及