Spring声明式事务

声明式事务

回顾事务

  • 把一组业务当成一个业务来做;要么都成功,要么都失败
  • 事务在项目开发中,十分重要,设计到数据的一致性问题,不能马虎
  • 确保完整性和一致性;
    事务ACID原则:
  • 原子性:事务是最小的单元,这个事务要么失败不起作用,要么就是完成,只有这两种情况。
  • 一致性:事务完成或失败必须保证事务所操作的说有数据都保持一样操作,要么所有数据都操作成功,要么都操作失败,不存在一部分数据操作成功,一部分数据操作失败。
  • 隔离性:并发事务中,一个事务的操作不影响其他事务完成状态。对里面的数据影响需要事务的隔离级别来控制隔离性。
  • 持久性:一旦事务完成,对数据库的操作是持久性的。

Spring声明式事务配置

编写接口

public interface UserMapper {
    public List<Use> selectUser();
    public int addUser(Use use);
    public int deleteUser(int id);
}

如果我在这里写错了删除的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.wx.mapper.UserMapper">
    <select id="selectUser" resultType="com.wx.pojo.Use">
        select * from user
    </select>
    <insert id="addUser" parameterType="com.wx.pojo.Use">
        insert into user (id,name,pwd) value (#{id},#{name},#{pwd});
    </insert>
    <delete id="deleteUser" parameterType="int">
        deletes from user where id = #{id}
    </delete>
</mapper>
<?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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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">
    <!--DataSource:使用Spring的数据源替换Mybatis的配置
    这里使用Spring的jdbc-->
    <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?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <!--sqlSessionFactory-->
    <bean id="sqlSessionFactory"
          class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--绑定Mybatis配置文件-->
        <property name="mapperLocations" value="com/wx/mapper/*.xml"/>
    </bean>
    <bean id="userMapper" class="com.wx.mapper.UserMapperImpl">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
    </beans>
package com.wx.mapper;

import com.wx.pojo.Use;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{

    @Override
    public int addUser(Use use) {
        return getSqlSession().getMapper(UserMapper.class).addUser(use);
    }

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

    @Override
    public List<Use> selectUser() {
        Use use = new Use (8,"小王","111");
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        mapper.addUser(use);
        mapper.deleteUser(8);
        return mapper.selectUser();
    }
}

然后在这里调用增加和删除的方法
然后测试

import com.wx.mapper.UserMapper;
import com.wx.mapper.UserMapperImpl;
import com.wx.pojo.Use;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        for (Use use : userMapper.selectUser()) {
            System.out.println(use);
        }
    }
}

在这里插入图片描述
就可以发现添加了这个id为8的,但因为删除的sql写错了他并没有删除,但事实上这里因为出错也不应该将其添加成功,如果这个是金钱交易的话,这边打入款了,但另一边并没有入款,所以我们要使用事务。

在spring中配置声明事务

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

我们还要导入头文件约束

xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd

然后结合AOP实现事务的织入

   <!--结合AOP实现事务的织入-->
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--给哪些方法配置事务-->
<!--配置事务的传播特性: new propagation = -->
        <tx:attributes>
            <tx:method name="add*"/>
            <tx:method name="delete*"/>
            <tx:method name="select*" read-only="true"/>
        </tx:attributes>
    </tx:advice>
<!--配置事务切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.wx.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

tx:method 属性
name:与事务属性关联的方法名。通配符()可以用来指定一批关联到相同的事务属性的方法。 如:'get’、‘handle*’、'on*Event’等等。
propagation:事务传播行为,可选的有:

  • REQUIRED:指定当前方法必需在事务环境中运行,如果当前有事务环境就加入当前正在执行的事务环境,如果当前没有事务,就新建一个事务。这是默认值。
  • SUPPORTS:指定当前方法加入当前事务环境,如果当前没有事务,就以非事务方式执行。
  • MANDATORY:指定当前方法必须加入当前事务环境,如果当前没有事务,就抛出异常。
  • REQUIRES_NEW:指定当前方法总是会为自己发起一个新的事务,如果发现当前方法已运行在一个事务中,则原有事务被挂起,我自己创建一个属于自己的事务,直我自己这个方法commit结束,原先的事务才会恢复执行。
  • NOT_SUPPORTED:指定当前方法以非事务方式执行操作,如果当前存在事务,就把当前事务挂起,等我以非事务的状态运行完,再继续原来的事务。
  • NEVER:指定当前方法绝对不能在事务范围内执行,如果方法在某个事务范围内执行,容器就抛异常,只有没关联到事务,才正常执行。
  • NESTED:指定当前方法执行时,如果已经有一个事务存在,则运行在这个嵌套的事务中.如果当前环境没有运行的事务,就新建一个事务,并与父事务相互独立,这个事务拥有多个可以回滚的保证点。就是指我自己内部事务回滚不会对外部事务造成影响,只对DataSourceTransactionManager事务管理器起效。
    然后再次删除数据库中id为8的,再次运行
    在这里插入图片描述
    可以发现就不会添加成功
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值