第10章—开启事务

spring boot 系列学习记录:http://www.cnblogs.com/jinxiaohang/p/8111057.html

码云源码地址:https://gitee.com/jinxiaohang/springboot

  此前,我们主要通过XML配置Spring来托管事务。在SpringBoot则非常简单,只需在业务层添加事务注解(@Transactional )即可快速开启事务。虽然事务很简单,但对于数据方面是需要谨慎对待的,识别常见坑点对我们开发有帮助。

  推荐做法:在业务层统一抛出异常,然后在控制层统一处理。

1. 引入依赖

如果是新建项目的,可以在这页添加依赖,如是原有项目可直接编写。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xiaohang</groupId>
    <artifactId>springboot-transactional</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot-transactional</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

二、添加数据源

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver

  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

三、编写各层代码

  • 实体层
import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;
import java.math.BigDecimal;

@Data
@Entity
public class UserAccount {

    @Id
    private String userId;

    private String userName;

    private BigDecimal balance;
}
  • dao层
import com.xiaohang.springboottransactional.entity.UserAccount;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserAccountRepository extends JpaRepository<UserAccount,String>{
}
  • service层
public interface UserAccountService {
    /**
     * 转账
     */
    public UserAccount change(String userId,BigDecimal bigDecimal,String userId2) throws Exception;
}
  • service实现层
import com.xiaohang.springboottransactional.entity.UserAccount;
import com.xiaohang.springboottransactional.repository.UserAccountRepository;
import com.xiaohang.springboottransactional.service.UserAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Service
public class UserAccountServiceImpl implements UserAccountService {

    @Autowired
    private UserAccountRepository userAccountRepository;

    @Transactional
    @Override
    public UserAccount change(String userId, BigDecimal bigDecimal, String userId2) throws Exception{
        UserAccount userAccount = userAccountRepository.findOne(userId);
        UserAccount userAccount2 = userAccountRepository.findOne(userId2);
        userAccount.setBalance(userAccount.getBalance().add(bigDecimal));
        userAccount2.setBalance(userAccount2.getBalance().subtract(bigDecimal));
        userAccountRepository.save(userAccount);
        int n=1/0;//throw new Exception();//假设发生故障
        userAccountRepository.save(userAccount2);
        return userAccountRepository.findOne(userId);

    }
}
  • 测试层
import com.xiaohang.springboottransactional.service.UserAccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.math.BigDecimal;

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserAccountServiceImplTest {

    @Autowired
    private UserAccountService userAccountService;

    @Test
    public void change() throws Exception {
        try {
            System.out.println(userAccountService.change("1",new BigDecimal("100"),"2"));
        }catch (Exception e){
            System.out.println("抛出异常");
        }
    }

}

三、测试



原始数据:



不开启事务,不抛出异常时:



不开启事务,抛出异常时(转账时发生错误,钱扣完,但是对方钱未到账;或者钱到帐了,但是钱未扣。)



先恢复数据:

开启事务,抛出异常时。

原文地址:https://www.cnblogs.com/jinxiaohang/p/8296549.html

时间: 2024-10-04 12:23:36

第10章—开启事务的相关文章

MySQL性能调优与架构设计——第10章 MySQL数据库Schema设计的性能优化

第10章 MySQL Server性能优化 前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化,但不包括mysqld之外的比如存储引擎相关的参数优化,存储引擎的相关参数设置建议将主要在下一章“常用存储引擎的优化”中进行说明. 10.1 MySQL 安装优化 选择合适的发行版本 1. 二进制发行版(包括RPM等包装好的特定二进制版本) 由于MySQL开源的特性,不仅仅MySQL AB提供了多个平

第10章,程序包管理学习笔记

更多内容请点击: Linux学习从入门到打死也不放弃,完全笔记整理(持续更新,求收藏,求点赞~~~~) http://blog.51cto.com/13683480/2095439 笔记整理开始时间:2018年4月20日14:07:22 第10章  程序包管理 本章内容 软件运行环境 软件包基础 rpm包管理 yum管理 定制yum仓库 编译安装 软件运行和编译: ABI: Application Binary  Interface 应用程序的二进制接口 window:       PE,Por

SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章)

SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章) 示例数据库:点我 CHAPTER 08 数据修改 8.1 插入数据 8.1.1 INSERT VALUES 语句 8.1.2 INSERT SELECT 语句 8.1.3 INSERT EXEC 语句 8.1.4 SELECT INTO 语句 8.1.5 BULK INSERT 语句 8.1.6 标识列属性和序列对象 8.1.6.1 标识列属性 8.1.6.2 序列对象 8.2 删除数据 8.2.1 DELETE 语

MySql开启事务

1 CREATE PROCEDURE test_sp1( ) 2 BEGIN 3 DECLARE t_error INTEGER DEFAULT 0; 4 DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1; 5 6 START TRANSACTION; 7 INSERT INTO test VALUES(NULL, 'test sql 001'); 8 INSERT INTO test VALUES('1', 'test sql 00

记录一次bug解决过程:resultType和手动开启事务

一.总结 二.BUG描述:MyBatis中resultType使用 MyBatis中的resultType类似于入参:parameterType.先看IDCM项目中的实际使用案例代码,如下: // List<Integer> orderIds = assetBeanMapperExt.getOrderIdsByParentIds(SqlStringUtil.formatInStr(logisticsOrder.getParentIds())); 我们的目的是通过*Ext层直接返回一个list,

我的学习之路_第二十二章_事务

JDBC事务 [事务] 作用: 保证多条SQL语句,要么都执行成功,要么都执行失败. mysql数据库,执行SQL语句,自动开启事务,提交事务,回滚事务,把数据永久保存 oracle数据库,执行SQL语句,手动开始会务,提交事务,回滚事务,把数据永久保存. Connection接口中和事务有关的方法: 无返回值 setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态. 参数:autoCommit : true表示自动提交模式, false表示禁用

[摘录]第10章 培养胜过对手的力量

第五部分 谈判高手 优势秘籍力量.控制和影响,是每个人与别人交往时都会追求这些东西.不是吗?在进行谈判时,那些最有影响力火灾是最有力量的一方往往会在谈判时迫使对手做出更多的让步.如果你甘心让对手来操纵或影响你的话,显然你就很可能得不到自己想要的结果.另一方面,如果你直到哪些因素,能影响你的对手,并知道如何使用一些具体的方法来形成这种影响力,你就可以将形势控制在自己手中.权力本身也可以成为一种非常富有建设性的力量,当我们谈论权力时,我并不是指独裁者们用来祸害平民们的那种权力,我所说的权力实际上是一

10-11-基数排序-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第10章  内部排序 - 基数排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.Scanf.c        相关测试数据下载  链接? 数据

读《构建之法》第8、9、10章有感

第8章  需求分析 软件需求 用户的需求五花八门,作为一个软件团队要准确而全面地获取这些需求主要有以下四个步骤: 获取和引导需求.这一步骤也被叫做“需求捕捉”.软件团队需要为用户着想,设身处地,为用户引导出需求. 分析和定义需求.从各个方面获取的需求进行规整,定义需求的内涵从各个角度将需求量化. 验证需求.软件团队要跟利益相关者沟通,通过分析报告.技术原型.用户调查或演示等形式向他们验证软件团队对于这些需求的认知. 在软件产品的生命周期中管理需求. 竞争性需求分析的框架:1.N(需求) 2.A(