本文源码:GitHub·点这里 || GitEE·点这里

一、事务管理简介

1、事务基本概念

一组业务操作ABCD,要么全部成功,要么全部不成功。

2、特性:ACID

原子性:整体

一致性:完成

隔离性:并发

持久性:结果

3、隔离问题

脏读:一个事务读到另一个事务没有提交的数据

不可重复读:一个事务读到另一个事务已提交的数据(update)

虚读(幻读):一个事务读到另一个事务已提交的数据(insert)

4、隔离级别

read uncommitted:读未提交。

read committed:读已提交。解决脏读。

repeatable read:可重复读。解决:脏读、不可重复读。

serializable :串行化。都解决,单事务。

二、Spring管理事务

1、顶级接口



1)PlatformTransactionManager

平台事务管理器,spring要管理事务,必须使用事务管理器进行事务配置时,必须配置事务管理器。

2)TransactionDefinition

事务详情(事务定义、事务属性),spring用于确定事务具体详情,

例如:隔离级别、是否只读、超时时间 等

进行事务配置时,必须配置详情。spring将配置项封装到该对象实例。

3)TransactionStatus

事务状态,spring用于记录当前事务运行状态。例如:是否有保存点,事务是否完成。

spring底层根据状态进行相应操作。

2、事务状态

3、事务定义

PROPAGATION_REQUIRED , required , 必须  【默认值】
支持当前事务,A如果有事务,B将使用该事务。
如果A没有事务,B将创建一个新的事务。
PROPAGATION_SUPPORTS ,supports ,支持
支持当前事务,A如果有事务,B将使用该事务。
如果A没有事务,B将以非事务执行。
PROPAGATION_MANDATORY,mandatory ,强制
支持当前事务,A如果有事务,B将使用该事务。
如果A没有事务,B将抛异常。
PROPAGATION_REQUIRES_NEW , requires_new ,必须新的
如果A有事务,将A的事务挂起,B创建一个新的事务
如果A没有事务,B创建一个新的事务
PROPAGATION_NOT_SUPPORTED ,not_supported ,不支持
如果A有事务,将A的事务挂起,B将以非事务执行
如果A没有事务,B将以非事务执行
PROPAGATION_NEVER ,never,从不
如果A有事务,B将抛异常
如果A没有事务,B将以非事务执行
PROPAGATION_NESTED ,nested ,嵌套
A和B底层采用保存点机制,形成嵌套事务。
掌握:PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED

三、SpringBoot2.0管理事务

基于转账的案例演示,基于druid连接池配置。druid连接池在文章。

SpringBoot2.0 基础案例(07):集成Druid连接池,配置监控界面

1、新建转账表

CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
money INT
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO account(username,money) VALUES('jack','10000');
INSERT INTO account(username,money) VALUES('rose','10000');
SELECT * FROM account;

2、基于事务手动管理器

该配置用于测试事务的手动管理。

/**
* 事物管理器
*/
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager (DruidDataSource dataSource){
LOGGER.info("【transactionManager 初始化...】");
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
/**
* 创建事物手动管理模板
*/
@Bean(name = "transactionTemplate")
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager)
LOGGER.info("【transactionTemplate 初始化...】");
TransactionTemplate transactionTemplate = new TransactionTemplate() ;
transactionTemplate.setTransactionManager(transactionManager);
return transactionTemplate;
}

3、封装转账接口

接口方法

public interface AccountService {
/**
* 汇款
*/
void out (String outer , Integer money);
/**
* 收款
*/
void in (String inner , Integer money);
}

接口实现

@Service
public class AccountServiceImpl implements AccountService {
@Resource
private JdbcTemplate jdbcTemplate ;
public void out(String outer, Integer money) {
String sql = "update account set money = money - ? where username = ?";
jdbcTemplate.update(sql, money,outer);
}
public void in(String inner, Integer money) {
String sql = "update account set money = money + ? where username = ?";
jdbcTemplate.update(sql, money,inner);
}
}

4、封装三个测试接口

测试接口

public interface TradeService {
/**
* 转账交易:没有事务管理
*/
void trade1(String outer ,String inner ,Integer money);
/**
* 转账交易:手动管理事务
*/
void trade2(String outer ,String inner ,Integer money);
/**
* 转账交易:注解管理事务
*/
void trade3(String outer ,String inner ,Integer money);
}

接口实现

@Service
public class TradeServiceImpl implements TradeService { @Resource
private AccountService accountService ;
@Resource
private TransactionTemplate transactionTemplate ; @Override
public void trade1(String outer, String inner, Integer money) {
accountService.out(outer, money);
// 抛出异常
int i = 1/0;
accountService.in(inner, money);
} @Override
public void trade2(String outer, String inner, Integer money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus arg0) {
accountService.out(outer, money);
// 抛出异常
int i = 1/0;
accountService.in(inner, money);
}
});
} @Transactional(value="transactionManager",propagation= Propagation.REQUIRED)
@Override
public void trade3(String outer, String inner, Integer money) {
accountService.out(outer, money);
// 抛出异常
int i = 1/0;
accountService.in(inner, money);
}
}

5、编写测试类

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TransactionApplication.class)
public class TradeTest {
@Resource
private TradeService tradeService ;
/**
* 没有事务管理
* jack 减少了1000块钱,但是rose得到1000块钱
* 1 jack 9000
* 2 rose 10000
*/
@Test
public void testTrade1 (){
tradeService.trade1("jack", "rose", 1000);
}
/**
* 手动管理事务
* 1 jack 10000
* 2 rose 10000
*/
@Test
public void testTrade2 (){
tradeService.trade2("jack", "rose", 1000);
}
/**
* 注解管理事务
* 1 jack 10000
* 2 rose 10000
*/
@Test
public void testTrade3 (){
tradeService.trade3("jack", "rose", 1000);
}
}

四、源代码地址

GitHub·地址
https://github.com/cicadasmile/spring-boot-base
GitEE·地址
https://gitee.com/cicadasmile/spring-boot-base

SpringBoot2.0 基础案例(12):基于转账案例,演示事务管理操作的更多相关文章

  1. (六)SpringBoot2.0基础篇- Redis整合(JedisCluster集群连接)

    一.环境 Redis:4.0.9 SpringBoot:2.0.1 Redis安装:Linux(Redhat)安装Redis 二.SpringBoot整合Redis 1.项目基本搭建: 我们基于(五) ...

  2. 4-9 基于Spring JDBC的事务管理(续)

    10. 基于Spring JDBC的事务管理(续) 当需要方法是事务性的,可以使用@Transactional注解,此注解可以添加在: 接口 会使得此接口的实现类的所有实现方法都是事务性的 接口中的抽 ...

  3. 【Spring实战】—— 16 基于JDBC持久化的事务管理

    前面讲解了基于JDBC驱动的Spring的持久化管理,本篇开始则着重介绍下与事务相关的操作. 通过本文你可以了解到: 1 Spring 事务管理的机制 2 基于JDBC持久化的事务管理 Spring的 ...

  4. 谈谈分布式事务之二:基于DTC的分布式事务管理模型[下篇]

    [续上篇] 当基于LTM或者KTM的事务提升到基于DTC的分布式事务后,DTC成为了本机所有事务型资源管理器的管理者:此外,当一个事务型操作超出了本机的范 围,出现了跨机器的调用后,本机的DTC需要于 ...

  5. SpringBoot2.0 基础案例(14):基于Yml配置方式,实现文件上传逻辑

    本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.文件上传 文件上传是项目开发中一个很常用的功能,常见的如头像上 ...

  6. SpringBoot2.0 基础案例(13):基于Cache注解模式,管理Redis缓存

    本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.Cache缓存简介 从Spring3开始定义Cache和Cac ...

  7. SpringBoot2.0基础案例(01):环境搭建和RestFul风格接口

    一.SpringBoot 框架的特点 1.SpringBoot2.0 特点 1)SpringBoot继承了Spring优秀的基因,上手难度小 2)简化配置,提供各种默认配置来简化项目配置 3)内嵌式容 ...

  8. SpringBoot2.0 基础案例(15):配置MongoDB数据库,实现增删改查逻辑

    本文源码:GitHub·点这里 || GitEE·点这里 一.NoSQL简介 1.NoSQL 概念 NoSQL( Not Only SQL ),意即"不仅仅是SQL".对不同于传统 ...

  9. SpringBoot2.0 基础案例(10):整合Mybatis框架,集成分页助手插件

    一.Mybatis框架 1.mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获 ...

随机推荐

  1. UVA - 10305 【拓扑排序】

    题意 给出一些任务的优先级别 将这些任务进行的时间 进行先后排序 思路 拓扑排序 将所以有先后关系的任务都连一条边 然后每次 输出 度为0 的任务 每次把 以这个任务为弧的边 都取消 相对应任务的度也 ...

  2. POJ - 1321 棋盘问题 【DFS】

    题目链接 http://poj.org/problem?id=1321 思路 和N皇后问题类似 但是有一点不同的是 这个是只需要摆放K个棋子就可以了 所以 我们要做好 两个出口 并且要持续往下一层找 ...

  3. java进程分析

    1. 找出 java进程pid,比如 11327 2. 使用jstack 看下 锁持有情况 /usr/java/latest/bin/jstack  -l 11327 3. 输出java堆栈信息,以及 ...

  4. 分享知识-快乐自己:自定义struts2类型转换的全局与局部错误信息。

    遇到类型转换错误的时候(也就是说不能进行类型转换),struts2框架自动生成一条错误信息,并且将该错误信息放到addFieldError里面.我们可以通过配置文件来替换这条由struts2自动生成的 ...

  5. 线程绑定CPU核-sched_setaffinity

    CPU亲合力就是指在Linux系统中能够将一个或多个进程绑定到一个或多个处理器上运行. 一个进程的CPU亲合力掩码决定了该进程将在哪个或哪几个CPU上运行.在一个多处理器系统中,设置CPU亲合力的掩码 ...

  6. 集训Day9

    又是不想学化学但元气满满的一天呢qwq 今天又有新的故事发生那就是! bzoj2150 最小流 每个点拆成$a_x$和$a_y$ $S$->$a_x$容量为1 $a_y$->$T$容量为1 ...

  7. java面试题07

    1.重载和重写的区别? 重载(Overload):(1)方法重载是让类以统一的方式处理不同类型数据的一种手段.多个同名函数同时存在,具有不同的参数个数/类型.重载Overloading是一个类中多态性 ...

  8. yum 命令用法

    [root@hdp01 ~]# yum list available |grep ambari  ######列出可安装的程序包ambari-infra-solr.noarch 2.6.1.5-3 a ...

  9. liunx让命令窗口显示段路径的方法

    平时我们使用linux终端命令行的时候,常常会被一个问题困扰,那就是文件路径过长,有时候甚至超过了一行,这样看起来非常别扭,其实只要两步就可以解决这个问题: 1,修改.bashrc文件(用户根目录下) ...

  10. Vijos:P1234口袋的天空

    背景 小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空. 有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖. 描述 给你云朵的个数N,再给你M个关系,表示哪些云朵可以连在一起. ...