Repository 封装数据访问逻辑,让上层无需关心数据库细节
@Service
public class OrderService {
@Autowired
private JdbcTemplate jdbcTemplate; // 直接依赖底层 JDBC
public List<Order> getUserOrders(Long userId) {
// ❌ 问题1:SQL 硬编码在 Service 里
// ❌ 问题2:更换数据库需要改业务代码
// ❌ 问题3:无法单元测试,必须连真实数据库
String sql = "SELECT * FROM orders WHERE user_id = ? AND deleted = 0";
return jdbcTemplate.query(sql, (rs, rowNum) -> {
Order order = new Order();
order.setId(rs.getLong("id"));
order.setUserId(rs.getLong("user_id"));
order.setTotalAmount(rs.getBigDecimal("total_amount"));
// ... 更多字段映射
return order;
}, userId);
}
public void updateOrderStatus(Long orderId, OrderStatus status) {
// ❌ 问题4:到处重复 SQL 片段
String sql = "UPDATE orders SET status = ?, updated_at = NOW() WHERE id = ?";
jdbcTemplate.update(sql, status.name(), orderId);
}
}
// ========== 1. 实体定义(Domain) ==========
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "user_id", nullable = false)
private Long userId;
@Column(name = "total_amount")
private BigDecimal totalAmount;
@Enumerated(EnumType.STRING)
private OrderStatus status;
@Column(name = "deleted")
private Boolean deleted = false;
// getters and setters...
}
// ========== 2. Repository 接口定义 ==========
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
// ✅ Spring Data 自动生成查询 - 简单查询
List<Order> findByUserIdAndDeletedFalse(Long userId);
// ✅ 自定义 JPQL 查询 - 复杂统计
@Query("""
SELECT new com.example.OrderStatistics(
o.userId,
COUNT(o),
SUM(o.totalAmount),
MAX(o.createdAt)
)
FROM Order o
WHERE o.createdAt BETWEEN :startDate AND :endDate
AND o.deleted = false
GROUP BY o.userId
HAVING COUNT(o) >= :minOrderCount
ORDER BY SUM(o.totalAmount) DESC
""")
List<OrderStatistics> findUserOrderStatistics(
@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate,
@Param("minOrderCount") Long minOrderCount,
Pageable pageable
);
// ✅ 批量更新 - 修改状态
@Modifying
@Query("UPDATE Order o SET o.status = :newStatus, " +
"o.updatedAt = CURRENT_TIMESTAMP WHERE o.id IN :ids")
int batchUpdateStatus(
@Param("ids") List<Long> orderIds,
@Param("newStatus") OrderStatus newStatus
);
}
// ========== 3. Service 层(纯业务逻辑) ==========
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository; // ✅ 依赖接口,不依赖具体实现
@Autowired
private UserRepository userRepository;
// ✅ 业务方法清晰简洁,不关心数据怎么存
public List<OrderDTO> getUserOrders(Long userId) {
// 可以在这里加业务校验
User user = userRepository.findById(userId)
.orElseThrow(() -> new UserNotFoundException(userId));
// 直接调用 Repository,SQL 藏在后面
List<Order> orders = orderRepository.findByUserIdAndDeletedFalse(userId);
// 转换为 DTO 返回
return orders.stream()
.map(OrderDTO::from)
.collect(Collectors.toList());
}
}