关于 spring-data-jpa
面向 Spring Data JPA 项目的数据访问模式技能,涵盖仓库、实体关系、查询、分页、审计与事务。适用于构建和优化持久层。
主要功能
- 01仓库接口与派生查询
- 02实体关系及级联配置
- 03自定义查询与分页
- 04审计字段与事务管理
- 05查询性能及 N+1 优化
适用场景
- 01创建 CRUD 仓库和自定义查询
- 02配置实体关系与级联操作
- 03为大型数据集实现分页
- 04排查查询性能和 N+1 问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ giuseppe-trisciuoglio/ developer-kit --skill spring-data-jpa安装后在 Claude Code 中输入/spring-data-jpa确认已加载。
附带文件references/examples.mdreferences/reference.md
详细介绍
Spring Data JPA
概述
提供有关 Spring Data JPA 仓库、实体关系、查询、分页、审计和事务的模式。
适用场景
创建具有 CRUD 操作、实体关系、@Query 注解、分页、审计或 UUID 主键的仓库。
说明
创建仓库接口
实现仓库接口:
-
扩展适当的仓库接口:
@Repository public interface UserRepository extends JpaRepository<User, Long> { // Custom methods defined here } -
对简单条件使用派生查询:
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") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, length = 100) private String email; } -
使用适当的级联类型配置关系:
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) private List<Order> orders = new ArrayList<>();**验证:**在应用于生产数据之前,先用小型数据集测试级联行为。确认删除操作不会意外触发级联。
-
设置数据库审计:
@CreatedDate @Column(nullable = false, updatable = false) private LocalDateTime createdDate;
应用查询模式
- 对简单条件使用派生查询
- 对复杂查询使用
@Query - 单条结果使用 Optional 返回
- 使用 Pageable 进行分页
- 对更新/删除操作应用
@Modifying
管理事务
- 使用
@Transactional(readOnly = true) 标记只读操作 - 为修改操作设置明确的事务边界
- 按需指定回滚条件
验证和优化
1. 验证实体配置:
- 在生产环境部署之前,在事务中测试级联行为
- 验证双向关系能否正确同步
2. 优化查询性能:
- 对针对大型表的查询运行
EXPLAIN ANALYZE - 如果检测到性能问题:添加索引 → 使用 EXPLAIN 验证 → 重复此过程
- 使用
@EntityGraph防止 N+1 查询
3. 验证分页:
- 确保索引列能够支持分页查询
- 使用大型数据集进行测试,以验证游标稳定性
示例
基本 CRUD 仓库
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
// Derived query
List<Product> findByCategory(String category);
// Custom query
@Query("SELECT p FROM Product p WHERE p.price > :minPrice")
List<Product> findExpensiveProducts(@Param("minPrice") BigDecimal minPrice);
}
分页实现
@Service
public class ProductService {
private final ProductRepository repository;
public Page<Product> getProducts(int page, int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("name").ascending());
return repository.findAll(pageable);
}
}
带审计功能的实体
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
@CreatedBy
@Column(nullable = false, updatable = false)
private String createdBy;
}
最佳实践
实体设计
- 仅使用构造器注入(绝不使用字段注入)
- 优先使用带
final修饰符的不可变字段 - DTO 使用 Java record(16+)或
@Value - 始终提供适当的
@Id和@GeneratedValue注解 - 使用明确的
@Table和@Column注解
性能优化
- 使用适当的获取策略(LAZY 与 EAGER)
- 对大型数据集实现分页
- 为频繁查询的字段使用数据库索引
- 考虑使用
@EntityGraph避免 N+1 查询问题
参考文档
有关完整示例、详细模式和高级配置,请参阅:
约束和警告
- 切勿在 REST API 中直接公开 JPA 实体;始终使用 DTO,以避免延迟加载问题。
- 使用
@EntityGraph或查询中的JOIN FETCH避免 N+1 查询问题。 - 谨慎对大型集合使用
CascadeType.REMOVE,因为这可能导致性能问题。 - 不要对集合使用
EAGER获取类型;这可能导致过多的数据库查询。 - 避免长时间运行的事务,因为它们可能导致数据库锁争用。
- 对读取操作使用
@Transactional(readOnly = true)以启用优化。 - 注意一级缓存;同一事务中的实体可能无法反映数据库变更。
- UUID 主键可能导致索引碎片;考虑使用顺序 UUID 或 Long ID。
- 对大型数据集进行分页需要适当的索引,以避免全表扫描。
评论
支持 Markdown