Spring5中的事务管理

Spring5中的事务管理

事务在之前就已经了解过了,这里简单的来讲一下,在一条或多条DML语句执行时,确保同时成功或者同时失败

模型搭建

举一个非常典型的问题,银行转账问题,Jerry向Tom转账100元,其中一共产生两条sql语句,第一Jerry余额少100,第二Tom余额多100,且必须要保证这两条语句要么同时成功要么同时失败。

之前在JavaWeb中解决办法是关闭当前数据库连接的自动提交,在成功的时候提交,失败的时候回滚。来看一下Spring5中该如何处理

首先我们先搭建上述问题的模型

  • 数据库模型搭建

    做的非常简单,只需要用户名和余额即可

    在这里插入图片描述

  • Service及Dao

    @Service
    public class BankService {
        @Autowired
        public BankDaoImpl bankDao;
    
        public void accountMoney(){
            bankDao.addMoney();
            //模拟异常
            int i = 10/0;
            bankDao.removeMoney();
        }
    
        public void setBankDao(BankDaoImpl bankDao) {
            this.bankDao = bankDao;
        }
    }
    
    @Repository
    public class BankDaoImpl implements BankDao {
        @Autowired
        public JdbcTemplate jdbcTemplate;
    
        @Override
        public void addMoney() {
            String sql = "update t_bank set `balance` = balance + 100 where id = 1";
            jdbcTemplate.execute(sql);
        }
    
        @Override
        public void removeMoney() {
            String sql = "update t_bank set `balance` = balance - 100 where id = 2";
            jdbcTemplate.execute(sql);
        }
    
        public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }
    }
    
  • 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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        <!--开启注解扫描-->
        <context:component-scan base-package="com.yellowstar"></context:component-scan>
    
        <!--创建数据库连接池对象-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
            <property name="url" value="jdbc:mysql://localhost:3306/test"></property>
            <property name="username" value="root"></property>
            <property name="password" value="Hkx123"></property>
        </bean>
    
        <!--创建jdbcTemplate对象-->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    </beans>
    
  • 测试类

        @Test
        public void test3(){
            ApplicationContext context = new ClassPathXmlApplicationContext("Bean.xml");
            BankService bankService = context.getBean("bankService", BankService.class);
            bankService.accountMoney();
        }
    

Spring5事务管理介绍

  • 事务添加到Java EE三层架构中的Service层(业务逻辑层)
  • 在Spring进行事务管理操作有两种方式
    • 编程式事务管理(即上文所讲的成功提交,失败回滚)
    • 声明式事务管理
      • 基于注解方式(推荐使用)
      • 基于XML配置文件方式
  • 在Spring进行声明式事务管理,底层使用AOP原理

使用Spring管理事务

  1. 在xml文件中配置事务管理器并注入数据源

        <!--创建事务管理器-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!--注入数据源-->
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    
  2. 开启事务注解

        <!--xmlns:tx="http://www.springframework.org/schema/tx"-->需要在头部文件配置tx空间
    	<!--开启事务注释-->
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
  3. 在方法或类上添加@Transactional注解

    在方法上添加代表对此方法进行事务管理,在类上添加代表对类中的所有方法进行事务管理

    @Service
    @Transactional
    public class BankService {
        @Autowired
        private BankDaoImpl bankDao;
    
        public void accountMoney(){
            bankDao.addMoney();
            //模拟异常
            int i = 10/0;
            bankDao.removeMoney();
        }
    
        public void setBankDao(BankDaoImpl bankDao) {
            this.bankDao = bankDao;
        }
    }
    

Spring事务管理:事务参数

先来看一下几个比较重要的事务参数

  • propagation:传播行为
  • isolation:隔离级别
  • timeout:存活时长:事务在一定时间内进行提交,不提交则回滚
  • readOnly:只读:设置true代表数据库只读,只能进行查询操作
  • rollbackFor:回滚:出现哪些异常进行回滚
  • noRollbackFor:不回滚:出现哪些异常不回滚

在这里插入图片描述

传播行为

spring定义了7种事务传播行为,最常用的是REQUIRED或REQUIRED_NEW

  • REQUIRED:如果有事务在运行,当前的方法就在这个事务内运行,否则启动一个新事务,并在自己的事务内运行(默认)
  • REQUIRED_NEW:当前方法必须启动新事务,并在自己的事务内运行,如果有事务正在运行,应该将他挂起
  • SUPPORTS:如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中
  • NOT_SUOPPORTS:当前的方法不应该运行在事务中,如果有运行的事务,将他挂起
  • MANDATORY:当前的方法必须运行在事务中,如果没有正在运行的事务,就抛出异常
  • NEVER:当前方法不应该运行在事务中,如果有运行的事务,就抛出异常
  • NESTED:如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行,否则就启动一个新的事务,并在他自己的事务内运行
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class BankService {

隔离级别

事务的隔离级别分四种

  • 读未提交
  • 读已提交
  • 可重复读
  • 序列化读
@Service
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
public class BankService {

完全注解开发

创建配置类,代替xml配置文件

  1. 创建配置类
  2. 开启注解扫描
  3. 开启事务
  4. 创建数据库连接池
  5. 创建JdbcTemplate对象
  6. 创建事务管理器
@Configuration //配置类
@ComponentScan(basePackages = "com.yellowstar") //组件扫描
@EnableTransactionManagement //开启事务
public class TransactionConfig {
    //创建数据库连接池对象
    @Bean
    public DruidDataSource getDruidDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true");
        dataSource.setUsername("root");
        dataSource.setPassword("Hkx123");
        return dataSource;
    }

    //创建JdbcTemplate对象
    @Bean
    public JdbcTemplate getJdbcTemplate(DruidDataSource dataSource){
        //到 ioc 容器中根据类型找到 dataSource
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

    //创建事务管理器
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DruidDataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值