美文网首页程序员
Spring声明式事务

Spring声明式事务

作者: 小杨小杨神采飞杨 | 来源:发表于2020-04-22 23:10 被阅读0次

模拟一个买书结账的环境
环境搭建:
bookDao类,与数据库交互

@Repository
public class bookDao {
    @Autowired
    private JdbcTemplate template;

    //根据isbn获取价格
    public int getPrice(String isbn) {
        String sql = "select price from book where isbn = ?";
        Integer price = template.queryForObject(sql, Integer.class, isbn);
        return price;
    }

    //根据价格减少钱
    public void reduceMoney(int price,String username) {
        String sql = "update account set balance = balance - ? where username = ?";
        template.update(sql,price,username);
    }

    //根据isbn减少库存
    public void reduceStock(String isbn,int num) {
        String sql = "update book_stock set stock = stock - ? where isbn = ?";
        template.update(sql,num,isbn);
    }
}

bookService类,逻辑操作

@Service
public class bookService {
    @Autowired
    private bookDao dao;

    //实现结账操作
    public void pay() throws IOException {
        Scanner s = new Scanner(System.in);
        System.out.print("请输入您的姓名:");
        String username = s.next();
        System.out.print("请输入购买的书籍编号:");
        String isbn = s.next();
        System.out.print("请输入购买数量:");
        int num = s.nextInt();

        System.out.println("正在结账...");

        int price = dao.getPrice(isbn);
        dao.reduceMoney((price*num),username);
        dao.reduceStock(isbn,num);

        System.out.println("购买成功");
    }
}

ioc容器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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--扫描指定包下配置了注解的bean-->
    <context:component-scan base-package="cn.yzx.dao"/>
    <context:component-scan base-package="cn.yzx.service"/>
    <!--开启注解配置-->
    <context:annotation-config/>
    <!--引入外部配置文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    
    <!--获取druid数据库连接池-->
    <bean id="DataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${driverClassName}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${password}"/>
    </bean>

    <!--注册JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="DataSource"/>
    </bean>
</beans>

测试类

public class mytest {
    public static void main(String[] args) throws IOException {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        bookService bean = context.getBean(bookService.class);
        bean.pay();
    }
}

实现需求,用户买了书,根据买书的数量以及书的价格,减少用户的钱,以及书的库存

  • 无事务
    显而易见一个很严重的问题,如果在减少用户钱、库存减少两次操作中,后执行的一个除了错误,则前一个执行的结果无法撤回,比如,我这里是用户先付钱再减少库存,在减少库存的sql语句中人为的制造错误

    制造错误
    此时,钱已经减少了,但是库存因为错误,并没有减少
    运行结果
    用户的钱
    书的库存
    此时,我们就需要使用事务,事务可以保证所有操作都正常执行数据库数据才会发生改变,之前我们使用的是手动的事务,较为麻烦,且在本案例中有多次数据库连接,要甄别他们也十分麻烦,而spring的AOP功能与事务的步骤基本吻合,所以可以使用AOP来实现事务,但是自己写AOP也很麻烦,所以spring为我们写好的基于AOP的声明式事务
  • 使用声明式事务
    首先修改IOC容器的配置文件,添加一下几行


    xml

    注意,使用tx需要导入tx的名称空间依赖

然后在进行操作的方法(Service层)上,使用@Transactional开启声明式事务


@Transactional

再次执行,依然报错


结果
但此时用户的钱没有减少
用户的钱

书的库存也没有减少


书的库存

声明式事务的一些细节

声明式事务的注解中,有许多参数可以填入

  1. isolation:事务隔离级别 (重要)
isolation

首先了解概念

为什么需要设置隔离级别?

为什么需要设置隔离级别 脏读演示

设置为读已提交隔离级别,虽然解决了读脏数据的问题,但是没有解决一次失误事务读取到的数据不同的问题

不可重复读演示

设置为可重复读级别,mysql在此级别下,已经解决了所有问题

事务2的操作不影响事务1的读取结果
所以一般都设置为可重复读级别,默认也是该级别

隔离级别分为?


隔离级别 隔离级别支持

其中mysql在可重复读隔离级别下就可以防止所有问题了,表中给出的信息是错误的

设置隔离级别
  1. propagation:事务传播行为 (重要)
propagation

解释:当有多个事务嵌套运行时,若子事务出现异常,父事务是否要回滚?其他子事务是否要回滚?这就是事务传播,可以通过propagation属性进行设置

7种传播行为
挂起:暂停
一二对应(常用),三四五六一一对应,七独立
设置传播行为
图示
注意:子事务如果是REQUIRED传播方式,那么子事务的所有配置,例如超时、设置回滚不回滚之类的全都不生效,只继承上一级事务的配置
  1. readOnly:设置事务为只读事务,不能增删改,可以加快查询速度,因为不涉及增删改,则无关事务,就不用管事务的操作了


    readOnly
测试 测试结果
  1. timeout:事务超出指定时间后,自动终止并回滚


    timeout
测试 测试结果

异常相关

异常:
运行时异常:声明式事务默认在发生运行时异常时回滚
编译时异常:需要try抓取或throws抛出的异常,声明式事务默认在发生运行时异常时不回滚
所以就需要设置以下四个属性,来设置那些属性需要回滚,那些不需要

  1. rollbackFor:指定那些异常事务需要回滚 (常用)
rollbackFor

可以让原本不回滚的异常回滚
例如:IO流读取文件不存在异常,不会触发事务的回滚,但设置后就会触发


手动添加文件读取异常
测试结果

rollbackFor指定该异常回滚


指定回滚
测试结果
  1. noRollbackFor:指定那些异常事务不回滚 (常用)
noRollbackFor

可以让原本回滚的异常不回滚
例如数学异常,会触发事务的回滚,指定后就不会触发
手动设置数学异常


设置异常

测试


测试结果
设置不回滚
设置数学异常不回滚
测试
运行前库存
运行后库存

可见未回滚
此处要注意一个点:运行时异常默认是回滚的,设置不回滚后,若异常发生在修改sql语句之前,依然不会执行sql语句,因为运行时异常发生后,java程序会停止运行,所以要测试此异常,需要将异常放到所有sql语句之后


放到sql语句之后
  1. rollbackForClassName:指定那些异常事务需要回滚by异常全类名


    rollbackForClassName

效果与rollbackFor一致,只是参数是全类名,更麻烦,不常用

  1. noRollbackForClassName:指定那些异常事务不回滚by异常全类名


    noRollbackForClassName

效果与noRollbackFor一致,只是参数是全类名,更麻烦,不常用

使用xml配置声明式事务

xml

还是一个原则:重要的使用xml配置,不重要的使用注解配置

相关文章

  • spring04

    Spring JdbcTemplate学习 Spring 声明式事务 xml配置实现 Spring 声明式事务 注...

  • Spring的事务机制解析一

    一Spring事务的种类 1.声明式事务 2.编程式事务 二Spring事务的具体描述 (一)声明式事务 1.声明...

  • 手写源码(一):自己实现Spring事务

    手写Spring事务 Spring事务分为声明式事务(注解或包扫描)和编程式(在代码里提交或回滚)事务,声明式事务...

  • spring事务(二) 声明式事务

    spring事务(二) 声明式事务 知识导读 声明式事务是对编程式事务的包装 声明式事务通过使用AOP来实现,注册...

  • Java Spring-声明式事务

    Spring-声明式事务

  • Spring 事务机制详解

    Spring事务机制主要包括声明式事务和编程式事务 Spring声明式事务时,有一个非常重要的概念就是事务属性。事...

  • spring事务管理 TransactionProxyFacto

    J2EE,当然离不开事务,事务又当然少不了Spring声明式事务。spring声明式事务,很多码农门,应该和笔者一...

  • Spring事务总结

    1. 编程式事务和声明式事务 spring支持编程式事务管理和声明式事务管理两种方式。 编程式事务Spring推荐...

  • Spring Boot开启声明式事务

    Spring Boot开启声明式事务 在以前早期的Spring使用xml方式的时候,配置声明式事务通常用xml方式...

  • spring 声明式事务管理

    本节阐述在事务相关的问题上,Spring框架的声明式事务管理的内部工作原理。 关于Spring框架的声明式事务支持...

网友评论

    本文标题:Spring声明式事务

    本文链接:https://www.haomeiwen.com/subject/nnfwihtx.html