Install any skill in seconds. Free to start, no credit card required.
Get Started Free →JPA/Hibernate patterns for entity design, relationships, query optimization, transactions, auditing, indexing, pagination, and pooling in Spring Boot.
.claude/skills/affaan-m-jpa-patterns/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 0% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 34% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 63% | 0% |
| case-01 | ✓→✓ | = Same ✓ | -19% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 33% | 0% |
用于 Spring Boot 中的数据建模、存储库和性能调优。
java@Entity @Table(name = "markets", indexes = { @Index(name = "idx_markets_slug", columnList = "slug", unique = true) }) @EntityListeners(AuditingEntityListener.class) public class MarketEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, length = 200) private String name; @Column(nullable = false, unique = true, length = 120) private String slug; @Enumerated(EnumType.STRING) private MarketStatus status = MarketStatus.ACTIVE; @CreatedDate private Instant createdAt; @LastModifiedDate private Instant updatedAt; }
启用审计:
java@Configuration @EnableJpaAuditing class JpaConfig {}
java@OneToMany(mappedBy = "market", cascade = CascadeType.ALL, orphanRemoval = true) private List<PositionEntity> positions = new ArrayList<>();
JOIN FETCHEAGER;对于读取路径使用 DTO 投影java@Query("select m from MarketEntity m left join fetch m.positions where m.id = :id") Optional<MarketEntity> findWithPositions(@Param("id") Long id);
javapublic interface MarketRepository extends JpaRepository<MarketEntity, Long> { Optional<MarketEntity> findBySlug(String slug); @Query("select m from MarketEntity m where m.status = :status") Page<MarketEntity> findByStatus(@Param("status") MarketStatus status, Pageable pageable); }
javapublic interface MarketSummary { Long getId(); String getName(); MarketStatus getStatus(); } Page<MarketSummary> findAllBy(Pageable pageable);
@Transactional 注解服务方法@Transactional(readOnly = true) 以进行优化java@Transactional public Market updateStatus(Long id, MarketStatus status) { MarketEntity entity = repo.findById(id) .orElseThrow(() -> new EntityNotFoundException("Market")); entity.setStatus(status); return Market.from(entity); }
javaPageRequest page = PageRequest.of(pageNumber, pageSize, Sort.by("createdAt").descending()); Page<MarketEntity> markets = repo.findByStatus(MarketStatus.ACTIVE, page);
对于类似游标的分页,在 JPQL 中包含 id > :lastId 并配合排序。
status、slug、外键)status, created_at)select *;仅投影需要的列saveAll 和 hibernate.jdbc.batch_size 进行批量写入推荐属性:
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.validation-timeout=5000对于 PostgreSQL LOB 处理,添加:
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true@DataJpaTest 来镜像生产环境logging.level.org.hibernate.SQL=DEBUG 和 logging.level.org.hibernate.orm.jdbc.bind=TRACE 以查看参数值请记住:保持实体精简,查询有针对性,事务简短。通过获取策略和投影来预防 N+1 问题,并根据读写路径建立索引。
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-02 | fail→pass | 12,813 | 7,301 | -43% | 1 | 1 | 0% | 2,656 | 2,666 | +0% | 0 | 0 | — |
case-01 | pass→pass | 21,589 | 12,476 | -42% | 1 | 1 | 0% | 4,601 | 3,738 | -19% | 0 | 0 | — |
case-03 | pass→pass | 12,726 | 12,980 | +2% | 1 | 1 | 0% | 3,077 | 4,081 | +33% | 0 | 0 | — |
case-04 | pass→pass | 15,692 | 12,248 | -22% | 1 | 1 | 0% | 3,467 | 3,787 | +9% | 0 | 0 | — |
case-05 | pass→pass | 11,144 | 12,821 | +15% | 1 | 1 | 0% | 2,583 | 3,864 | +50% | 0 | 0 | — |
case-06 | pass→pass | 7,363 | 4,918 | -33% | 1 | 1 | 0% | 1,566 | 2,223 | +42% | 0 | 0 | — |
case-07 | pass→pass | 10,292 | 8,654 | -16% | 1 | 1 | 0% | 1,923 | 2,771 | +44% | 0 | 0 | — |
case-08 | pass→pass | 9,782 | 6,955 | -29% | 1 | 1 | 0% | 2,015 | 2,510 | +25% | 0 | 0 | — |
case-09 | pass→pass | 9,528 | 10,606 | +11% | 1 | 1 | 0% | 1,817 | 3,107 | +71% | 0 | 0 | — |
case-10 | fail→pass | 13,396 | 12,186 | -9% | 1 | 1 | 0% | 2,656 | 3,562 | +34% | 0 | 0 | — |
case-11 | fail→fail | 11,729 | 11,242 | -4% | 1 | 1 | 0% | 2,354 | 3,361 | +43% | 0 | 0 | — |
case-12 | pass→pass | 6,293 | 5,347 | -15% | 1 | 1 | 0% | 1,120 | 2,075 | +85% | 0 | 0 | — |
case-13 | pass→pass | 5,374 | 2,970 | -45% | 1 | 1 | 0% | 1,159 | 1,733 | +50% | 0 | 0 | — |
case-14 | pass→pass | 14,323 | 10,933 | -24% | 1 | 1 | 0% | 2,458 | 3,170 | +29% | 0 | 0 | — |
case-15 | pass→pass | 11,169 | 4,723 | -58% | 1 | 1 | 0% | 2,241 | 2,158 | -4% | 0 | 0 | — |
case-16 | pass→pass | 9,491 | 5,116 | -46% | 1 | 1 | 0% | 2,003 | 2,286 | +14% | 0 | 0 | — |
case-17 | pass→pass | 3,325 | 2,112 | -36% | 1 | 1 | 0% | 648 | 1,559 | +141% | 0 | 0 | — |
case-18 | fail→pass | 14,318 | 13,242 | -8% | 1 | 1 | 0% | 2,321 | 3,788 | +63% | 0 | 0 | — |
case-19 | pass→pass | 12,598 | 14,875 | +18% | 1 | 1 | 0% | 2,544 | 3,781 | +49% | 0 | 0 | — |
case-20 | pass→pass | 11,440 | 11,599 | +1% | 1 | 1 | 0% | 2,294 | 3,277 | +43% | 0 | 0 | — |
case-21 | pass→pass | 8,068 | 4,111 | -49% | 1 | 1 | 0% | 1,725 | 1,986 | +15% | 0 | 0 | — |
case-22 | pass→pass | 4,787 | 2,680 | -44% | 1 | 1 | 0% | 984 | 1,737 | +77% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +14 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.