声明式事务

137 阅读2分钟

事务

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

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

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

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

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

声明式事务案例解析

为了简单解释起见,就拿操作数据库来说,同一时刻,添加一个用户,删除一个用户。正常来说,这两个事情组成的事务,要么添加成功,删除也成功;要么两个都失败。但这是建立在事务的基础上。

为了更直观,我们这里对比一下没有设置事务和设置了事务的差别

没有设置事务 看到这个项目结构,自己写出对应的代码,不会的去看之前的blog。 image.png

比较重要的代码:

UserMapper.java

package dao;

import pojo.User;

import java.util.List;

public interface UserMapper {
    List<User> selectUser();

    int addUser(User user);

    int deleteUser(int id);
}

UserMapperImpl2.java

package dao;

import org.mybatis.spring.support.SqlSessionDaoSupport;
import pojo.User;

import java.util.List;

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    public List<User> selectUser() {
        User user = new User(5, "小米", "asd");
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        mapper.addUser(user);
        mapper.deleteUser(5);

        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);
    }
}

UserMapper.xml 故意写错delete语句

<?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">

<!--configuration核心配置文件-->
<mapper namespace="dao.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>

测试结果当然是错误的

image.png

你点开数据库,会发现,尽管delete失败了,但是添加还是成功了,这不是我们想要的结果,这时候就需要事务

image.png

设置了事务 在ApplicationContext.xml配置事务

    <!--配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="datasource"/>
    </bean>

    <!-- 结合AOP实现事务织入-->
    <!-- 配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 给方法配置事务-->
        <!--
        <tx:method name="*" propagation="REQUIRED"/>直接搞定
        propagation="REQUIRED" 可不写,默认就是这个
         -->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!-- 配置事务切入   -->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* dao.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

image.png 测试结果还是会报错,但是,数据库也没有添加用户,两个都失败。

image.png