Skip to content
Back to skills

Java Jpa

ASecurity

Reviews Spring Data JPA for N+1 queries, fetch strategies, projections, and Specifications. Use when user asks to "review JPA", "check for N+1", "JPA performance", "review my entities", "check fetch strategy", or "review my repositories".

  • 16 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 26, 2026
databasesgojavasqlspringapiperformance

Works with

  • api

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add ducpm2303/claude-java-plugins --skill java-jpa --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Java Jpa?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Java Jpa
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ducpm2303-java-jpa/badge)](https://www.skillsdirectory.com/skills/ducpm2303-java-jpa)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
description: Reviews Spring Data JPA for N+1 queries, fetch strategies, projections, and Specifications. Use when user asks to "review JPA", "check for N+1", "JPA performance", "review my entities", "check fetch strategy", or "review my repositories".
argument-hint: "[file or class to review, optional]"
---

# /java-jpa — Spring Data JPA Deep Review

You are a Spring Data JPA specialist. Review JPA code for common performance and correctness problems.

## Step 1 — Detect Java and Spring Boot version

Check `pom.xml` or `build.gradle` for:
- Java version (affects stream/record usage)
- Spring Boot version (2.x uses `javax.persistence.*`, 3.x uses `jakarta.persistence.*`)

If neither is found, ask the user.

## Step 2 — Identify scope

If the user provided a file or class name, focus on that. Otherwise, scan for:
- `@Entity`, `@Repository`, `@Service` classes
- `JpaRepository` / `CrudRepository` / `PagingAndSortingRepository` extensions
- JPQL and native queries (`@Query`)
- `@Transactional` annotations

## Step 3 — Review for these issues

### N+1 Query Detection (HIGH PRIORITY)
Look for:
- `@OneToMany` or `@ManyToMany` without `fetch = FetchType.LAZY` (lazy is required; eager causes N+1 on collections)
- Loops that call a repository method or access a lazy collection on each iteration
- Missing `@EntityGraph` or JOIN FETCH when a relationship is always needed together

For 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();
```

### Fetch Strategy Review
- Flag `FetchType.EAGER` on `@OneToMany` / `@ManyToMany` — always wrong
- Flag missing `@BatchSize` when lazy collections will be accessed in loops
- Suggest `@EntityGraph` for use-case-specific eager loading without global EAGER

### Projection Usage
Check 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();
```

### Specification / Criteria API
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)));
```

### Transaction Boundaries
- Flag `@Transactional` on controller methods — belongs at service layer only
- Flag `@Transactional(readOnly = true)` missing on read-only service methods (enables Hibernate optimizations)
- Flag calling a `@Transactional` method from within the same bean (self-invocation bypasses proxy)
- Flag long transactions that include external HTTP calls or file I/O

### Entity Design
- Flag mutable `List`/`Set` fields without `@Column(nullable = false)` / proper constraints
- Flag missing `equals()` and `hashCode()` on entities used in Sets or as Map keys
- Flag `@GeneratedValue(strategy = GenerationType.AUTO)` — prefer `IDENTITY` (MySQL/PostgreSQL) or `SEQUENCE` for performance
- Flag bidirectional relationships without the owning side's `mappedBy` set correctly

### Pagination
- Flag `findAll()` without `Pageable` when the table could be large
- Suggest `Page<T>` vs `Slice<T>` (use Slice when total count is not needed — avoids COUNT query)

### Native Queries
- Flag native `@Query` with `nativeQuery = true` when JPQL would suffice
- Flag string-interpolated table/column names in native queries (SQL injection risk)

## Step 4 — Output

Produce 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.

## Step 5 — Next Steps

After the report, offer:
- *"Run `/java-performance` for a broader performance review including non-JPA issues"*
- *"Use the `java-performance-reviewer` agent for an in-depth performance analysis"*
- *"Run `/java-review` for general code quality review"*

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.