• 05、Spring事务详解


    本文主要介绍Spring中的事务相关知识:
    1、熟悉事务管理的三个核心接口
    2、了解Spring事务的两种方式
    3、掌握基于XML和注解的事务使用

    1、Spring事务管理概述

    1、事务管理的核心接口

    1、PlatformTransactionManager

    PlatformTransactionManage接口是Spring平台提供的平台事务管理器,主要用于管理事务。该接口中主要包含3个事务操作方法。

    • TransactionStatus getTransaction(TransactionDefinition definition):根据事务定义信息从事务环境中返回一个已存在的事务,或者创建一个新的事务。
    • void commit(TransactionStatus status):根据事务的状态提交事务,如果事务状态已经标识为 rollback-only,该方法执行回滚事务的操作。
    • void rollback(TransactionStatus status):将事务回滚,当 commit 方法抛出异常时,rollback 会被隐式调用。

    2、使用事务选用实现类

    • JDBC 和 MyBatis 使用 DataSourceTransactionManager。
    • Hibernate 使用 HibernateTransactionManager。
    • JPA 使用 JpaTransactionManager。

    3、TransactionDefinition接口

    • int getPropagationBehavior():获取事务的传播行为。
    • int getIsolationLevel();:获取事务的隔离级别。
    • int getTimeout();:获取事务的超时时间。
    • boolean isReadOnly();:判断事务是否只读。
    • String getName();:获取事务对象名称。

    4、TransactionStatus

    • boolean isNewTransaction(); 判断是否是新的事务
    • boolean hasSavepoint(); 判断是否存在保存点
    • void setRollbackOnly(); 设置事务回滚
    • boolean isRollbackOnly(); 判断是否回滚
    • void flush(); 刷新事务
    • boolean isCompleted(); 判断事务是否完成

    2、事务管理的方式

    • 编程式事务:通过编写代码来管理事务;
    • 声明式事务:通过XML配置或注解来管理事务。

    2、基于XML方式的声明式事务

    1、创建一个maven项目导入相关依赖

        <dependencies>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>5.1.45version>
                <scope>runtimescope>
            dependency>
            
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>druidartifactId>
                <version>1.1.9version>
            dependency>
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.4.5version>
            dependency>
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatis-springartifactId>
                <version>1.3.1version>
            dependency>
    
            
            <dependency>
                <groupId>org.slf4jgroupId>
                <artifactId>slf4j-log4j12artifactId>
                <version>1.7.25version>
            dependency>
            
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-jdbcartifactId>
                <version>5.0.8.RELEASEversion>
            dependency>
            <dependency>
                <groupId>org.aspectjgroupId>
                <artifactId>aspectjweaverartifactId>
                <version>1.8.13version>
            dependency>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-webmvcartifactId>
                <version>5.0.8.RELEASEversion>
            dependency>
            
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-testartifactId>
                <version>5.0.8.RELEASEversion>
                <scope>testscope>
            dependency>
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.12version>
                <scope>testscope>
            dependency>
    
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <version>1.18.22version>
                <scope>providedscope>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    2、准备数据库

    CREATE TABLE `account`  (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `balance` decimal(10, 0) NULL DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    INSERT INTO `account` VALUES (1, 10000);
    INSERT INTO `account` VALUES (2, 0);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3、编写dao接口及Mapper.xml文件

    • dao接口
    package cn.simplelife.mapper;
    
    import org.apache.ibatis.annotations.Param;
    
    import java.math.BigDecimal;
    
    /**
     * @ClassName AccountMapper
     * @Description
     * @Author simplelife
     * @Date 2022/11/23 15:34
     * @Version 1.0
     */
    
    public interface AccountMapper {
        void addBalance(@Param("inId") Long inId, @Param("amount") BigDecimal amount);
    
        void subtractBalance(@Param("outId") Long outId, @Param("amount") BigDecimal amount);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • mapper.xml文件
    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="cn.simplelife.mapper.AccountMapper">
    
        <update id="addBalance">
            UPDATE account
            SET balance=balance + #{amount}
            WHERE id = #{inId}
        update>
    
        <update id="subtractBalance">
            UPDATE account
            SET balance=balance - #{amount}
            WHERE id = #{outId}
        update>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    4、编写实体类

    package cn.simplelife.domain;
    
    import lombok.Data;
    
    import java.math.BigDecimal;
    
    /**
     * @ClassName Account
     * @Description
     * @Author simplelife
     * @Date 2022/11/23 15:15
     * @Version 1.0
     */
    @Data
    public class Account {
        private Long id;
        private BigDecimal balance;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    5、编写mybatis-config.xml配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
        <!--配置别名-->
        <typeAliases>
            <package name="cn.simplelife.domain"/>
        </typeAliases>
    
        <!--关联mapper-->
        <mappers>
            <mapper resource="cn/simplelife/mapper/*.xml"/>
        </mappers>
    </configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    6、编写业务接口及实现类

    • 业务层接口
    package cn.simplelife.service;
    
    import java.math.BigDecimal;
    
    /**
     * @ClassName IAccountService
     * @Description
     * @Author simplelife
     * @Date 2022/11/23 17:09
     * @Version 1.0
     */
    
    public interface IAccountService {
        void transfer(Long outId, Long inId, BigDecimal amount);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 业务层实现类
    package cn.simplelife.service.impl;
    
    import cn.simplelife.mapper.AccountMapper;
    import cn.simplelife.service.IAccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.math.BigDecimal;
    
    /**
     * @ClassName IAccountServiceImpl
     * @Description
     * @Author simplelife
     * @Date 2022/11/23 17:10
     * @Version 1.0
     */
    
    @Service
    public class IAccountServiceImpl implements IAccountService {
    
        @Autowired
        private AccountMapper accountMapper;
    
        @Override
        public void transfer(Long outId, Long inId, BigDecimal amount) {
            accountMapper.subtractBalance(outId, amount);
            System.out.println(10 / 0);
            accountMapper.addBalance(inId, amount);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    7、编写applicationContext.xml配置文件

    
    <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: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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
        
        <context:component-scan base-package="cn.simplelife.*"/>
    
        
        <context:property-placeholder location="classpath:db.properties"/>
    
        
        <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${password}"/>
        bean>
    
        <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="druidDataSource"/>
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
        bean>
    
        <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="cn.simplelife.mapper"/>
        bean>
        
        <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="druidDataSource"/>
        bean>
    
        
        <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
            <tx:attributes>
                <tx:method name="*"/>
            tx:attributes>
        tx:advice>
    
        <aop:config>
            
            <aop:pointcut id="txPoint" expression="execution(* cn.simplelife.service.impl.*ServiceImpl.*(..))"/>
            
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
        aop:config>
    
        <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    8、编写测试类

    import cn.simplelife.service.IAccountService;
    import cn.simplelife.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import java.math.BigDecimal;
    
    /**
     * @ClassName SqlSessionFactoryTest
     * @Description
     * @Author simplelife
     * @Date 2022/11/23 15:26
     * @Version 1.0
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class SqlSessionFactoryTest {
        @Autowired
        private IAccountService iAccountService;
    
        @Test
        public void getSqlSessionTest() {
            System.out.println(MybatisUtils.getSqlSession());
            iAccountService.transfer(1L, 2L, new BigDecimal("100"));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    9、测试结果

    • 成功
      在这里插入图片描述
      在这里插入图片描述
    • 失败

    在这里插入图片描述
    在这里插入图片描述

    3、基于注解的事务

    1、修改配置文件如下

    <?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: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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!--配置IocDi注解解析器-->
        <context:component-scan base-package="cn.simplelife.*"/>
    
        <!--  关联db.properties-->
        <context:property-placeholder location="classpath:db.properties"/>
    
        <!--配置数据源-->
        <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${password}"/>
        </bean>
    
        <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="druidDataSource"/>
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
        </bean>
    
        <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="cn.simplelife.mapper"/>
        </bean>
        
        <!--配置事务管理器-->
        <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="druidDataSource"/>
        </bean>
        <!--开启事务注解支持-->
        <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    2、修改业务层方法

    添加注解

    package cn.simplelife.service.impl;
    
    import cn.simplelife.mapper.AccountMapper;
    import cn.simplelife.service.IAccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.math.BigDecimal;
    
    /**
     * @ClassName IAccountServiceImpl
     * @Description
     * @Author simplelife
     * @Date 2022/11/23 17:10
     * @Version 1.0
     */
    
    @Service
    public class IAccountServiceImpl implements IAccountService {
    
        @Autowired
        private AccountMapper accountMapper;
    
        @Override
        @Transactional
        public void transfer(Long outId, Long inId, BigDecimal amount) {
            accountMapper.subtractBalance(outId, amount);
            System.out.println(10 / 0);
            accountMapper.addBalance(inId, amount);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
  • 相关阅读:
    volatile在C语言中的基本使用方法
    【总线】AXI总线:FPGA设计中的通信骨干
    Vue2电商前台项目——完成加入购物车功能和购物车页面
    C++ Reference: Standard C++ Library reference: C Library: cwchar: mbrtowc
    【计算机网络】 7、websocket 概念、sdk、实现
    除了 filter 还有什么置灰网站的方式?
    计算机毕业设计ssm+vue+elementUI医院门诊互联电子病历管理信息系统
    java毕业设计蛋糕店会员系统Mybatis+系统+数据库+调试部署
    【Vue面试题十三】、Vue中的$nextTick有什么作用?
    elasticSearch配置
  • 原文地址:https://blog.csdn.net/m0_37911124/article/details/128043237