SuperAPI AI 工具集

hibernate-jpa-validator

编程与开发

查看项目

更新于 10-15 10:05

技能介绍

用途

本技能用于对 Hibernate/JPA 代码进行全谱系分析,灵感来自 Vlad Mihalcea 的 Hypersistence Optimizer。在审查任何实体或 JPA 代码时,应运行完整检查清单,而不仅限于用户提问的部分。性能被视为一等公民,而非事后补充。

技能聚焦 ORM 关注点:映射、抓取计划、SQL 生成、事务、schema。它不覆盖 Jakarta Bean Validation 约束(@Valid、@NotNull、@Size、ConstraintValidator、校验分组),这些应交给 Bean Validation 技能或通用 Spring 指导。

核心哲学:先展示生成的 SQL,再解释底层 JDBC 行为,最后给出修复方案。

请求评估

根据用户需求分流:

  • 实体类 → 运行实体映射完整检查清单
  • 慢查询 / N+1 → 抓取策略审查
  • 查询优化 / 投影 → 查询优化
  • 批量插入/更新 → 批处理
  • 缓存问题 → 缓存审查
  • 连接池调优 → 连接池
  • Spring Data JPA 模式 → Spring Data JPA
  • 事务 / 锁 / 传播 → 事务与并发
  • Testcontainers / 仓储测试 → 数据访问层测试
  • Flyway / DDL 校验 / 迁移 → 迁移相关
  • PR/模块的全部内容 → 按顺序运行以上各节

主要能力

实体映射校验(核心,每个实体都运行)

  • 标识符策略:SEQUENCE + @SequenceGenerator(allocationSize=50) 为正确;SEQUENCE 默认 allocationSize=1 需修复优化器;IDENTITY 破坏 JDBC 批处理;TABLE 为悲观锁反模式,永不使用;AUTO 不可预测、依赖数据库,永不使用;UUID.randomUUID() 随机 UUID 会导致索引碎片,优先时间有序。
  • equals/hashCode:这是 Hibernate 中最关键的正确性问题。使用生成 ID 且可变哈希契约、或 IDE 自动生成未审查的 equals/hashCode 都应标记。推荐业务键 / @NaturalId,或使用稳定 hashCode(getClass().hashCode())配合生成 ID。
  • 关联映射:@ManyToOne 始终 fetch = LAZY(EAGER 是默认值,常被遗漏);@OneToMany 始终 mappedBy + 反向端持有外键(单向 @OneToMany 会产生虚假 DELETE+INSERT);@ManyToMany 使用 Set 而非 List(List 触发 bag 语义 → DELETE ALL + 重新 INSERT);@OneToOne 使用 @MapsId 共享主键;所有双向关联添加 addXxx/removeXxx 同步辅助方法。
  • 级联类型:@ManyToOne 上的 CascadeType.ALL 或 REMOVE 是灾难性的;@ManyToMany 上 orphanRemoval = true 永不使用;@OneToMany 到依赖子实体缺失级联是便利性遗漏。
  • 抓取类型:所有关联必须 FetchType.LAZY。@ManyToOne 和 @OneToOne 默认 EAGER,必须覆盖。
  • @DynamicUpdate / @DynamicInsert:实体列多且频繁部分更新时应用。
  • @Immutable 用于参考数据:查找表、参考数据、插入后永不改变的内容。
  • 列定义:非空列缺失 nullable = false、String 字段缺失 @Column(length=...)、唯一业务键缺失 unique = true / @UniqueConstraint、WHERE 子句使用的 FK 列缺失 @Index。
  • Lombok 在实体上的使用:@Data、@EqualsAndHashCode、未排除字段的 @ToString、缺少 @NoArgsConstructor 的 @Builder、缺少 @Builder.Default、@Value 均为问题;@FieldNameConstants 推荐使用。
  • Java Records 与 JPA:不能作为 @Entity / @MappedSuperclass;@Embeddable 仅 Hibernate 6.2+;@IdClass 优秀;@EmbeddedId 仅 Hibernate 6.2+;Spring Data 类投影可用;接口投影不可用;可空列使用 long/int 会导致 NPE,应使用包装类型。
  • Kotlin 数据类与 JPA:data class 作为 @Entity 有问题;需 kotlin-jpa 和 kotlin-allopen 配合;仅 kotlin-jpa 不够;@Id 使用非空 Long 有问题;非空 Kotlin 类型支撑可空列是 NPE 隐患;data class 作为 @Embeddable 可接受;作为 DTO 投影可用;@JvmInline value class 字段有问题;val 属性上的 @Access(AccessType.PROPERTY) 有问题。

N+1 与抓取策略

检测方式:启用 Hibernate 统计(hibernate.generate_statistics=true),或使用 datasource-proxy / p6spy 统计每请求 SQL 数量。

修复策略按优先级:JOIN FETCH、@EntityGraph、@BatchSize、@Fetch(FetchMode.SUBSELECT)。注意 MultipleBagFetchException:不能 JOIN FETCH 两个 List(bag)集合,应改用 Set 或分查询抓取。

查询优化

只读数据使用 DTO 投影(接口或类投影),而非完整实体。分页优先 Keyset 而非 OFFSET。

批处理

配置 hibernate.jdbc.batch_size、order_inserts、order_updates。每 batch_size 次迭代 flush + clear 防止一级缓存 OOM。IDENTITY 生成会静默禁用 JDBC 批处理,这是优先选择 SEQUENCE 的主要原因。

缓存审查

推荐缓存前先问:实体是否跨事务共享?可以多陈旧?只读参考数据用 READ_ONLY;多数读、少更新用 NONSTRICT_READ_WRITE;需要事务正确性用 READ_WRITE 或 TRANSACTIONAL;报表/聚合不缓存。查询缓存的陷阱:结果类型中任何实体更新都会使整个区域失效。

连接池调优

HikariCP 默认大多可用。需显式设置的:maximum-pool-size(经验性调整)、minimum-idle = maximum-pool-size、max-lifetime 小于数据库 wait_timeout / 负载均衡空闲超时、leak-detection-threshold: 2000。

Spring Data JPA 模式

需标记的反模式:findAll()、写路径上的 findById()、带分配 ID 的新实体 save()、@Modifying 缺少 clearAutomatically = true、生成 N+1 的派生查询、@Transactional 内对托管实体 save()、用 countByXxx > 0 做存在性检查、JOIN FETCH + Pageable、从 REST 控制器返回实体、spring.jpa.open-in-view=true。批量更新需 clearAutomatically = true 和 flushAutomatically = true。推荐使用 Hypersistence Utils 的 BaseJpaRepository。

事务与并发

默认强制:spring.jpa.open-in-view=false;读服务方法加 @Transactional(readOnly = true),写加 @Transactional;服务层拥有事务。检查:@Transactional 方法无自调用、每个可变实体加 @Version、悲观锁有显式超时、外部 API 调用在事务外、读写路由需用 LazyConnectionDataSourceProxy 包装。

数据访问层测试

规则:通过 Testcontainers 使用真实数据库,生产代码面向 PostgreSQL/MySQL 时绝不用 H2/HSQLDB;@DataJpaTest 上加 @AutoConfigureTestDatabase(replace = Replace.NONE);使用 em.flush() + em.clear()。

使用方式

技能以检查清单形式组织,按请求类型分流到对应章节。审查实体时运行完整清单,不跳过任何项。输出遵循“展示 SQL → 解释 JDBC 行为 → 给出修复”的结构。

适用场景

  • 审查或编写 Hibernate/JPA 实体与关联映射
  • 排查慢查询、N+1 问题
  • 优化查询与投影
  • 批量插入/更新
  • 缓存策略选择
  • 连接池调优
  • Spring Data JPA 代码审查
  • 事务、锁、传播行为审查
  • 数据访问层测试
  • Flyway / DDL 校验 / 迁移

限制

  • 不覆盖 Jakarta Bean Validation 约束(@Valid、@NotNull、@Size、ConstraintValidator、校验分组),应交给 Bean Validation 技能或通用 Spring 指导。
  • 资料中标注了时效性说明:最后验证时间为 2026-07(Hibernate ORM 7.x / Spring Boot 4.1 时代;6→7 说明对照官方 7.0 迁移指南)。若答案依赖版本敏感事实且时间已过,应抽查当前发布说明或工具源码。当当前文档与本文件冲突时,以文档为准。
  • 资料未提供安装命令、价格、平台等具体信息。