spring+mybatis+事务回滚(@transactional)

3 篇文章 0 订阅
1 篇文章 0 订阅

目录

事务操作的四大特征 ACID:

在 pom.xml 中添加依赖

编写实体类  Account

编写操作类  AccountDao

编写服务类  AccountService

编写配置文件  spring-context.xml

编写测试类  AccountServiceTest


事务操作的四大特征 ACID:

原子性 atommicity :表示多个操作要么同时成功,要么同时失败。因为时多个操作,所以失败的时候可能已经成功了默写操作,但是这些操作最终不能执行成功,也就是需要回滚。

一致性 consistency :相同的操作返回的相同的结果。在单个数据库中一般不考虑数据的一致性,因为数据库是由一个,相同的 sql 语句查询的结果肯定相同。但分布式存储系统中,数据时存储的不同的服务器中,那再这种情况下如何保证数据的一致性呢?

隔离性 isolation :这是四个特性中较好理解的一个,在一个数据库中,要是有多个用户并发方法相同的数据,那数据库会为每个用户开启一个事务,这个时候,每个事物之间不能相互影响,也就是隔离性。

持久性 durability :表示事务一旦被提交,就不会改变,即使是服务器或数据库系统遇到故障也不会丢失数据。实际中的数据库中是很多数据的,像阿里巴巴,腾讯这些公司,数据库的数据更是多得数不清,这些数据当然不会轻易丢失,所以持久性还是比较容易理解的。

案例:模拟银行银行的转账功能,这个功能分为减钱和加钱两个部分,现在转账账户上执行减钱操作,再从接收账户上执行加钱账户。这明显是个原子操作,减钱之后没加,那钱去哪里了呢?

在 pom.xml 中添加依赖

<dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.9</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.7</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.27</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.20</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.20</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

因为我使用的是 maven 工程,所以使用依赖,如果大家使用的是 Java EE 工程,可以把依赖下载好,然后添加到依赖中。

编写实体类  Account

/**
 * @Author XY
 * @Date 2022/6/11 10:56
 */
public class Account {
    private Integer id;
    private String username;
    private Integer balance;

}

这个类在本程序中并没有用到,大家可以参考这个类来创建数据表。

编写操作类  AccountDao

import org.apache.ibatis.annotations.Param;

/**
 * @Author XY
 * @Date 2022/6/11 10:57
 */
public interface AccountMapper {

    /**
     * 减钱操作
     * @param from 减钱的账户,@Param("username")表示在编写 sql 语句的时候变量名是 username
     * @param money 转账金额
     * @return 该操作导致数据表的受影响行数
     */
    Integer updateMinusBalance(@Param("username") String from, @Param("money") Integer money);

    /**
     * 加钱操作
     * @param to 加钱操作
     * @param money 转账金额
     * @return 该操作导致数据表的受影响行数
     */
    Integer updateAddBalance(@Param("username") String to, @Param("money") Integer money);
}

编写服务类  AccountService

import com.qfedu.ssm.dao.AccountMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author XY
 * @Date 2022/6/11 14:06
 * <p>
 * 下面这两个注解就可以使转账异常使回滚
 * @EnableTransactionManagement,添加这个注解的时候可能会出现 No qualifying bean of type 'org.springframework.transaction.TransactionManager' available 这个异常,也就是找不到合适TransactionManager,这个时候向 spring 容器注册一个就行
 * @Transactional
 */
@Service
@EnableTransactionManagement
public class AccountService {
    @Autowired
    AccountMapper accountMapper;

    @Transactional
    public void transfer(String from, String to, Integer money) {
        Integer r1 = accountMapper.updateMinusBalance(from, money);
        System.out.println("r1>>>>" + r1);
        //手动制造异常,模拟出错时的转账失败
//        Integer i = 1 / 0;
        Integer r2 = accountMapper.updateAddBalance(to, money);
        System.out.println("r2>>>>>" + r2);
    }
}

编写配置文件  spring-context.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 https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.qfedu.ssm"/>
    <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test01?serverTimezone=Asia/Shanghai"/>
        <property name="username" value="root"/>
        <property name="password" value="1234"/>
    </bean>
    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations">
            <value>classpath*:mapper/*.xml</value>
        </property>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.qfedu.ssm.dao"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
    </bean>
</beans>

编写测试类  AccountServiceTest

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Author XY
 * @Date 2022/6/11 14:08
 */
public class AccountServiceTest {

    @Test
    public void test01() {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context.xml");
        AccountService accountService = ctx.getBean(AccountService.class);
        accountService.transfer("zhangsan", "lisi", 50);
    }
}

总结:当没有异常时,转账操作正常运行,当出现异常时,已经成功的操作会执行回滚,也就是相当于撤销。

这里在告诉大家一个快捷键,ctrl + shift + t 可以快速创建一个测试类,默认的类名就是当前类名加上 Test ,我这里是 maven 创建的测试类在测试包下,如果你们的是 Java EE 工程,创建的测试类就和被测试类在同一包下。

 Testing library :这里先择JUnit4

Class name : 这里是测试类的名称

Destination package :这个测试类的包名(不建议修改)

setUp 和 tearDown :这两个分别是测试类注解 @Before 和 @After 对应的方法

Generate test methods for :这里是测试的方法,勾上的话就会自动创建好

编写好测试类后,在被测试类中可以直接使用  ctrl + shift + t 快捷键调转到测试类中,也可以再创建一个测试类。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值