spring学习(十三、声明式事务)

十三、声明式事务

1.回顾事务

  • 把一组业务当成一个业务来做。要么都成功,要么都失败
  • 事务在项目开发中十分重要,涉及到数据一致性的问题
  • 确保完整性和一致性

事务的ACID原则

  • 原子性
  • 一致性
  • 隔离性
    • 多个业务可能操作一个资源,防止数据损坏
  • 持久性
    • 事务一旦提交,无论系统发生什么问题,结果都不会影响,被持久化的写到存储器中

2.spring中的事务管理

  • 声明式事务:AOP
  • 编程式事务:需要在代码中,进行事务的管理

在代码中测试事务的一致性,selectUser就作为一个事务

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {


    public List<User> selectUser() {
        User user = new User(7, "氪二百", "12345666");
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        mapper.addUser(user);
        mapper.deleteUser(user.getId());
        return mapper.selectUser();
    }

    public int addUser(User user) {
        return getSqlSession().getMapper(UserMapper.class).addUser(user);
    }

    public int deleteUser(int id) {
        return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
    }
}

在这里将delete的SQL操作写错,来测试事务的一致性

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzt.mapper.UserMapper">

    <select id="selectUser" resultType="user">
        select * from mybatis.user
    </select>

    <insert id="addUser" parameterType="user">
        insert into mybatis.user(id, name, pwd) values (#{id},#{name},#{pwd})
    </insert>
    
    <!--故意写错,测试事务的一致性-->
    <delete id="deleteUser" parameterType="int">
        deletes from mybatis.user where id=#{id}        
    </delete>

</mapper>

spring-dao.xml中需要添加的配置

xmlns:tx="http://www.springframework.org/schema/tx"
...
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
   <constructor-arg ref="dataSource" />
</bean>

<!--结合AOP实现事务的织入-->
<!--配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
   <!--给哪些方法配置事务-->
   <!--配置事务的传播特性 propagation-->
   <tx:attributes>
      <tx:method name="add" propagation="REQUIRED"/>
      <tx:method name="delete" propagation="REQUIRED"/>
      <tx:method name="update" propagation="REQUIRED"/>
      <tx:method name="select" read-only="true"/>   <!--只读read-only 不能对数据库进行增删改的操作-->
      <tx:method name="*" propagation="REQUIRED"/>
   </tx:attributes>
</tx:advice>

propagation传播方式:

REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 spring的默认选择

NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。

【下面的不怎么用】

SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。

MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。

REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。

NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

配置事务切入AOP【写在spring-dao.xml中】

<!--配置事务切入-->
<aop:config>
     <!--mapper包下面的所有类所有方法都要被切入-->
   <aop:pointcut id="txPointCut" expression="execution(* com.lzt.mapper.*.*(..))"/>   
   <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>

在测试时,测试类中的事务就具有了一致性,如果delete操作出现错误,则整个selectUser操作都会回滚

注意事项:

  • 如果不配置事务可能会存在数据提交不一致的情况
  • 如果我们不在Spring中配置声明式事务,则需要在代码中手动配置事务
  • 事务在项目中十分重要,涉及到数据的一致性和完整性
posted @ 2021-02-28 23:07  HoneyOneD  阅读(57)  评论(0)    收藏  举报