SpringBoot2.0 基础案例(12):基于转账案例,演示事务管理操作
本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base
一、事务管理简介
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 码云地址:知了一笑 https://gitee.com/cicadasmile/spring-boot-base
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java创建数组的三种形式
Java创建数组的三种形式 测试类: package cn.wsyjlly.base; import java.util.Arrays; /** * @author wsyjlly * @create 2019.08.18 - 15:11 **/ public class StringOperator { public static void main(String[] args) { //方式一:声明并赋初值,声明和赋值不可以分开写 String[] str1 = {"aaa","bbb","ccc"}; //方式二:先声明,后赋值,声明和赋值可以分开写。 String[] str2 = new String[]{"aaa","bbb","ccc"}; //方式三:先声明,后赋默认值,声明和赋值可以分开写。 String[] str3; str3 = new String[3]; Character[] str4 = new Character[3]; Integer[] str5 = new Integer[3]; char[] str6 = new char[3]; byte[]...
- 下一篇
16个Spring注解,你知道的有几个?
@Controller标识一个该类是Spring MVC controller处理器,用来创建处理http请求的对象. @RestControllerSpring4之后加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默认返回json格式。 @Service用于标注业务层组件,说白了就是加入你有一个用注解的方式把这个类注入到spring配置中 @Autowired用来装配bean,都可以写在字段上,或者方法上。默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,例如:@Autowired(required=false) @RequestMapping类定义处: 提供初步的请求映射信息,相对于 WEB 应用的根目录。方法处: 提供进一步的细分映射信息,相对于类定义处的 URL。 @RequestParam用于将请求参数区数据映射到功能处理方法的参数上例如 这个id就是要接收从接口传递过来的...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS关闭SELinux安全模块
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- 设置Eclipse缩进为4个空格,增强代码规范
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7安装Docker,走上虚拟化容器引擎之路