10.spring声明式事务

一.回顾事务

  • 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!

  • 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性。

1.事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。

2.事务四个属性ACID

  1. 原子性(atomicity)

    • 事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用

  2. 一致性(consistency)

    • 一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中

  3. 隔离性(isolation)

    • 可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏

  4. 持久性(durability)

    • 事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

二.Spring中的事务管理

1.测试事务的一致性

步骤:(在上一个的博客项目的基础上)

  1. 在UserMapper接口中添加两个方法

    1. addUser:添加用户

    2. deleteUser:删除用户

  2. 在UserMapper.xml中编写SQL语句,故意将delete写成deletes导致出错

  3. 修改UserMapperImpl类

    1. 添加addUser方法

    2. 添加deleteUser方法

    3. 修改selectUser方法,让它先添加一个用户,在删除一个用户最后返回所有用户

在UserMapper接口中添加两个方法

 1 public interface UserMapper {
 2 
 3     List<User> selectUser();
 4 
 5     //添加用户
 6     int addUser(User user);
 7 
 8     //删除用户
 9     int deleteUser(int id);
10 }

在UserMapper.xml中编写SQL语句,故意将delete写成deletes导致出错

1 <insert id="addUser" parameterType="user">
2     insert into mybatis.user (id, name, pwd) value (#{id},#{name},#{pwd});
3 </insert>
4 
5 <delete id="deleteUser" parameterType="_int">
6     deletes from mybatis.user where id = #{id};
7 </delete>

修改UserMapperImpl类

 1 public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
 2 
 3 
 4     public List<User> selectUser() {
 5         User user = new User(7,"小明","123456");
 6         UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
 7         mapper.addUser(user);
 8         mapper.deleteUser(7);
 9         return mapper.selectUser();
10     }
11 
12     @Override
13     public int addUser(User user) {
14         return getSqlSession().getMapper(UserMapper.class).addUser(user);
15     }
16 
17     @Override
18     public int deleteUser(int id) {
19         return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
20     }
21 }

直接运行测试程序发现,添加了用户但没有删除用户,事务没有回滚一致性被破坏

2.Spring的事务管理分为两类:

  • 编程式事务管理(不好,不使用)

    • 将事务管理代码嵌到业务方法中来控制事务的提交和回滚

    • 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

  • 声明式事务管理(好,使用)

    • 一般情况下比编程式事务好用。

    • 将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。

    • 将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。

3.使用声明式事务管理保证事务的ACID

步骤:

  1. 修改spring-dao.xml,导入头部约束信息

  2. 修改spring-dao.xml

    1. 添加声明式事务

    2. 添加结合了AOP配置事务通知

    3. 添加结合了AOP配置切点

修改spring-dao.xml,导入头部约束信息tx

  •  xmlns:tx="http://www.springframework.org/schema/tx" 
  •  http://www.springframework.org/schema/tx 
  •  http://www.springframework.org/schema/tx/spring-tx.xsd 
 1 <beans xmlns="http://www.springframework.org/schema/beans"
 2        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xmlns:tx="http://www.springframework.org/schema/tx"
 4        xmlns:aop="http://www.springframework.org/schema/aop"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans
 6         http://www.springframework.org/schema/beans/spring-beans.xsd
 7         http://www.springframework.org/schema/aop
 8         http://www.springframework.org/schema/aop/spring-aop.xsd
 9         http://www.springframework.org/schema/tx
10         http://www.springframework.org/schema/tx/spring-tx.xsd">

修改spring-dao.xml

 1 <!--4.配置声明式事务
 2         ref:引用我们的数据源
 3     -->
 4     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 5         <property name="dataSource" ref="dataSource" />
 6     </bean>
 7 
 8     <!--5.结合AOP切入,保证事务的一致性-->
 9     <!--配置事务通知-->
10     <tx:advice id="txAdvice" transaction-manager="transactionManager">
11         <tx:attributes>
12             <!--配置哪些方法使用什么样的事务,配置事务的传播特性
13                 1.事务的传播特性:多个事务方法相互调用时,事务如何在这些方法间传播
14                 2.read-only="true":只读不可操作数据
15                 3.propagation:用于配置事务的传播特性
16                 4.propagation="REQUIRED":如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择(默认)。
17             -->
18             <tx:method name="add" propagation="REQUIRED"/>
19             <tx:method name="delete" propagation="REQUIRED"/>
20             <tx:method name="update" propagation="REQUIRED"/>
21             <tx:method name="query" read-only="true"/>
22             <tx:method name="*" propagation="REQUIRED"/>
23         </tx:attributes>
24     </tx:advice>
25 
26     <!--6.配置AOP事务切入
27         配置切点为mapper包下的所有类和方法,用于保证事务的ACID
28     -->
29     <aop:config>
30         <aop:pointcut id="txPointcut" expression="execution(* ustc.wzh.mapper.*.*(..))"/>
31         <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
32     </aop:config>

此时测试发现没有添加,事务发生了回滚保证了一致性

将UserMapper.xml中的delete语句修复,依旧执行成功,保证事务一致性

4.总结:

为什么需要配置事务?

  • 如果不配置,就需要我们手动提交控制事务;

  • 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!

 

posted @ 2020-02-19 00:14  All_just_for_fun  阅读(205)  评论(0编辑  收藏  举报