其他
在 Spring Data JPA 项目中实现持久层:仓库…
适用于需要创建 Spring Data JPA 仓库、配置实体关系与审计、编写派生/自定义查询、设置分页与事务,并优化 N+1、索引和分页性能的 Java 持久层开发。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 39/100 ×0.15
适用场景
在 Spring Data JPA 项目特定
解决思路
- 创建仓库接口:定义 @Repository public interface XRepository extends JpaRepository<Entity, ID>,并在接口中声明自定义方法。
- 对简单条件使用派生查询,例如 Optional<User> findByEmail(String email); List<User> findByStatusOrderByCreatedDateDesc(String status)。
- 对复杂查询使用 @Query,例如 @Query("SELECT u FROM User u WHERE u.status = :status") List<User> findActiveUsers(@Param("status") String status)。
- 定义实体时使用 @Entity、@Table(name = "users")、@Id、@GeneratedValue(strategy = GenerationType.IDENTITY)、@Column(nullable = false, length = 100) 等注解。
- 配置实体关系时使用合适的 cascade 类型,例如 @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) private List<Order> orders = new ArrayList<>();。
- 在将 cascade 应用于生产数据前,用小数据集测试 cascade 行为,并验证删除操作不会意外级联。
- 设置数据库审计:在实体上使用 @EntityListeners(AuditingEntityListener.class),字段使用 @CreatedDate、@LastModifiedDate、@CreatedBy、@Column(nullable = false, updatable = false) 等。
- 应用查询模式:简单条件使用派生查询。
- 应用查询模式:复杂查询使用 @Query。
- 应用查询模式:单结果返回 Optional<T>。
- 应用查询模式:分页使用 Pageable。
- 应用查询模式:更新/删除操作使用 @Modifying。
- 管理事务:只读操作标记 @Transactional(readOnly = true)。
- 管理事务:修改操作使用显式事务边界。
- 管理事务:需要时指定回滚条件。
- 验证实体配置:生产部署前在事务中测试 cascade 行为。
- 验证实体配置:验证双向关系能正确同步。
- 优化查询性能:对大表查询运行 EXPLAIN ANALYZE。
- 优化查询性能:如果检测到性能问题,按“添加索引 → 用 EXPLAIN 验证 → 重复”迭代。
- 优化查询性能:使用 @EntityGraph 防止 N+1 查询。
- 验证分页:确保索引列支持分页查询。
- 验证分页:用大数据集测试分页,验证 cursor 稳定性。
- 实体设计:仅使用构造器注入,绝不使用字段注入。
- 实体设计:优先使用 final 修饰的不可变字段。
- 实体设计:DTO 使用 Java records(16+)或 @Value。
- 实体设计:总是提供合适的 @Id 和 @GeneratedValue 注解。
- 实体设计:使用显式 @Table 和 @Column 注解。
- 性能优化:使用合适的 fetch 策略(LAZY vs EAGER)。
- 性能优化:为大数据集实现分页。
- 性能优化:对频繁查询字段使用数据库索引。
- 性能优化:考虑使用 @EntityGraph 避免 N+1 查询问题。
- 实现基本 CRUD 仓库,例如 ProductRepository extends JpaRepository<Product, Long>,包含 List<Product> findByCategory(String category); 和 @Query("SELECT p FROM Product p WHERE p.price > :minPrice") List<Product> findExpensiveProducts(@Param("minPrice") BigDecimal minPrice)。
- 实现分页:在 service 中使用 PageRequest.of(page, size, Sort.by("name").ascending()),调用 repository.findAll(pageable) 返回 Page<Product>。
- 实现审计实体:在实体上使用 @EntityListeners(AuditingEntityListener.class),并用 @CreatedDate、@LastModifiedDate、@CreatedBy 标注字段。
- 查阅 references/examples.md 获取常见场景的完整代码示例。
- 查阅 references/reference.md 获取详细模式和高级配置。
- 使用 DTO,避免将 JPA 实体直接暴露在 REST API 中,以防止懒加载问题。
- 使用 @EntityGraph 或 JOIN FETCH 避免 N+1 查询问题。
- 对集合不要使用 EAGER fetch type,以避免过多数据库查询。
- 对大集合慎用 CascadeType.REMOVE,避免性能问题。
- 避免长事务,减少数据库锁竞争。
- 注意一级缓存:同一事务内实体可能不反映数据库变化。
- UUID 主键可能造成索引碎片时,考虑使用 sequential UUIDs 或 Long ID。
- 大表分页必须正确建立索引,以避免全表扫描。
适用边界 · 注意事项
- 不要将 JPA 实体直接暴露在 REST API 中;应使用 DTO,否则可能触发懒加载问题。
- 不要对集合使用 EAGER fetch type,也不要在大集合上随意使用 CascadeType.REMOVE,以免过多查询或性能问题。
- 避免长事务、无索引的大表分页、以及无规划的 UUID 主键,否则可能出现锁竞争、全表扫描或索引碎片。