用途
本技能用于对 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 迁移指南)。若答案依赖版本敏感事实且时间已过,应抽查当前发布说明或工具源码。当当前文档与本文件冲突时,以文档为准。
- 资料未提供安装命令、价格、平台等具体信息。