以下是几个使用Spring事务处理订单的案例,涵盖了声明式事务和分布式事务的场景:
### 1\. 声明式事务处理订单
#### 场景描述
用户下单时,需要完成以下操作:
1. 创建订单记录。
2. 扣减库存。
3. 扣减用户余额。
如果任何一个步骤失败,整个操作需要回滚。
#### 代码实现
```java
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private InventoryService inventoryService;
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
timeout = 30,
rollbackFor = {InsufficientStockException.class, PaymentFailedException.class}
)
public void placeOrder(Order order) {
inventoryService.reduceStock(order.getItems()); // 可能抛出 InsufficientStockException
orderRepository.save(order);
processPayment(order); // 可能抛出 PaymentFailedException
}
private void processPayment(Order order) {
// 支付逻辑
}
}
```
#### 事务说明
- 使用`@Transactional`注解声明事务,指定传播行为为`REQUIRED`,隔离级别为`READ_COMMITTED`,超时时间为30秒。
- 如果在扣减库存或支付过程中抛出异常,事务会回滚,确保订单记录、库存和用户余额的状态保持一致。
### 2\. 分布式事务处理订单支付
#### 场景描述
跨服务的订单支付涉及订单服务、支付服务和库存服务,需要保证跨服务事务的一致性。
#### 代码实现
```java
@Service
public class DistributedOrderService {
@Autowired
private OrderService orderService;
@Autowired
private PaymentService paymentService;
@Autowired
private InventoryService inventoryService;
@GlobalTransactional(name = "createOrderTx", timeoutMills = 30000)
public void createOrderWithPayment(OrderRequest request) {
// 1. 创建订单(本地事务)
Order order = orderService.create(request);
// 2. 调用支付服务(远程事务)
paymentService.process(order.getId(), order.getAmount());
// 3. 扣减库存(跨服务调用)
inventoryService.deduct(order.getProductId(), order.getQuantity());
}
}
```
#### 事务说明
- 使用Seata实现分布式事务管理,通过`@GlobalTransactional`注解声明全局事务。
- 如果任何一个服务(订单服务、支付服务、库存服务)失败,全局事务会回滚,确保数据一致性。
### 3\. 声明式事务处理复杂订单逻辑
#### 场景描述
用户下单时,需要完成以下操作:
1. 验证订单信息。
2. 锁定库存。
3. 扣减用户余额。
4. 使用优惠券(如果有)。
5. 创建订单记录。
#### 代码实现
```java
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
@Autowired
private AccountDao accountDao;
@Autowired
private CouponDao couponDao;
@Autowired
private InventoryService inventoryService;
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
timeout = 30,
rollbackFor = {BusinessException.class, RuntimeException.class}
)
@Override
public OrderResult createOrder(OrderRequest request) throws BusinessException {
// 1. 验证订单基本信息
validateOrderRequest(request);
// 2. 锁定库存(使用REQUIRES_NEW传播行为,独立事务)
inventoryService.lockInventory(request.getProductId(), request.getQuantity());
// 3. 扣减账户余额
deductAccountBalance(request.getUserId(), request.getTotalAmount());
// 4. 使用优惠券(如果有)
if (request.getCouponId() != null) {
useCoupon(request.getUserId(), request.getCouponId());
}
// 5. 创建订单
Order order = createOrderRecord(request);
// 6. 发送创建订单事件(异步,不影响主事务)
sendOrderCreatedEvent(order);
return convertToResult(order);
}
private void validateOrderRequest(OrderRequest request) throws BusinessException {
// 验证逻辑...
if (request.getQuantity() <= 0) {
throw new BusinessException("购买数量必须大于0");
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void lockInventory(Long productId, int quantity) throws BusinessException {
// 锁定库存逻辑...
}
private void deductAccountBalance(Long userId, BigDecimal amount) throws BusinessException {
// 扣减余额逻辑...
}
@Transactional(propagation = Propagation.MANDATORY)
public void useCoupon(Long userId, Long couponId) throws BusinessException {
// 使用优惠券逻辑...
}
private Order createOrderRecord(OrderRequest request) {
// 创建订单记录逻辑...
}
private void sendOrderCreatedEvent(Order order) {
// 异步发送事件...
}
}
```
#### 事务说明
- 使用`@Transactional`注解声明事务,指定传播行为和隔离级别。
- 对于锁定库存的操作,使用`Propagation.REQUIRES_NEW`传播行为,确保其独立提交,即使主事务失败也不会影响库存锁定操作。
### 4\. 编程式事务处理订单
#### 场景描述
使用编程式事务处理订单创建逻辑。
#### 代码实现
```java
@Service
public class OrderService {
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private OrderRepository orderRepository;
public CreateOrderResult createOrder(CreateOrderRequest request) {
GenericTransactionTemplate<CreateOrderRequest, CreateOrderResult> template =
new GenericTransactionTemplate<>(transactionManager);
return template.execute(request, new GenericTransactionTemplate.TransactionProcessor<>() {
@Override
public Function<CreateOrderRequest, CreateOrderResult> consume() {
return req -> {
// 事务内核心逻辑
Order order = new Order();
order.setUserId(req.getUserId());
order.setAmount(req.getAmount());
orderRepository.save(order);
return new CreateOrderResult(order.getId(), "SUCCESS");
};
}
@Override
public Predicate<CreateOrderRequest> filter() {
// 过滤非法金额订单
return req -> req.getAmount().compareTo(BigDecimal.ZERO) > 0;
}
@Override
public void verify(CreateOrderRequest req) {
if (req.getUserId() == null) {
throw new IllegalArgumentException("User ID cannot be null");
}
}
@Override
public void onTransactionException(Exception e) {
log.error("Order creation failed in transaction: {}", request, e);
}
@Override
public void afterCompletion() {
log.info("Order processing completed for request: {}", request);
}
}, TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 使用独立事务
}
}
```
#### 事务说明
- 使用`PlatformTransactionManager`和`GenericTransactionTemplate`实现编程式事务。
- 在事务中完成订单创建逻辑,并在异常时进行处理。
以上案例展示了Spring事务在不同场景下的应用,包括单体应用中的声明式事务、分布式事务以及编程式事务。
- 环境配置
- window怎么配置java环境变量?
- Java基础语法
- 数据类型
- Java中的数据类型
- Java中的泛型容器
- Java中的JSONObject
- Java高级特性
- Maven
- jib-maven-plugin
- 什么是Spring Boot 的 parent pom?
- maven中各个生命周期的含义
- Spring Boot
- maven与spring boot 的关系
- Java中的连接池
- Spring JDBC
- Spring JDBC的概念
- JdbcTemplate常用的方法
- Spring中Bean的概念
- Spring中的抽象,通俗解释一下
- Spring中的事物
- Spring中的事物,通俗解释一下
- Spring中的事物抽象,常见的有哪些,列举一下
- Spring中常用的事物场景有哪些,列举一下
- Spring事务管理有哪些注解?
- Spring中使用事物处理订单的案例,列举说明一下
- Spring中声明式事务、分布式事务以及编程式事务的区别,列举一下
- 配置文件
- application-properties配置文件
- Spring Boot 的启动
- spring boot项目如何启动?
- 列举一下Spring Boot的启动过程
- SpringApplication.run方法
- Spring Boot 启动时有哪些接口?
- CommandLineRunner
- Spring Boot 的常用注解
- 系统注解
- 表格:系统注解
- @Override
- @Deprecated
- @SuppressWarnnings
- 使用在类名上的注解
- 表格:使用在类名上的注解
- @RestController
- @Controller
- @Service
- @Repository
- @Component
- @Configuration
- @Resource
- @Autowired
- @RequestMapping
- @GetMapping
- @PostMapping
- @Transactional
- @Qualifier
- 使用在方法上的注解
- 表格:使用在方法上的注解
- @RequestBody
- @PathVariable
- @Bean
- @ResponseBody
- @PreAuthorize
- 其他常用注解
- 表格:其他常用注解
- @EnableAutoConfiguration
- @SpringBootApplication
- @EnableScheduling
- @EnableAsync
- @ComponentScan
- @Aspec
- @ControllerAdvice
- @ExceptionHandler
- @Value
- @ConfigurationProperties
- @EnableConfigurationProperties
- @MapperScan
- @ApiOperation
- Validator验证的常用注解
- spring IoC容器
- Spring IoC容器依赖注入实现方式
- MyBatis
- paginationInterceptor
- @TableName
- @TableId
- @Param
- UrlBasedCorsConfigurationSource
- Lombok
- @Data
- @Slf4j
- @EqualsAndHashCode
- @Accessors
- 支付系统
- 1. 初始化mysql数据库流程
- 2. 初始化redis数据库的流程
- 3. 初始化rabbitmq服务
- 环球置业
- 1.模块目录结构分析
- 2. DTO(数据传输层)的核心作用
- 3. VO(视图对象层)
- 4. VO(视图对象层)和 DTO 数据传输层 的区别
