spring声明式事务
1、回顾事务
-
把一组业务当成一个业务来做;要么都成功,要么都失败!
-
事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎!
-
确保完整性和一致性
-
事务ACID原则
- 原子性
- 一致性
- 隔离性
- 多个业务可能操作同一个资源,防止数据损坏
- 持久性
- 事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写到存储器中!
2、spring中的事务管理
-
声明式事务:AOP
-
代码实现
-
未声明事务时xml
-
<?xml version="1.0" encoding="UTF-8"?> <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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://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?userSSl=true&usrUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <bean id="sqlSessionFactiory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/liu/mapper/*.xml"/> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactiory"/> </bean> </beans>
-
测试类(在查询方法中,实现插入和删除同一个数据,删除操作sql不正确)
-
结果:(执行报错,但是数据库中数据却插入了,不符合实际)
-
-
-
声明事务并配置aop切面后的xml
-
<?xml version="1.0" encoding="UTF-8"?> <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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://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?userSSl=true&usrUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <bean id="sqlSessionFactiory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/liu/mapper/*.xml"/> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactiory"/> </bean> <!-- 配置声明式事务 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 结合 AOP 实现事务的置入 --> <!-- 配置事务的通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 你要给哪些方法配置事务 --> <!-- 配置事务的传播特性 --> <tx:attributes> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete"/> <tx:method name="update"/> <tx:method name="query" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 配置事务切入 --> <aop:config> <aop:pointcut id="txPointCut" expression="execution(* com.liu.mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config> </beans>
-
运行结果:(虽然同样报错,但是数据库中并没有插入数据)
-
-
-
编程式事务:需要在代码中进行事务管理
-
官方例子
-
public class UserService { private final PlatformTransactionManager transactionManager; public UserService(PlatformTransactionManager transactionManager) { this.transactionManager = transactionManager; } public void createUser() { TransactionStatus txStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); try { userMapper.insertUser(user); } catch (Exception e) { transactionManager.rollback(txStatus); throw e; } transactionManager.commit(txStatus); } }
-
为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况
- 如果我们不在spring中去配置声明式事务,那么我们就需要在代码中去手动配置事务
- 事务在项目开发中十分重要,涉及到数据的一致性和完整性问题,不容马虎!