😀前言
本篇是Spring 声明式事务系列的第二篇介绍了Spring 声明式事务机制
🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉
在csdn获奖荣誉: 🏆csdn城市之星2名
💓Java全栈群星计划top前5
🤗 端午大礼包获得者
💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客,感谢大家的观看🥰
如果文章有什么需要改进的地方还请大佬不吝赐教 先在次感谢啦😊
重点分析了 REQUIRED 和 REQUIRED_NEW 两种事务 传播属性, 其它知道即可(看上图)
buyGoods2 如果错误,不会影响到 buyGoods()反之亦然,即它们的事务是独立的.
buyGoods2 和 buyGoods 是一个整体,只要有方法的事务错误,那么两个方法都不会执行成功.!
● 事务的传播机制需要说明
public class GoodsDao {
/**
* 根据商品id,返回对应的价格
* @param id
* @return
*/
public Float queryPriceById2(Integer id) {
String sql = "SELECT price From goods Where goods_id=?";
Float price = jdbcTemplate.queryForObject(sql, Float.class, id);
return price;
}
/**
* 修改用户的余额 [减少用户余额]
* @param user_id
* @param money
*/
public void updateBalance2(Integer user_id, Float money) {
String sql = "UPDATE user_account SET money=money-? Where user_id=?";
jdbcTemplate.update(sql, money, user_id);
}
/**
* 修改商品库存 [减少]
* @param goods_id
* @param amount
*/
public void updateAmount2(Integer goods_id, int amount){
String sql = "UPDATE goods_amount SET goods_num=goods_num-? Where goods_id=?";
jdbcTemplate.update(sql, amount , goods_id);
}
}
注解解读
1. 使用@Transactional 可以进行声明式事务控制
2. 即将标识的方法中的,对数据库的操作作为一个事务管理
3. @Transactional 底层使用的仍然是AOP机制
4. 底层是使用动态代理对象来调用buyGoodsByTx
5. 在执行buyGoodsByTx() 方法 先调用 事务管理器的 doBegin() , 调用 buyGoodsByTx()
如果执行没有发生异常,则调用 事务管理器的 doCommit(), 如果发生异常 调用事务管理器的 doRollback()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void buyGoodsByTx(int userId, int goodsId, int amount) {
//输出购买的相关信息
System.out.println("用户购买信息 userId=" + userId
+ " goodsId=" + goodsId + " 购买数量=" + amount);
//1.得到商品的价格
Float price = goodsDao.queryPriceById(userId);
//2. 减少用户的余额
goodsDao.updateBalance(userId, price * amount);
//3. 减少库存量
goodsDao.updateAmount(goodsId, amount);
System.out.println("用户购买成功~");
}
@Transactional
public void buyGoodsByTx2(int userId, int goodsId, int amount) {
//输出购买的相关信息
System.out.println("用户购买信息 userId=" + userId
+ " goodsId=" + goodsId + " 购买数量=" + amount);
//1.得到商品的价格
Float price = goodsDao.queryPriceById2(userId);
//2. 减少用户的余额
goodsDao.updateBalance2(userId, price * amount);
//3. 减少库存量
goodsDao.updateAmount2(goodsId, amount);
System.out.println("用户购买成功~");
}
multiBuyGoodsByTx 这个方法 有两次购买商品操作
buyGoodsByTx 和 buyGoodsByTx2 都是声明式事务
当前buyGoodsByTx 和 buyGoodsByTx2 使用的传播属性是默认的 REQUIRED [这个含义前面讲过了
即会当做一个整体事务进行管理 , 比如buyGoodsByTx方法成功,但是buyGoodsByTx2() 失败,会造成 整个事务的回滚 即会回滚buyGoodsByTx
如果 buyGoodsByTx 和 buyGoodsByTx2 事务传播属性修改成 REQUIRES_NEW
这时两个方法的事务是独立的,也就是如果 buyGoodsByTx成功 buyGoodsByTx2失败, 不会造成 buyGoodsByTx回滚.
@Service
public class MultiplyService {
@Resource
private GoodsService goodsService;
@Transactional
public void multiBuyGoodsByTx() {
goodsService.buyGoodsByTx(1, 1, 1);
goodsService.buyGoodsByTx2(1, 1, 1);
}
}
可以验证:为 REQUIRED buyGoodsByTx 和 buyGoodsByTx02 是整体, 只要有方法的事务错误,那么两个方法都不会执行成功
@Test
public void buyGoodsByMulTxTest() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("tx_ioc.xml");
MultiplyTxService bean = ioc.getBean(MultiplyTxService.class);
bean.multiTxTest();
System.out.println("------ok--------");
}
故意写错
将 传 播 机 制 改 成 REQUIRES_NEW 可 以 验 证 : 设 置 为 REQUIRES_NEW
buyGoodsByTx 如果错误不会影响到 buyGoodsByTx02()反之亦然,也就 是说它们的事务是独立的
将二个方法的 @Transactional修改为下面的这种形式 完成测试
@Transactional(propagation = Propagation.REQUIRES_NEW)
本篇介绍了事务传播机制种类和事务的传播机制-应用实例希望可以帮到大家
😘Spring 声明式事务系列
第一篇–> 什么是Spring 声明式事务详细讲解
😁热门专栏推荐
想学习vue的可以看看这个
java基础合集
数据库合集
redis合集
nginx合集
linux合集
等等等还有许多优秀的合集在主页等着大家的光顾感谢大家的支持
🤔欢迎大家加入我的社区 尘觉社区
文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁
希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞