Spring Data JPA 注解详解
📦 完整代码示例 :https://github.com/penghs520/springboot-transaction
目录
@Modifying 注解
@Lock 注解
@Query 注解
@Transactional 注解
@Entity 相关注解
@Repository 注解
实际应用示例
最佳实践
总结
@Modifying 注解 作用 @Modifying 注解用于标识执行修改操作(INSERT、UPDATE、DELETE)的查询方法,告诉Spring Data JPA这是一个修改操作而不是查询操作。
语法 1 2 3 4 5 6 @Modifying( clearAutomatically = false, // 是否自动清除一级缓存 flushAutomatically = false // 是否自动刷新到数据库 ) @Query("UPDATE Entity e SET e.field = :value WHERE e.id = :id") int updateMethod (@Param("id") Long id, @Param("value") String value) ;
关键特性 1. 返回值类型
int : 返回受影响的行数
void : 不返回任何值
boolean : 返回操作是否成功
2. 事务要求
必须在事务内执行 ,否则抛出 TransactionRequiredException
通常与 @Transactional 注解配合使用
3. 缓存处理 1 2 3 @Modifying(clearAutomatically = true) @Query("UPDATE User u SET u.name = :name WHERE u.id = :id") int updateUserName (@Param("id") Long id, @Param("name") String name) ;
项目中的实际应用 1 2 3 4 5 6 7 8 9 @Modifying @Query("UPDATE UserAccount ua SET ua.balance = ua.balance - :amount WHERE ua.userId = :userId AND ua.balance >= :amount") int deductBalance (@Param("userId") Long userId, @Param("amount") BigDecimal amount) ;@Modifying @Query("UPDATE Inventory i SET i.stockQuantity = i.stockQuantity - :quantity WHERE i.productId = :productId AND i.stockQuantity >= :quantity") int deductStock (@Param("productId") Long productId, @Param("quantity") Integer quantity) ;
实现机制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class ModifyingQueryExecutor { public Object execute (Query query, Object[] parameters) { if (method.isAnnotationPresent(Modifying.class)) { int affectedRows = entityManager.createQuery(jpqlQuery) .setParameters(parameters) .executeUpdate(); if (modifying.clearAutomatically()) { entityManager.clear(); } if (modifying.flushAutomatically()) { entityManager.flush(); } return affectedRows; } } }
@Lock 注解 作用 @Lock 注解用于在查询时对数据库记录加锁,防止并发访问时的数据不一致问题。
语法 1 2 3 @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT e FROM Entity e WHERE e.id = :id") Optional<Entity> findByIdWithLock (@Param("id") Long id) ;
锁模式类型 1. 悲观锁(Pessimistic Locking) 1 2 3 4 5 6 7 8 9 @Lock(LockModeType.PESSIMISTIC_READ) @Query("SELECT u FROM User u WHERE u.id = :id") Optional<User> findByIdForRead (@Param("id") Long id) ; @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT u FROM User u WHERE u.id = :id") Optional<User> findByIdForUpdate (@Param("id") Long id) ;
2. 乐观锁(Optimistic Locking) 1 2 3 4 5 6 7 8 9 @Lock(LockModeType.OPTIMISTIC) @Query("SELECT u FROM User u WHERE u.id = :id") Optional<User> findByIdOptimistic (@Param("id") Long id) ; @Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT) @Query("SELECT u FROM User u WHERE u.id = :id") Optional<User> findByIdOptimisticWrite (@Param("id") Long id) ;
数据库层面的SQL实现 1 2 3 4 5 6 7 8 9 10 SELECT * FROM user_account WHERE user_id = ? FOR UPDATE ;SELECT * FROM user_account WHERE user_id = ? FOR UPDATE ;SELECT * FROM user_account WITH (UPDLOCK) WHERE user_id = ?;
项目中的实际应用 1 2 3 4 5 6 7 8 9 @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT ua FROM UserAccount ua WHERE ua.userId = :userId") Optional<UserAccount> findByUserIdWithLock (@Param("userId") Long userId) ; @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT i FROM Inventory i WHERE i.productId = :productId") Optional<Inventory> findByProductIdWithLock (@Param("productId") Long productId) ;
并发控制示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest orderRequest) { UserAccount userAccount = userAccountRepository.findByUserIdWithLock(orderRequest.getUserId()) .orElseThrow(() -> new BusinessException ("USER_NOT_FOUND" , "用户账户不存在" )); Inventory inventory = inventoryRepository.findByProductIdWithLock(orderRequest.getProductId()) .orElseThrow(() -> new BusinessException ("PRODUCT_NOT_FOUND" , "产品不存在" )); int stockUpdated = inventoryRepository.deductStock(orderRequest.getProductId(), orderRequest.getQuantity()); int balanceUpdated = userAccountRepository.deductBalance(orderRequest.getUserId(), totalAmount); if (stockUpdated == 0 || balanceUpdated == 0 ) { throw new BusinessException ("OPERATION_FAILED" , "扣减失败" ); } }
@Query 注解 作用 @Query 注解用于自定义查询语句,支持JPQL和原生SQL。
语法 1 2 3 4 5 6 7 8 9 10 11 @Query("SELECT u FROM User u WHERE u.name = :name") List<User> findByName (@Param("name") String name) ; @Query(value = "SELECT * FROM users WHERE name = ?1", nativeQuery = true) List<User> findByNameNative (String name) ; @Query("SELECT u FROM User u WHERE u.age > :age") Page<User> findByAgeGreaterThan (@Param("age") Integer age, Pageable pageable) ;
项目中的实际应用 1 2 3 4 5 6 7 @Query("SELECT COUNT(o) FROM Order o WHERE o.userId = :userId AND o.status = 'SUCCESS'") long countSuccessfulOrdersByUserId (@Param("userId") Long userId) ;@Query("SELECT CASE WHEN i.stockQuantity >= :quantity THEN true ELSE false END FROM Inventory i WHERE i.productId = :productId") boolean hasEnoughStock (@Param("productId") Long productId, @Param("quantity") Integer quantity) ;
@Transactional 注解 作用 @Transactional 注解用于声明事务边界,确保数据一致性。
语法 1 2 3 4 5 6 7 8 9 10 @Transactional( propagation = Propagation.REQUIRED, // 事务传播行为 isolation = Isolation.READ_COMMITTED, // 事务隔离级别 timeout = 30, // 事务超时时间(秒) rollbackFor = Exception.class, // 回滚异常类型 noRollbackFor = RuntimeException.class // 不回滚异常类型 ) public void businessMethod () { }
事务传播行为详解 事务传播行为定义了当一个事务方法被另一个事务方法调用时,应该如何处理事务。
1 2 3 4 5 6 7 8 9 public enum Propagation { REQUIRED, SUPPORTS, MANDATORY, REQUIRES_NEW, NOT_SUPPORTED, NEVER, NESTED }
1. REQUIRED(默认行为)- 最常用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 @Service public class OrderService { @Autowired private PaymentService paymentService; @Autowired private InventoryService inventoryService; @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest request) { Order order = new Order (); orderRepository.save(order); paymentService.processPayment(request.getPaymentInfo()); inventoryService.deductStock(request.getProductId(), request.getQuantity()); return OrderResponse.success(order); } } @Service public class PaymentService { @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void processPayment (PaymentInfo paymentInfo) { paymentRepository.save(new Payment (paymentInfo)); if (paymentInfo.getAmount().compareTo(BigDecimal.ZERO) <= 0 ) { throw new BusinessException ("INVALID_AMOUNT" , "支付金额无效" ); } } }
2. REQUIRES_NEW - 独立事务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 @Service public class OrderService { @Autowired private AuditService auditService; @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest request) { try { Order order = new Order (); orderRepository.save(order); auditService.logOrderCreation(order.getId(), request.getUserId()); if (request.getAmount().compareTo(new BigDecimal ("10000" )) > 0 ) { throw new BusinessException ("AMOUNT_TOO_LARGE" , "订单金额过大" ); } return OrderResponse.success(order); } catch (Exception e) { throw e; } } } @Service public class AuditService { @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void logOrderCreation (String orderId, Long userId) { AuditLog auditLog = new AuditLog (); auditLog.setOrderId(orderId); auditLog.setUserId(userId); auditLog.setAction("ORDER_CREATED" ); auditLog.setTimestamp(LocalDateTime.now()); auditLogRepository.save(auditLog); } }
3. NESTED - 嵌套事务(保存点机制) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 @Service public class OrderService { @Autowired private PromotionService promotionService; @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest request) { Order order = new Order (); orderRepository.save(order); try { promotionService.applyCoupon(order.getId(), request.getCouponCode()); } catch (CouponException e) { log.warn("优惠券应用失败: {}" , e.getMessage()); } return OrderResponse.success(order); } } @Service public class PromotionService { @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class) public void applyCoupon (String orderId, String couponCode) { Coupon coupon = couponRepository.findByCode(couponCode) .orElseThrow(() -> new CouponException ("优惠券不存在" )); if (coupon.isExpired()) { throw new CouponException ("优惠券已过期" ); } if (coupon.isUsed()) { throw new CouponException ("优惠券已使用" ); } coupon.setUsed(true ); coupon.setUsedOrderId(orderId); couponRepository.save(coupon); } }
4. SUPPORTS - 支持事务但不强制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 @Service public class ReportService { @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) public OrderStatistics generateOrderStatistics (Long userId) { List<Order> orders = orderRepository.findByUserId(userId); return OrderStatistics.builder() .totalOrders(orders.size()) .totalAmount(orders.stream() .map(Order::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::add)) .build(); } } @Service public class OrderService { @Autowired private ReportService reportService; @Transactional(rollbackFor = Exception.class) public OrderResponse createOrderWithStats (OrderRequest request) { Order order = createOrder(request); OrderStatistics stats = reportService.generateOrderStatistics(request.getUserId()); return OrderResponse.success(order, stats); } public OrderStatistics getOrderStats (Long userId) { return reportService.generateOrderStatistics(userId); } }
5. MANDATORY - 强制要求事务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 @Service public class PaymentService { @Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class) public void processRefund (String orderId, BigDecimal amount) { Order order = orderRepository.findById(orderId) .orElseThrow(() -> new BusinessException ("ORDER_NOT_FOUND" , "订单不存在" )); if (!order.canRefund()) { throw new BusinessException ("CANNOT_REFUND" , "订单不能退款" ); } Refund refund = new Refund (); refund.setOrderId(orderId); refund.setAmount(amount); refundRepository.save(refund); order.setStatus(OrderStatus.REFUNDED); orderRepository.save(order); } } @Service public class OrderService { @Autowired private PaymentService paymentService; @Transactional(rollbackFor = Exception.class) public void refundOrder (String orderId) { Order order = orderRepository.findById(orderId).orElseThrow(); paymentService.processRefund(orderId, order.getAmount()); } public void incorrectRefundCall (String orderId) { Order order = orderRepository.findById(orderId).orElseThrow(); paymentService.processRefund(orderId, order.getAmount()); } }
6. NOT_SUPPORTED - 非事务执行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 @Service public class NotificationService { @Transactional(propagation = Propagation.NOT_SUPPORTED) public void sendOrderNotification (String orderId, String userEmail) { try { emailService.sendEmail(userEmail, "订单创建成功" , "您的订单 " + orderId + " 已创建成功" ); smsService.sendSms(getUserPhone(userEmail), "订单创建成功" ); notificationLogRepository.save(new NotificationLog (orderId, "EMAIL_SMS_SENT" )); } catch (Exception e) { log.error("发送通知失败: orderId={}, error={}" , orderId, e.getMessage()); } } } @Service public class OrderService { @Autowired private NotificationService notificationService; @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest request) { Order order = new Order (); orderRepository.save(order); notificationService.sendOrderNotification(order.getId(), request.getUserEmail()); return OrderResponse.success(order); } }
7. NEVER - 禁止事务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 @Service public class CacheService { @Transactional(propagation = Propagation.NEVER) public void updateCache (String key, Object value) { redisTemplate.opsForValue().set(key, value, Duration.ofMinutes(30 )); log.info("缓存更新成功: key={}" , key); } } @Service public class OrderService { @Autowired private CacheService cacheService; @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest request) { Order order = new Order (); orderRepository.save(order); return OrderResponse.success(order); } public void updateOrderCache (Order order) { cacheService.updateCache("order:" + order.getId(), order); } }
8. 实际业务场景综合示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 @Service public class ComplexOrderService { @Autowired private PaymentService paymentService; @Autowired private InventoryService inventoryService; @Autowired private AuditService auditService; @Autowired private NotificationService notificationService; @Autowired private PromotionService promotionService; @Transactional(rollbackFor = Exception.class) public OrderResponse createComplexOrder (OrderRequest request) { auditService.logOrderCreation("ORDER_START" , request.getUserId()); try { Order order = new Order (); order.setUserId(request.getUserId()); order.setProductId(request.getProductId()); order.setQuantity(request.getQuantity()); orderRepository.save(order); paymentService.processPayment(request.getPaymentInfo()); inventoryService.deductStock(request.getProductId(), request.getQuantity()); try { promotionService.applyCoupon(order.getId(), request.getCouponCode()); } catch (CouponException e) { log.warn("优惠券应用失败: {}" , e.getMessage()); } notificationService.sendOrderNotification(order.getId(), request.getUserEmail()); auditService.logOrderCreation("ORDER_SUCCESS" , request.getUserId()); return OrderResponse.success(order); } catch (Exception e) { auditService.logOrderCreation("ORDER_FAILED" , request.getUserId()); throw e; } } }
9. 传播行为选择指南 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
@Transactional 在接口和实现类上的区别 1. 在接口上使用 @Transactional 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public interface OrderService { @Transactional(rollbackFor = Exception.class) OrderResponse createOrder (OrderRequest orderRequest) ; @Transactional(rollbackFor = Exception.class) OrderResponse cancelOrder (String orderId) ; @Transactional(readOnly = true) OrderResponse getOrderById (String orderId) ; } @Service public class OrderServiceImpl implements OrderService { @Override public OrderResponse createOrder (OrderRequest orderRequest) { } @Override public OrderResponse cancelOrder (String orderId) { } @Override public OrderResponse getOrderById (String orderId) { } }
2. 在实现类上使用 @Transactional 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public interface OrderService { OrderResponse createOrder (OrderRequest orderRequest) ; OrderResponse cancelOrder (String orderId) ; OrderResponse getOrderById (String orderId) ; } @Service public class OrderServiceImpl implements OrderService { @Override @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest orderRequest) { } @Override @Transactional(rollbackFor = Exception.class) public OrderResponse cancelOrder (String orderId) { } @Override @Transactional(readOnly = true) public OrderResponse getOrderById (String orderId) { } }
3. 混合使用(实现类覆盖接口配置) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public interface OrderService { @Transactional OrderResponse createOrder (OrderRequest orderRequest) ; @Transactional(readOnly = true) OrderResponse getOrderById (String orderId) ; } @Service public class OrderServiceImpl implements OrderService { @Override @Transactional(rollbackFor = Exception.class, timeout = 30) public OrderResponse createOrder (OrderRequest orderRequest) { } @Override public OrderResponse getOrderById (String orderId) { } }
4. 类级别的事务配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @Transactional(readOnly = true) public interface OrderService { OrderResponse getOrderById (String orderId) ; @Transactional(rollbackFor = Exception.class) OrderResponse createOrder (OrderRequest orderRequest) ; } @Service @Transactional(rollbackFor = Exception.class) public class OrderServiceImpl implements OrderService { @Override public OrderResponse createOrder (OrderRequest orderRequest) { } @Override @Transactional(readOnly = true) public OrderResponse getOrderById (String orderId) { } }
5. 优先级和最佳实践 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public interface OrderService { @Transactional(rollbackFor = Exception.class) OrderResponse createOrder (OrderRequest orderRequest) ; @Transactional(readOnly = true) OrderResponse getOrderById (String orderId) ; } @Service public class OrderServiceImpl implements OrderService { @Override @Transactional( rollbackFor = Exception.class, timeout = 30, // 30秒超时 isolation = Isolation.READ_COMMITTED ) public OrderResponse createOrder (OrderRequest orderRequest) { } @Override public OrderResponse getOrderById (String orderId) { } }
6. 注意事项和陷阱 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 @Service public class OrderServiceImpl implements OrderService { @Transactional private void privateMethod () { } @Override public OrderResponse createOrder (OrderRequest orderRequest) { privateMethod(); } } @Service public class OrderServiceImpl implements OrderService { @Override @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest orderRequest) { return this .internalCreateOrder(orderRequest); } @Transactional(propagation = Propagation.REQUIRES_NEW) public OrderResponse internalCreateOrder (OrderRequest orderRequest) { return null ; } } @Service public class OrderServiceImpl implements OrderService { @Autowired private OrderService self; @Override @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest orderRequest) { return self.internalCreateOrder(orderRequest); } @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public OrderResponse internalCreateOrder (OrderRequest orderRequest) { return null ; } }
项目中的实际应用 1 2 3 4 5 6 7 8 9 10 11 12 13 @Override @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest orderRequest) { } @Override @Transactional(rollbackFor = Exception.class) public OrderResponse cancelOrder (String orderId) { }
@Entity 相关注解 1. @Entity 标识一个类为JPA实体。
1 2 3 4 5 @Entity @Table(name = "orders") public class Order { }
2. @Table 指定数据库表名和约束。
1 2 3 4 5 6 7 8 9 @Table( name = "orders", schema = "public", uniqueConstraints = @UniqueConstraint(columnNames = {"order_id"}), indexes = @Index(name = "idx_user_id", columnList = "user_id") ) public class Order { }
3. @Id 和 @GeneratedValue 标识主键和生成策略。
1 2 3 4 5 6 7 8 9 10 11 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;public enum GenerationType { AUTO, IDENTITY, SEQUENCE, TABLE }
4. @Column 指定列属性。
1 2 3 4 5 6 7 8 9 @Column( name = "order_id", nullable = false, unique = true, length = 50, precision = 10, scale = 2 ) private String orderId;
5. @Enumerated 枚举类型映射。
1 2 3 4 5 6 7 @Enumerated(EnumType.STRING) @Column(name = "status", nullable = false, length = 20) private OrderStatus status;public enum OrderStatus { PENDING, SUCCESS, FAILED, CANCELLED }
6. @Version 乐观锁版本控制。
1 2 @Version private Long version;
7. 生命周期回调注解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Entity public class Order { @PrePersist public void prePersist () { this .createdAt = LocalDateTime.now(); this .updatedAt = LocalDateTime.now(); } @PreUpdate public void preUpdate () { this .updatedAt = LocalDateTime.now(); } @PostLoad public void postLoad () { } }
@Repository 注解 作用 标识数据访问层组件,提供异常转换功能。
语法 1 2 3 4 @Repository public interface UserRepository extends JpaRepository <User, Long> { }
异常转换 1 2 3 4 5 6 7 @Repository public interface UserRepository extends JpaRepository <User, Long> { }
实际应用示例 完整的订单创建流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 @Service public class OrderServiceImpl implements OrderService { @Autowired private UserAccountRepository userAccountRepository; @Autowired private InventoryRepository inventoryRepository; @Autowired private OrderRepository orderRepository; @Override @Transactional(rollbackFor = Exception.class) public OrderResponse createOrder (OrderRequest orderRequest) { try { UserAccount userAccount = userAccountRepository.findByUserIdWithLock(orderRequest.getUserId()) .orElseThrow(() -> new BusinessException ("USER_NOT_FOUND" , "用户账户不存在" )); Inventory inventory = inventoryRepository.findByProductIdWithLock(orderRequest.getProductId()) .orElseThrow(() -> new BusinessException ("PRODUCT_NOT_FOUND" , "产品不存在" )); if (inventory.getStockQuantity() < orderRequest.getQuantity()) { throw new BusinessException ("INSUFFICIENT_STOCK" , "库存不足" ); } BigDecimal totalAmount = inventory.getPrice().multiply(new BigDecimal (orderRequest.getQuantity())); if (userAccount.getBalance().compareTo(totalAmount) < 0 ) { throw new BusinessException ("INSUFFICIENT_BALANCE" , "账户余额不足" ); } int stockUpdated = inventoryRepository.deductStock(orderRequest.getProductId(), orderRequest.getQuantity()); if (stockUpdated == 0 ) { throw new BusinessException ("STOCK_DEDUCTION_FAILED" , "库存扣减失败" ); } int balanceUpdated = userAccountRepository.deductBalance(orderRequest.getUserId(), totalAmount); if (balanceUpdated == 0 ) { throw new BusinessException ("BALANCE_DEDUCTION_FAILED" , "余额扣减失败" ); } Order order = new Order ( generateOrderId(), orderRequest.getUserId(), orderRequest.getProductId(), orderRequest.getQuantity(), inventory.getPrice(), totalAmount, Order.OrderStatus.SUCCESS ); order = orderRepository.save(order); return OrderResponse.success(order, inventory.getProductName(), "订单创建成功" ); } catch (BusinessException e) { Order failedOrder = new Order ( generateOrderId(), orderRequest.getUserId(), orderRequest.getProductId(), orderRequest.getQuantity(), BigDecimal.ZERO, BigDecimal.ZERO, Order.OrderStatus.FAILED ); orderRepository.save(failedOrder); return OrderResponse.failure(generateOrderId(), orderRequest.getUserId(), orderRequest.getProductId(), e.getMessage()); } } }
最佳实践 1. 事务管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Service public class OrderService { @Transactional(rollbackFor = Exception.class) public void createOrder () { } } @Controller public class OrderController { @Transactional public void createOrder () { } }
2. 锁的使用 1 2 3 4 5 6 7 8 9 @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT u FROM User u WHERE u.id = :id") Optional<User> findByIdWithLock (@Param("id") Long id) ; @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT u FROM User u WHERE u.name = :name") List<User> findByName (@Param("name") String name) ;
3. 查询优化 1 2 3 4 5 6 7 @Query("SELECT new com.example.UserDTO(u.id, u.name) FROM User u WHERE u.age > :age") List<UserDTO> findUsersByAge (@Param("age") Integer age) ; @Query("SELECT u FROM User u WHERE u.status = :status") Page<User> findByStatus (@Param("status") String status, Pageable pageable) ;
4. 异常处理 1 2 3 4 5 6 7 8 9 10 11 12 13 @Transactional(rollbackFor = Exception.class) public void businessMethod () { try { } catch (BusinessException e) { throw e; } catch (Exception e) { throw new BusinessException ("SYSTEM_ERROR" , "系统异常" , e); } }
5. 性能考虑 1 2 3 4 5 6 7 8 @Modifying @Query("UPDATE User u SET u.status = :status WHERE u.id IN :ids") int updateUserStatus (@Param("ids") List<Long> ids, @Param("status") String status) ;@Query("SELECT u FROM User u WHERE u.email = :email") Optional<User> findByEmail (@Param("email") String email) ;
总结 Spring Data JPA注解提供了强大的数据访问和事务管理功能:
@Modifying : 用于修改操作,确保数据一致性
@Lock : 用于并发控制,防止数据竞争
@Query : 用于自定义查询,提高查询效率
@Transactional : 用于事务管理,确保ACID特性
@Entity相关注解 : 用于实体映射,定义数据结构
合理使用这些注解可以构建出高性能、高可靠性的数据访问层。