
Spring Data Jpa
- 213 installs
- 105 repo stars
- Updated July 27, 2026
- amplicode/spring-skills
Spring Data JPA is an agent skill that discovers existing JPA entity conventions and generates new entities that match them.
About
Spring Data JPA is an agent skill that keeps new Hibernate entities consistent with what is already in your Spring Boot codebase. Solo builders use it when adding tables or bounded contexts without introducing a second style of IDs, fetch types, or setter patterns. The workflow deliberately lists domain entities, reads two or three representatives, and scores conventions like SEQUENCE versus IDENTITY, dedicated sequences per table, field-level annotations, and default LAZY associations before writing code. That makes it a strong fit for brownfield SaaS APIs where Amplicode or similar tooling exposes entity inventory. Intermediate complexity assumes you already run Spring Data repositories and want agent-generated entities that pass review on the first pass.
- Ordered substeps 1.1→1.5: list entities, score conventions, then apply ID/sequence/access rules
- Detects ID strategy among SEQUENCE, IDENTITY, and UUID with per-table vs shared sequence generators
- Scores annotation placement, `serialVersionUID`, lazy `@ManyToOne`, and fluent vs void setters from live code
- Uses `list_all_domain_entities` (or equivalent) to read representative entities before generating new ones
Spring Data Jpa by the numbers
- 213 all-time installs (skills.sh)
- Ranked #22 of 89 Java & JVM skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/amplicode/spring-skills --skill spring-data-jpaAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 213 |
|---|---|
| repo stars | ★ 105 |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | amplicode/spring-skills ↗ |
What it does
Add or extend Spring Data JPA entities and repositories that match your repo’s existing ID, sequence, Lombok, and fetch conventions.
Who is it for?
Best when you're on Spring Boot services and extend domain models and want one consistent persistence style.
Skip if: Greenfield projects with zero existing entities to inspect, or non-JVM stacks.
When should I use this skill?
Adding JPA entities or repositories and the codebase already has domain entities to mirror.
What you get
After the skill runs, new entities and repositories follow scored project conventions for ID generation, fetch type, annotations, and setters.
- New entity classes aligned to detected ID and mapping conventions
- Repository interfaces consistent with existing Spring Data patterns
By the numbers
- Convention workflow uses ordered substeps 1.1 through 1.5 without skipping
Files
Preflight: Spring MCP
This skill is part of the Spring Agent Toolkit and is designed to work with the Spring MCP server (provided by the Amplicode IntelliJ plugin). Before doing anything else, check your tool list for any Spring MCP tool — they are exposed under the amplicode MCP server (e.g. get_project_summary, list_module_dependencies, get_entity_details); harnesses that flatten MCP tools into the tool list use the mcp__amplicode__ prefix on the same names.
- If at least one Amplicode tool is available — MCP is connected. Proceed with the skill below.
- If none are available — stop and invoke the `amplicode-install` skill (bundled with the Spring Agent Toolkit). It installs the Amplicode plugin and walks the user through the «Настроить Spring Agent» welcome-screen button + MCP-client restart. After it completes, the MCP tools become available — resume this skill.
- If
amplicode-installis not registered in your skill list, tell the user (in their language): "This skill needs the Amplicode IntelliJ plugin and its MCP server. Install it from https://amplicode.ru/marketplace into IntelliJ IDEA Ultimate/Community or GigaIDE, open any project, click «Настроить Spring Agent» on the Amplicode welcome screen, then restart your MCP client."
---
Working with JPA Entities
When the task involves creating or modifying a JPA entity:
1. If entity conventions have not been detected yet in this conversation — check memory for previously saved conventions first. If found in memory, reuse them. Otherwise read references/entity-conventions.md and follow all substeps there to detect project conventions. 2. Read references/entity-rules-impl.md and follow the rules there when writing or modifying the entity
Reviewing JPA Patterns
When the user asks to review JPA patterns, conventions, or code quality in the project:
1. Detect current conventions by following references/entity-conventions.md (steps 1.1–1.5). 2. Compare the detected conventions against the best practices defined in references/entity-rules-impl.md. For each deviation, output a recommendation in the format:
### JPA Review
**[Convention or pattern name]**
- Current: <what the project does>
- Recommended: <what the best practice says>
- Reason: <why this matters>If no deviations are found — state that the project follows best practices.
---
Working with Transactions
When the task involves adding or modifying transactional behavior:
1. If transaction conventions have not been detected yet in this conversation — check memory for previously saved conventions first. If found in memory, reuse them. Otherwise read references/transaction-conventions.md and follow all substeps there to detect project conventions. 2. Read references/transaction-rules-impl.md and follow the rules there when writing or modifying transactional code.
Detect Entity Conventions
Follow substeps 1.1 → 1.2 → 1.3 → 1.4 → 1.5 in order. Do not skip or reorder them.
---
Step 1.1: Find existing entities
Call list_all_domain_entities to get a list of entities in the project. Pick 2–3 representative ones and read their source files.
---
Step 1.2: Score each convention
For each convention below, determine the answer from the code and assign a confidence score (1–100):
General conventions:
- ID strategy — check existing
@Idfields: is itLongwith@GeneratedValue(strategy = SEQUENCE)(sequence),Longwith@GeneratedValue(strategy = IDENTITY)(identity/autoincrement), orUUIDwith@GeneratedValue(strategy = UUID)(client-generated)? Default: database-generated (Long+SEQUENCE) - Sequence scope — if SEQUENCE is used, check
@SequenceGenerator: is there a dedicated sequence per table (each entity has its owngeneratorname), a shared sequence across all tables (one common generator), or is@SequenceGeneratoromitted entirely (Hibernate default sequence)? Default: dedicated sequence per table - Annotation placement — are
@Column,@Id, etc. on fields or getter methods? Default: on fields - `serialVersionUID` — does any entity declare
private static final long serialVersionUID? Default: not generated - FetchType on @ManyToOne / @OneToOne — check the
fetchattribute. Default:LAZY - Fluent setters — do setters return
thisorvoid? Default:void - Field access modifier — are fields
privateorprotected? Default:private - Naming strategy — does the project rely on JPA Implicit Naming Strategy (names omitted from
@Table/@Column), or are all names explicit? Default: explicit — always name JPA objects explicitly so that no Implicit Naming Strategy affects the code - Table name template — check
@Table(name=...)values: case (lower/upper/as-is), prefix, postfix, underscores, pluralized? Default: lower case, underscore, no prefix/postfix, not pluralized - Column name template — check
@Column(name=...)values: case (lower/upper/as-is), prefix, postfix, underscores? Default: lower case, underscore, no prefix/postfix - Entity class name convention — is the Java class name transformed in any way (prefix/postfix)? Default: as-is, no transformation
- Index/constraint name case — check
@Index(name=...),@UniqueConstraint(name=...). Default:lower
Constants Generation conventions (score separately):
- Constants generated? — does any entity have
public static final Stringconstants for entity/table/column names? Default: no - What is generated — entity name constant, table name constant, column name constants? Default: all three if constants are used
- Where constants are placed — in the same class, or in a separate nested/inner class? Default: same class
Lombok conventions (score separately — only relevant if Lombok is on the classpath):
- Lombok used? — are any Lombok annotations present on entities? Default: yes
- `@Getter` and `@Setter` — is
@Getter/@Setteron class level? Default: yes - `@Builder` — is
@Builderused? Default: no - `@AllArgsConstructor` — is
@AllArgsConstructorused? Default: no - `@NoArgsConstructor` — is
@NoArgsConstructorused? Default: no - `@ToString` — is
@ToStringused? Default: no - `@ToString(onlyExplicitlyIncluded = true)` — is this variant used? Default: no
equals & hashCode conventions (score separately):
- equals/hashCode style — check existing
equals/hashCodeimplementations: is it manual withHibernateProxycheck (proxy-safe pattern), or generated via Lombok@EqualsAndHashCode(onlyExplicitlyIncluded = true)on specific fields (e.g.id)? Default: manual with HibernateProxy. If noequals/hashCodeimplementations are found in the project — confidence is high (90), use the default without asking. - `@EqualsAndHashCode` fields — if Lombok is used, which fields are included via
@EqualsAndHashCode.Include? Default:idonly
toString conventions (score separately):
- toString style — check existing
toString()implementations: is it manual (overriddentoString()method in the class body), or generated via Lombok@ToString? Default: manual. If notoString()implementations are found in the project — confidence is high (90), use the default without asking. - toString fields — if manual, which fields are included? Check that no related entity fields are accessed (would trigger lazy loading). Default: all local (non-relation) fields
- `@ToString(onlyExplicitlyIncluded = true)` — if Lombok
@ToStringis used, isonlyExplicitlyIncluded = trueset with@ToString.Includeon specific fields? Default: no
---
Step 1.3: Collect uncertain conventions
Score confidence only for conventions where the code contains relevant examples but the pattern is ambiguous or inconsistent. If a convention is simply absent from the code (e.g. no @ManyToOne exists yet, no Lombok annotations anywhere) — confidence is high, use the default without asking.
Collect all conventions where confidence < 80. For each, formulate a question with explicit answer options; put the default value first (marked as "Recommended").
---
Step 1.4: Ask developer
If there are any uncertain conventions from step 1.3, ask the developer using AskUserQuestion — combine all questions into a single tool call.
Example call — general uncertain convention + Lombok block:
{
"questions": [
{
"header": "Constraint case",
"question": "What case is used for index and constraint names?",
"multiSelect": false,
"options": [
{ "label": "lower (Recommended)", "description": "e.g. idx_loan_due_date" },
{ "label": "UPPER", "description": "e.g. IDX_LOAN_DUE_DATE" }
]
},
{
"header": "Lombok used?",
"question": "Is Lombok used in entity classes?",
"multiSelect": false,
"options": [
{ "label": "Yes (Recommended)", "description": "Lombok annotations are present on entities" },
{ "label": "No", "description": "No Lombok — explicit getters/setters/constructors only" }
]
},
{
"header": "Lombok features",
"question": "Which Lombok annotations are used on entity classes?",
"multiSelect": true,
"options": [
{ "label": "@Getter and @Setter (Recommended)", "description": "Generate getters and setters for all fields" },
{ "label": "@Builder", "description": "Generate builder pattern" },
{ "label": "@AllArgsConstructor", "description": "Generate constructor with all fields" },
{ "label": "@NoArgsConstructor", "description": "Generate no-args constructor" }
]
}
]
}Note: ask about "Lombok features" only if "Lombok used?" was confirmed as Yes. Ask about "Constants what" and "Constants where" only if "Constants used?" was confirmed as Yes. Ask about "@EqualsAndHashCode fields" only if equals/hashCode style = Lombok. Ask about "toString fields" only if toString style = manual.
Example questions for toString:
{
"questions": [
{
"header": "toString style",
"question": "How is toString() implemented in entity classes?",
"multiSelect": false,
"options": [
{ "label": "Manual (Recommended)", "description": "Overridden toString() method listing local fields only" },
{ "label": "Lombok @ToString", "description": "Generated via @ToString annotation" }
]
},
{
"header": "toString fields",
"question": "Which fields are included in toString()?",
"multiSelect": false,
"options": [
{ "label": "All local fields (Recommended)", "description": "All fields except relations (@ManyToOne, @OneToMany, etc.)" },
{ "label": "Explicit subset", "description": "Only specific fields marked with @ToString.Include or listed manually" }
]
}
]
}Example questions for equals & hashCode:
{
"questions": [
{
"header": "equals/hashCode style",
"question": "How is equals/hashCode implemented in entity classes?",
"multiSelect": false,
"options": [
{ "label": "Manual with HibernateProxy (Recommended)", "description": "Proxy-safe pattern using HibernateProxy check in equals/hashCode" },
{ "label": "Lombok @EqualsAndHashCode", "description": "Generated via @EqualsAndHashCode(onlyExplicitlyIncluded = true) on selected fields" }
]
},
{
"header": "@EqualsAndHashCode fields",
"question": "Which fields are included in @EqualsAndHashCode?",
"multiSelect": true,
"options": [
{ "label": "id (Recommended)", "description": "Only the primary key field" },
{ "label": "business key fields", "description": "Natural key fields (e.g. email, code)" }
]
}
]
}Example questions for Constants Generation:
{
"questions": [
{
"header": "Constants used?",
"question": "Are string constants generated for entity/table/column names?",
"multiSelect": false,
"options": [
{ "label": "No (Recommended)", "description": "No constants — names are inlined directly in annotations" },
{ "label": "Yes", "description": "e.g. public static final String TABLE_NAME = \"loans\"" }
]
},
{
"header": "Constants what",
"question": "Which name constants are generated?",
"multiSelect": true,
"options": [
{ "label": "Entity name", "description": "Constant for the entity class simple name" },
{ "label": "Table name", "description": "Constant for the @Table name value" },
{ "label": "Column names", "description": "Constant per each @Column name value" }
]
},
{
"header": "Constants where",
"question": "Where are name constants placed?",
"multiSelect": false,
"options": [
{ "label": "Same class (Recommended)", "description": "Constants declared directly in the entity class" },
{ "label": "Nested class", "description": "Constants declared in a static nested class inside the entity" },
{ "label": "Separate class", "description": "Constants declared in a dedicated companion class" }
]
}
]
}---
Step 1.5: Summarize resolved conventions
Before writing any code, output a single consolidated list of all conventions from Step 1.2, with each value filled in from what you actually found in the code or what the developer confirmed in Step 1.4. Do not copy the example below — construct your own list based on the real project.
Every convention from Step 1.2 must appear in the list, including Lombok and Constants Generation items. Each value must reflect the actual project state, not the defaults.
Example format (values here are illustrative only — replace with what you discovered):
- Annotation placement: on fields
- serialVersionUID: not generated
- FetchType on @ManyToOne / @OneToOne: LAZY
- Fluent setters: void
- Field access modifier: private
- Naming strategy: explicit
- Table name template: lower case, underscore, no prefix/postfix, not pluralized
- Column name template: lower case, underscore, no prefix/postfix
- Entity class name convention: as-is
- Index/constraint name case: lower
- Constants generated: no
- Lombok used: yes — @Getter, @Setter
- equals/hashCode style: manual with HibernateProxy
- toString style: manual — all local fieldsThis list is your working contract for all code written in this session.
Entity Implementation Rules
Apply these rules when writing or modifying any JPA entity. All rules assume the conventions resolved in Step 1 are already applied.
---
Class — creating a new entity class
- Annotate with
@Entity - If naming strategy = explicit (Step 1.5) — add
@Table(name = "...")with the name derived from the table name template convention - If naming strategy = implicit — add
@Tablewithoutname - If Lombok = yes (Step 1.5) — add Lombok annotations on the class according to resolved Lombok conventions:
- Add
@Getterand/or@Setterif configured - If
@AllArgsConstructoris configured — add it - If
@NoArgsConstructoris configured — add it - If
@Builderis configured — add it;@Builderrequires both@AllArgsConstructorand@NoArgsConstructorto be present (JPA needs the no-args constructor, Builder generates the all-args one) - If Lombok = no — no Lombok annotations; write getters and setters manually
---
Id
Every entity must have an id field — either declared directly or inherited from a parent class. Before adding id to an entity, call get_entity_details to check if the parent already provides it.
If id must be declared directly:
Database-generated (SEQUENCE) — declare private Long id with the following annotations:
- Annotate with
@Id - Annotate with
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "<name>") - If sequence scope = dedicated per table — also annotate with
@SequenceGenerator(name = "<name>")using an entity-specific name (e.g.loan_seq) - If sequence scope = shared — also annotate with
@SequenceGenerator(name = "<shared_name>")using the shared name found in existing entities - If sequence scope = Hibernate default — omit
@SequenceGenerator - If naming strategy = explicit — annotate with
@Column(name = "id", nullable = false) - If naming strategy = implicit — annotate with
@Column(nullable = false)
Database-generated (IDENTITY) — declare private Long id with the following annotations:
- Annotate with
@Id - Annotate with
@GeneratedValue(strategy = GenerationType.IDENTITY) - If naming strategy = explicit — annotate with
@Column(name = "id", nullable = false) - If naming strategy = implicit — annotate with
@Column(nullable = false)
Client-generated — declare private UUID id with the following annotations:
- Annotate with
@Id - Annotate with
@GeneratedValue(strategy = GenerationType.UUID) - If naming strategy = explicit — annotate with
@Column(name = "id", nullable = false) - If naming strategy = implicit — annotate with
@Column(nullable = false)
---
Field Annotation Rules
Every field must have @Column with explicit name:
// CORRECT
@Column(name = "birth_date")
private LocalDate birthDate;
// WRONG — missing explicit column name
private LocalDate birthDate;Validation — use bean validation (Jakarta Validation) for all field constraints.
---
Field Type Rules
BigDecimal
BigDecimal must always be declared with explicit precision and scale in @Column — without them Hibernate uses database defaults which vary across vendors and cause precision loss:
// CORRECT
@Column(name = "price", precision = 10, scale = 2)
private BigDecimal price;
// WRONG — missing precision and scale
@Column(name = "price")
private BigDecimal price;---
Relationship Rules
OneToMany
Prefer bidirectional @OneToMany over unidirectional — unidirectional requires an extra join table or produces inefficient SQL (extra DELETE + INSERT on collection changes). In a bidirectional relationship, the @ManyToOne side owns the FK column:
Use Set<> initialized as LinkedHashSet (preserves insertion order) as the default collection type — in this case the child entity must have correct equals/hashCode (see section below). If List is used instead, equals/hashCode on the child side are not required.
// Parent side
@OneToMany(mappedBy = "owner", fetch = FetchType.LAZY)
@OrderBy("name")
private Set<Pet> pets = new LinkedHashSet<>();
// Child side owns the FK
@ManyToOne
@JoinColumn(name = "owner_id")
private Owner owner;ManyToOne
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "owner_id")
private Owner owner;- No cascade on ManyToOne (reference to existing data)
- Always specify
@JoinColumn(name = "...")explicitly FetchType.LAZYby default — override toEAGERonly when explicitly needed
ManyToMany
@ManyToMany
@JoinTable(
name = "vet_specialties",
joinColumns = @JoinColumn(name = "vet_id"),
inverseJoinColumns = @JoinColumn(name = "specialty_id")
)
private Set<Specialty> specialties;- Always use
Setfor ManyToMany collections — usingListis strongly discouraged because Hibernate deletes and reinserts all rows on every change (the "bag" problem); useListonly as a last resort - Always define
@JoinTablewith explicit table name and both join columns - The inverse side entity must have
equals/hashCode—Setrequires them for correct behavior (see section below)
---
equals & hashCode
Never include relation fields (@ManyToOne, @OneToMany, @ManyToMany, @OneToOne) in equals/hashCode — accessing them triggers lazy loading and causes LazyInitializationException outside a transaction. Only include relation fields if the user explicitly requests it.
If equals/hashCode style = manual (Step 1.5) — implement the proxy-safe pattern that compares effective classes rather than direct instanceof:
If equals/hashCode style = Lombok (Step 1.5):
- Annotate the class with
@EqualsAndHashCode(onlyExplicitlyIncluded = true) - Annotate the
idfield (or the fields resolved in Step 1.5) with@EqualsAndHashCode.Include - Do not add
@EqualsAndHashCode.Includeto any relation fields
Manual pattern — correctly handles uninitialized proxies:
@Override
public final boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
Class<?> objectEffectiveClass = o instanceof HibernateProxy proxy
? proxy.getHibernateLazyInitializer().getPersistentClass() : o.getClass();
Class<?> thisEffectiveClass = this instanceof HibernateProxy proxy
? proxy.getHibernateLazyInitializer().getPersistentClass() : this.getClass();
if (thisEffectiveClass != objectEffectiveClass) return false;
Pet other = (Pet) o;
return getId() != null && Objects.equals(getId(), other.getId());
}
@Override
public final int hashCode() {
return this instanceof HibernateProxy proxy
? proxy.getHibernateLazyInitializer().getPersistentClass().hashCode()
: getClass().hashCode();
}---
toString
Never include relation fields (@ManyToOne, @OneToMany, @ManyToMany, @OneToOne) in toString() — accessing them triggers lazy loading and causes LazyInitializationException outside a transaction. Only include relation fields if the user explicitly requests it.
If toString style = manual (Step 1.5):
- Override
toString()and include only local (non-relation) fields according to the toString fields convention from Step 1.5
If toString style = Lombok (Step 1.5):
- If
@ToString(onlyExplicitlyIncluded = true)is configured — annotate the class with@ToString(onlyExplicitlyIncluded = true)and annotate each included local field with@ToString.Include - Otherwise — annotate the class with
@ToStringand annotate each relation field with@ToString.Excludeto prevent lazy loading
Manual pattern — only local fields:
Related skills
How it compares
Use instead of generic “create JPA entity” prompts when convention detection from the repo matters more than textbook examples.
FAQ
Who is spring-data-jpa for?
backend developers using Spring Boot and Hibernate who add entities without breaking team-wide persistence patterns.
When should I use spring-data-jpa?
Use it in Build → backend when scaffolding repositories, mirroring legacy tables, or expanding a modular monolith after listing existing domain entities.
Is spring-data-jpa safe to install?
Review the Security Audits panel on this page; the skill reads project source and may invoke listing tools—avoid running it on repos with untrusted macros or secrets in entity files.