12、声明式事务
12.1 回顾事务
-
把一组业务当做一个业务来做,要么都成功,要么都失败
-
事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎
-
确保完整性和一致性
事务的ACID原则:
-
原子性(atomic)
- 要么都实现,要么都失败
-
一致性(consistency)
- 操作前和操作后,数据总量不变
-
隔离性(isolation)
- 多个业务操作同一资源,不能相互干扰,防止数据损坏
-
持久性(durability)
- 事务一旦提交,不可回滚,无论系统发生什么问题,被持久化的写到存储器中。
12.2 spring中的事务管理
增删改需要事务,查询不需要(查询设置为只读)
-
声明式事务:AOP【交给容器事务管理】
-
编程式事务:需要在代码中,进行事务的管理【需要改变代码】
12.2.1 补充:spring的七种事务传播属性:propagation 传播
required(依赖):支持当前事务,如果当前没有事务,就新建一个事务 【默认】 supports(支持):支持当前事务,如果当前没有事务,就以非事务的方式执行 mandatory(强制):支持当前事务,如果当前没有事务,就抛出异常 required_new:新建事务,如果当前存在事务,把当前事务挂起 not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起 never:以非事务方式执行,如果当前存在事务,则抛出异常 nested(嵌套):支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务
真实开发:
<tx:method name="*" propagation="REQUIRED"/>
12.2.2 案例
<?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">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!--创建sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注册数据源-->
<property name="dataSource" ref="dataSource"/>
<!--注册mybatis-->
<property name="configLocation" value="mybatis-config.xml"/>
<!--注册UserMapper-->
<property name="mapperLocations" value="classpath:com/kuang/mapper/UserMapper.xml"/>
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!--配置声明式事务 官网的-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--有属性可以用 property 赋值,没有可以用构造器-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--结合aop实现事务的织入-->
<!--配置事务的类:spring-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给那些方法配置事务-->
<!--配置事务的传播特性:new-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.kuang.mapper.*.*(..))"/>
<!--切入 txAdvice包下的所有方法 都会编织上事务 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
12.2.3 思考:为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况
- 如果我们不在spring中去配置声明式事务,我们就需要在代码中手动配置事务
- 事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题