$npx -y skills add a-pavithraa/springboot-skills-marketplace --skill spring-data-jpaDesigns and implements Spring Data JPA repositories, projections, query patterns, custom repositories, CQRS read models, entity relationships, and persistence performance fixes for Java 25 and Spring Boot 4 projects. Use when the task needs repository-boundary decisions or concre
| 1 | # Spring Data JPA Implementation |
| 2 | |
| 3 | ## Purpose |
| 4 | |
| 5 | Use this skill when the task is specifically about persistence design or implementation in a Spring Boot codebase. This skill adds value through aggregate-root guidance, query-pattern selection, CQRS read-model decisions, and the bundled repository and relationship templates. |
| 6 | |
| 7 | ## Critical rules |
| 8 | |
| 9 | - Never create repositories for every entity. Create repositories only for aggregate roots. |
| 10 | - Never rely on long derived query method names when the query has become non-trivial. |
| 11 | - Never use `save()` blindly when entity state transitions matter; understand persist versus merge behavior. |
| 12 | - Prefer projections or dedicated query services for read-heavy paths. |
| 13 | - Keep transaction boundaries in the service layer unless the existing architecture intentionally does otherwise. |
| 14 | |
| 15 | ## Workflow |
| 16 | |
| 17 | ### Step 1: Identify the persistence problem |
| 18 | |
| 19 | Collect the minimum context first: |
| 20 | |
| 21 | 1. Is the type an aggregate root or an internal entity? |
| 22 | 2. Is the task primarily read-side, write-side, or both? |
| 23 | 3. Is the query simple lookup, filtered search, aggregation, projection, or dynamic criteria? |
| 24 | 4. Is the path performance-sensitive? |
| 25 | 5. Are there module-boundary or loose-coupling constraints that affect relationship modeling? |
| 26 | |
| 27 | ### Step 2: Choose the implementation pattern |
| 28 | |
| 29 | Use this table to decide what to load next. |
| 30 | |
| 31 | | Pattern | Use when | Read | |
| 32 | |---------|----------|------| |
| 33 | | Simple repository | Basic CRUD and 1-2 simple lookups | Existing code or none | |
| 34 | | `@Query` repository | Multiple filters, joins, sorting, readable JPQL | `references/query-patterns.md` | |
| 35 | | DTO projection | Read-only and performance-critical responses | `references/dto-projections.md` | |
| 36 | | Custom repository | Criteria API, bulk operations, EntityManager logic | `references/custom-repositories.md` | |
| 37 | | CQRS query service | Separate read and write models, reporting, specialized read paths | `references/cqrs-query-service.md` | |
| 38 | |
| 39 | Use this decision guide: |
| 40 | |
| 41 | | Need | Simple | `@Query` | DTO | Custom | CQRS | |
| 42 | |------|--------|----------|-----|--------|------| |
| 43 | | Basic CRUD | Yes | Yes | No | Yes | Yes | |
| 44 | | Custom filters | No | Yes | Yes | Yes | Yes | |
| 45 | | Best read performance | No | Sometimes | Yes | Sometimes | Yes | |
| 46 | | Complex dynamic logic | No | No | No | Yes | Yes | |
| 47 | | Clear read/write split | No | No | Sometimes | Sometimes | Yes | |
| 48 | |
| 49 | ### Step 3: Load the matching reference |
| 50 | |
| 51 | Load only the references needed for the current task: |
| 52 | |
| 53 | - `references/query-patterns.md` |
| 54 | - `references/dto-projections.md` |
| 55 | - `references/custom-repositories.md` |
| 56 | - `references/cqrs-query-service.md` |
| 57 | - `references/relationships.md` |
| 58 | - `references/performance-guide.md` |
| 59 | |
| 60 | ### Step 4: Apply the matching asset |
| 61 | |
| 62 | Use the bundled templates in `assets/` instead of rebuilding the pattern from scratch: |
| 63 | |
| 64 | - `assets/query-repository.java` |
| 65 | - `assets/dto-projection.java` |
| 66 | - `assets/custom-repository.java` |
| 67 | - `assets/query-service.java` |
| 68 | - `assets/relationship-patterns.java` |
| 69 | |
| 70 | ### Step 5: Validate relationships and transaction boundaries |
| 71 | |
| 72 | Before finalizing the change, check: |
| 73 | |
| 74 | - repository exists only at the aggregate-root boundary |
| 75 | - lazy-loading behavior is intentional |
| 76 | - pagination or projections are used where row counts can grow |
| 77 | - `@ManyToMany` has not been introduced when a join entity is more appropriate |
| 78 | - read services use `@Transactional(readOnly = true)` where appropriate |
| 79 | - write operations stay in service-layer transactions |
| 80 | |
| 81 | ### Step 6: Validate performance-sensitive paths |
| 82 | |
| 83 | Read `references/performance-guide.md` when the task includes: |
| 84 | |
| 85 | - N+1 risks |
| 86 | - fetch-plan problems |
| 87 | - unbounded queries |
| 88 | - batch operations |
| 89 | - heavy read views that should use projections |
| 90 | |
| 91 | ## High-value patterns to prefer |
| 92 | |
| 93 | ### Repository boundaries |
| 94 | |
| 95 | - Aggregate roots get repositories. |
| 96 | - Internal child entities usually do not. |
| 97 | |
| 98 | ### Query style |
| 99 | |
| 100 | - Use derived query methods for simple lookups. |
| 101 | - Use `@Query` for joins, readable text blocks, or multiple filters. |
| 102 | - Use DTO projections when the response does not need entities. |
| 103 | - Use a CQRS query service when the read model differs from the write model. |
| 104 | |
| 105 | ### Relationships |
| 106 | |
| 107 | - Prefer `@ManyToOne` over `@OneToMany` when possible. |
| 108 | - Use IDs instead of entity references when loose coupling is more important than navigation. |
| 109 | - Treat `@ManyToMany` as a warning sign; prefer an explicit join entity. |
| 110 | |
| 111 | ## Output format |
| 112 | |
| 113 | When proposing or implementing a persistence change, return: |
| 114 | |
| 115 | ```markdown |
| 116 | ## Recommended pattern |
| 117 | - Pattern: |
| 118 | - Why: |
| 119 | |
| 120 | ## Files to change |
| 121 | - `path/to/file` |
| 122 | |
| 123 | ## References used |
| 124 | - `references/...` |
| 125 | |
| 126 | ## Risks to verify |
| 127 | - .. |