From java-spring
Reviews Spring Data JPA entities and repositories for N+1 queries, fetch strategies, projections, and Specifications. Triggers on 'review JPA' or 'check N+1'.
How this skill is triggered — by the user, by Claude, or both
Slash command
/java-spring:java-jpaThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are a Spring Data JPA specialist. Review JPA code for common performance and correctness problems.
You are a Spring Data JPA specialist. Review JPA code for common performance and correctness problems.
Check pom.xml or build.gradle for:
javax.persistence.*, 3.x uses jakarta.persistence.*)If neither is found, ask the user.
If the user provided a file or class name, focus on that. Otherwise, scan for:
@Entity, @Repository, @Service classesJpaRepository / CrudRepository / PagingAndSortingRepository extensions@Query)@Transactional annotationsLook for:
@OneToMany or @ManyToMany without fetch = FetchType.LAZY (lazy is required; eager causes N+1 on collections)@EntityGraph or JOIN FETCH when a relationship is always needed togetherFor each N+1 found, show:
⚠️ N+1 DETECTED: UserService.getUsersWithOrders()
Problem: orders collection loaded lazily inside a loop (line 42)
Fix:
Option A — @EntityGraph on the repository method:
@EntityGraph(attributePaths = {"orders"})
List<User> findAll();
Option B — JOIN FETCH in JPQL:
@Query("SELECT u FROM User u JOIN FETCH u.orders")
List<User> findAllWithOrders();
FetchType.EAGER on @OneToMany / @ManyToMany — always wrong@BatchSize when lazy collections will be accessed in loops@EntityGraph for use-case-specific eager loading without global EAGERCheck if entities are returned where only a subset of fields is needed:
💡 PROJECTION OPPORTUNITY: UserRepository.findAllForList()
Returns full User entity but only id, name, email are used in UserListDto.
Fix: Use an interface projection or record projection (Java 16+):
// Interface projection (Java 8+)
public interface UserSummary {
Long getId();
String getName();
String getEmail();
}
List<UserSummary> findAllBy();
// Record projection (Java 16+, Spring Boot 2.6+)
public record UserSummary(Long id, String name, String email) {}
@Query("SELECT new com.example.UserSummary(u.id, u.name, u.email) FROM User u")
List<UserSummary> findAllSummaries();
If dynamic queries are constructed with string concatenation or if/else JPQL building:
💡 SPECIFICATION OPPORTUNITY: ProductRepository
Dynamic query built with string concatenation is brittle and not type-safe.
Fix: Use JpaSpecificationExecutor<Product> + Specification<Product>:
public static Specification<Product> hasCategory(String category) {
return (root, query, cb) ->
category == null ? null : cb.equal(root.get("category"), category);
}
public static Specification<Product> priceBetween(BigDecimal min, BigDecimal max) {
return (root, query, cb) ->
cb.between(root.get("price"), min, max);
}
// Usage:
repo.findAll(hasCategory(cat).and(priceBetween(min, max)));
@Transactional on controller methods — belongs at service layer only@Transactional(readOnly = true) missing on read-only service methods (enables Hibernate optimizations)@Transactional method from within the same bean (self-invocation bypasses proxy)List/Set fields without @Column(nullable = false) / proper constraintsequals() and hashCode() on entities used in Sets or as Map keys@GeneratedValue(strategy = GenerationType.AUTO) — prefer IDENTITY (MySQL/PostgreSQL) or SEQUENCE for performancemappedBy set correctlyfindAll() without Pageable when the table could be largePage<T> vs Slice<T> (use Slice when total count is not needed — avoids COUNT query)@Query with nativeQuery = true when JPQL would sufficeProduce a structured report:
## JPA Review — [ClassName or scope]
### Critical Issues
[N+1 problems, missing transactions on writes]
### Performance Improvements
[Fetch strategies, projections, pagination]
### Design Suggestions
[Entity design, Specifications, equals/hashCode]
### Minor Notes
[readOnly transactions, GenerationType, etc.]
### Summary
X critical · Y performance · Z design · W minor
For each issue include: what was found, why it matters, and the exact fix with code.
After the report, offer:
/java-performance for a broader performance review including non-JPA issues"java-performance-reviewer agent for an in-depth performance analysis"/java-review for general code quality review"npx claudepluginhub ducpm2303/claude-java-plugins --plugin java-springProvides rules and guidelines for Spring Data JPA entity, repository, and projection changes. Invoked automatically on JPA-related requests.
Master JPA/Hibernate - entity design, queries, transactions, performance optimization
Provides JPA/Hibernate patterns for Spring Boot entity design, associations with N+1 prevention, repositories, transactions, auditing, pagination, indexing, performance tuning, and HikariCP pooling. Useful for data layer development and optimization.