下面是对“Spring中的事务传播行为示例详解”的完整攻略:
下面是对“Spring中的事务传播行为示例详解”的完整攻略:
简介
Spring框架提供了事务管理机制,使用该机制可以方便地实现事务控制,避免出现数据的脏读、不可重复读和幻读问题。在Spring事务管理机制中,事务传播行为是一个很重要的概念,它可以控制事务的触发范围,处理运行中的事务该如何被其他事务影响。
在这篇攻略中,我们将会详细讲解Spring中的事务传播行为,并通过示例来说明它是如何影响事务的执行结果的。
事务传播行为介绍
Spring事务管理机制中,事务传播行为是一个非常重要的特性。它描述了事务在被嵌套执行时,当前的事务如何与新的事务进行交互。
以下是事务传播行为的7种选项:
- PROPAGATION_REQUIRED(默认):支持当前事务,如果当前没有事务,就新建一个事务。这是最常用的选项。
- PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务的方式执行。
- PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW:新建事务,如果当前有事务,就把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED:以非事务的方式执行操作,如果当前有事务,就把当前事务挂起。
- PROPAGATION_NEVER:以非事务的方式执行,如果当前有事务,则抛出异常。
- PROPAGATION_NESTED:如果当前事务存在,则嵌套执行子事务,子事务可以独立地提交或回滚,主事务正常结束会导致子事务的提交,而主事务的回滚会导致所有的子事务都回滚。
示例说明
示例一:PROPAGATION_REQUIRED
@Service
public class ProductService {
@Autowired
private ProductMapper productMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void updateProduct(Product product) {
// 第一次更新
productMapper.updateProduct(product);
System.out.println("第一次更新成功");
// 抛出异常
System.out.println(1 / 0);
// 第二次更新
productMapper.updateProduct(product);
System.out.println("第二次更新成功");
}
}
上述代码中,我们定义了一个更新商品信息的Service,并给Service添加了@Transactional注解,其中propagation设置为REQUIRED。这时,更新商品信息的方法updateProduct就成为了一个事务边界,一旦有任何一个更新操作抛出异常,事务就会回滚。
对于上述代码中的updateProduct()方法,它会在执行第一次更新后,手动抛出一个异常。因此,在这种情况下,我们只能看到“第一次更新成功”这条信息的输出。事务终止了,并且对于数据库中已经提交的信息也进行了回滚。
示例二:PROPAGATION_REQUIRES_NEW
@Service
public class ProductService {
@Autowired
private ProductMapper productMapper;
@Autowired
private PurchaseService purchaseService;
@Transactional(propagation = Propagation.REQUIRED)
public void purchaseProduct(Product product, User user) {
// 更新商品信息
productMapper.updateProduct(product);
// 购买商品
try {
purchaseService.addPurchase(user.getUserId(), product.getProductId());
} catch (Exception e) {
System.out.println("购买出现异常: " + e.getMessage());
}
// 操作结束
System.out.println("操作完成");
}
}
@Service
public class PurchaseService {
@Autowired
private PurchaseMapper purchaseMapper;
@Autowired
private ProductService productService;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addPurchase(String userId, Integer productId) {
// 新增购买信息
purchaseMapper.insertPurchase(userId, productId);
// 更新商品信息
productService.updateProductById(productId);
}
}
上述代码中,我们定义了两个Service:ProductService和PurchaseService。在ProductService中,我们有一个purchaseProduct(Product product, User user)方法,它的更新操作和添加purchase记录操作需要在同一事务中提交。我们在PurchaseService中定义一个PROPAGATION_REQUIRES_NEW的事务传播模式的addPurchase()方法,用来实现购买的操作。此时,对于updateProduct()方法和addPurchase()方法,分别成为不同的事务边界。
通过以上的事务传播行为的设置,我们可以实现一个功能:当purchaseService的方法抛出异常时,能够只回滚purchaseService方法中的事务,而不回滚需要在purchaseService之外执行的productService方法中的事务。并且,在购买操作执行成功后,会正常输出“操作完成”的信息。
结论
Spring中的事务传播行为是很重要的一个概念。通过设置不同的事务传播模式,我们可以在不同的业务场景下,控制事务的范围,有效的避免因为事务嵌套等问题导致的事务逻辑错误。我们可以通过以上的例子来更好地理解其中的操作和运行机制。
本文标题为:Spring中的事务传播行为示例详解
- 一文详解Redis为什么一定要设置密码原理 2023-07-13
- MySQL DBA教程:Mysql性能优化之缓存参数优化 2023-12-22
- 一篇文章掌握MySQL的索引查询优化技巧 2023-12-22
- 实现在线 + 离线模式进行迁移 Redis 数据实战指南 2023-07-12
- 最新Navicat 15 for MySQL破解+教程 正确破解步骤 2023-07-26
- Myeclipse链接Oracle等数据库时lo exception: The Network Adapter could not establish the connection 2023-12-05
- oracle mysql 拼接值遇到的坑及双竖线 || concat详解 2023-07-24
- Redis(一):NoSQL入门和概述 2023-09-12
- MySQL和Oracle批量插入SQL的通用写法示例 2023-08-06
- Redis(二):Redis入门介绍 2023-09-11