kotlin-backend-jpa-entity-mapping
Skill1.1k starsChanged 16 days agoApache-2.0View on GitHub
Model Kotlin persistence code correctly for Spring Data JPA and Hibernate. Covers entity design, identity and equality, uniqueness constraints, relationships, fetch plans, and common ORM (Object-Relational Mapping) traps specific to Kotlin. Use when creating or reviewing JPA (Java Persistence API) entities, diagnosing N+1 or LazyInitializationException, placing indexes and uniqueness rules, or preventing Kotlin-specific bugs such as data class entities and broken equals/hashCode.
3 other projects use a version of this, 3 of them edited; 1 new project in the last 4 weeks, against 0 the 4 before.
Adopted by
Surging: 1 new project took it in the last 4 weeks, none the 4 weeks before.thin data
Most recently taken up by
- TeddyAlbina/skillsedited, first seen Nov 1, 2026
- torad-labs/agent-driven-architectureedited, first seen Oct 13, 2026
- JetBrains/skillsedited, first seen Apr 28, 2026
Who's talking about Kotlin/kotlin-agent-skills
- @pamelaahill.bsky.social“The @kotlinlang.org team has been working on some skills. There is one for migrating your project to AGP 9, …”Bluesky · Mar 18, 2026 · 15 likes
- @kotlinweekly.bsky.social“Kotlin Agent Skills: github.com/Kotlin/kotli... #kotlin”Bluesky · May 18, 2026 · 8 likes
- @kotlinlang.org“🤖 Kotlin agent skills are now available on GitHub! Explore AI-assisted skills for converting Java to …”Bluesky · May 19, 2026 · 5 likes
- premex-ab/gross“Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.1”GitHub · Jul 3, 2026 · 1 reactions
- premex-ab/gross“Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.0”GitHub · Jun 10, 2026 · 1 reactions
The biggest 5 of 50 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 50
Talked about on GitHub, Bluesky and Hacker News (50 times).
On GitHub · 46
- Jul 3, 2026Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.1 — premex-ab/gross1 reaction
- Jun 10, 2026Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.0 — premex-ab/gross1 reaction · 1 comment
- Nov 11, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Nov 7, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Nov 2, 2026Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.2 in the kotlin-and-compose group across 1 directory — altaraneu/watchwallet0 reactions
41 more on GitHub
- Nov 1, 2026codex-plugins.github.kotlin.kotlin-agent-skills: init at 0-unstable-2026-10-30 — sudosubin/agents.nix0 reactions
- Nov 1, 2026codex-marketplaces.github.kotlin.kotlin-agent-skills: init at 0-unstable-2026-10-30 — sudosubin/agents.nix0 reactions
- Oct 30, 2026claude-code-plugins.github.kotlin.kotlin-agent-skills: 0-unstable-2026-03-24 → 0-unstable-2026-10-30 — sudosubin/agents.nix0 reactions
- Oct 30, 2026claude-code-marketplaces.github.kotlin.kotlin-agent-skills: 0-unstable-2026-09-11 → 0-unstable-2026-10-30 — sudosubin/agents.nix0 reactions
- Oct 29, 2026claude-code-plugins.github.kotlin.kotlin-agent-skills: 0-unstable-2026-09-11 → 0-unstable-2026-03-24 — sudosubin/agents.nix0 reactions
- Oct 28, 2026claude-code-plugins.github.kotlin.kotlin-agent-skills: init at 0-unstable-2026-09-11 — sudosubin/agents.nix0 reactions
- Oct 28, 2026claude-code-marketplaces.github.kotlin.kotlin-agent-skills: init at 0-unstable-2026-09-11 — sudosubin/agents.nix0 reactions
- Oct 21, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions · 1 comment
- Oct 11, 2026Build(deps): Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.2 — krishnasinghrao/cloudstream-macos0 reactions
- Oct 10, 2026Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.3.8 to 0.5.2 — HKmario852/monologue0 reactions
- Oct 7, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions · 1 comment
- Oct 3, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions · 1 comment
- Sep 30, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions · 1 comment
- Sep 29, 2026agent-skills.github.kotlin.kotlin-agent-skills: init at 0-unstable-2026-09-11 — sudosubin/agents.nix0 reactions
- Sep 24, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions · 1 comment
- Sep 23, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions · 1 comment
- Sep 23, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions · 1 comment
- Sep 19, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions · 1 comment
- Sep 19, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions · 1 comment
- Sep 9, 2026Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.2 in /ragedroid — eordano/ragewarden0 reactions
- Sep 7, 2026chore(deps): Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.2 — caucy2026/KemiMail0 reactions · 1 comment
- Sep 7, 2026chore(deps): bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.2 — VictorSkurchik/tablet-demo0 reactions
- Aug 25, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Aug 21, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Aug 18, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Aug 14, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Aug 14, 2026chore(deps): bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.1 — motyabc/email0 reactions · 1 comment
- Aug 11, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Aug 7, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Aug 4, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Jul 31, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Jul 31, 2026[bot] Generate Manifests — sator-imaging/suggest-skills0 reactions
- Jul 30, 2026chore(deps): bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.1 — slowwylx/DVote0 reactions
- Jul 16, 2026build(deps): bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.1 — fuchi-no-dokuneko/ShareGuard0 reactions
- Jun 30, 2026chore(deps): bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.0 — feihu1991/legado-with-MD30 reactions
- Jun 27, 2026Create a SKILL for every migration — InsertKoinIO/koin-compiler-plugin0 reactions
- Jun 25, 2026Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.0 — investigaciongiis/test_signal_android0 reactions
- Jun 15, 2026Bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.0 — alexandregpereira/Monster-Compendium0 reactions
- Jun 9, 2026bump: (deps): bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.0 — TENUM-Dev/tenum0 reactions
- May 19, 2026Add Kotlin Agent Skill for DataFrame — Kotlin/dataframe0 reactions
- Apr 25, 2018Come to the Dark Side : we have Kotlin! 🍪 — ghusta/android-docker-search0 reactions · 1 comment
On Bluesky · 3
- Mar 18, 2026The @kotlinlang.org team has been working on some skills. There is one for migrating your project to AGP 9, done by my super-smart… — @pamelaahill.bsky.social15 likes and reposts
- May 18, 2026Kotlin Agent Skills: github.com/Kotlin/kotli... #kotlin — @kotlinweekly.bsky.social8 likes and reposts
- May 19, 2026🤖 Kotlin agent skills are now available on GitHub! Explore AI-assisted skills for converting Java to Kotlin, migrating to AGP 9.0, mapping… — @kotlinlang.org5 likes and reposts · 1 reply
On Hacker News · 1
- May 18, 2026Kotlin-agent-skills: A collection of skills for projects using Kotlin1 point
Other versions3 projects use a version of this.
Word for word · 0
None found.
Edited · 3
- JetBrains/skills★ 38693% same
- torad-labs/agent-driven-architecture★ 496% same
- TeddyAlbina/skills★ 296% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository9 other files it gives its agents.
- kotlin-tooling-agp9-migrationSkill
- kotlin-tooling-cocoapods-spm-migrationSkill
- kotlin-tooling-gradle-to-kotlin-toolchain-pluginSkill
- kotlin-tooling-gradle-to-kotlin-toolchain-projectSkill
- kotlin-tooling-immutable-collections-0-5-x-migrationSkill
- kotlin-tooling-java-to-kotlinSkill
- kotlin-tooling-kotlin-toolchain-plugin-authoringSkill
- kotlin-tooling-kotlin-toolchainSkill
- kotlin-tooling-native-build-performanceSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
16 rules. 7 are common, 0 are distinctive, and 9 are very specific to this project.
7
Common
Most of the 3 edited versions we read keep these.
0
Distinctive
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 29
Never use
data classfor JPA entities: Use a regular class. Keep data class for DTOs. - Common: line 30
Keep transport DTOs and persistence entities separate unless the project clearly uses a shared model.
- Very specific: line 32
Use lateinit only when the project already accepts that tradeoff and the lifecycle is safe.
- Very specific: line 33
Verify kotlin("plugin.jpa") or equivalent no-arg support when JPA entities exist.
- Common: line 34
Verify classes and members are compatible with proxying where needed.
- Very specific: line 38
Never accept all-field equals/hashCode generated by data class on an entity.
- Common: line 39
Follow project conventions when they already define an identity strategy.
- Very specific: line 40
If no convention exists, use ID-based equality with a stable hashCode.
- Common: line 97
When an API must be idempotent (e.g., "reserve stock for order X"), enforce uniqueness at both layers: database constraint for correctness, …
- Very specific: line 165
Prefer targeted fetch solutions: @EntityGraph, JOIN FETCH, batch fetching, or DTO projection.
- Common: line 167
Use indexes and uniqueness constraints to support real query patterns.
- Very specific: line 172
orphanRemovalvs cascade remove: not interchangeable. Explain lifecycle semantics before choosing. - Very specific: line 182
Do not use data class for JPA entities.
- Very specific: line 183
Do not recommend FetchType.EAGER everywhere to silence lazy loading symptoms.
- Common: line 184
Do not expose entities directly through API responses by default.
- Common: line 185
Do not claim an N+1 fix without explaining how the fetch plan changes query behavior.
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
JPA Entity Mapping for Kotlin
Kotlin's data class is natural for DTOs but dangerous for JPA entities. Hibernate relies on
identity semantics that data class breaks: equals/hashCode over all fields corrupts
Set/Map membership after state changes, and auto-generated copy() creates detached
duplicates of managed entities.
This skill teaches correct entity design, identity strategies, and uniqueness constraints for Kotlin + Spring Data JPA projects.
Entity Design Rules
- Never use
data classfor JPA entities. Use a regularclass. Keepdata classfor DTOs. - Keep transport DTOs and persistence entities separate unless the project clearly uses a shared model.
- Model required columns as non-null only when object construction and persistence lifecycle make it safe.
- Use
lateinitonly when the project already accepts that tradeoff and the lifecycle is safe. - Verify
kotlin("plugin.jpa")or equivalent no-arg support when JPA entities exist. - Verify classes and members are compatible with proxying where needed.
Identity and Equality
- Never accept all-field
equals/hashCodegenerated bydata classon an entity. - Follow project conventions when they already define an identity strategy.
- If no convention exists, use ID-based equality with a stable
hashCode. - For DB-generated IDs, model the unsaved state with nullable
var id: Long? = nulland aprotected set; do not use0Las a sentinel value. - Be explicit about mutable fields and lazy associations when discussing equality.
Broken: data class Entity
// WRONG: data class generates equals/hashCode from ALL fields,
// and the generated ID uses a 0 sentinel instead of null
data class Order(
@Id @GeneratedValue val id: Long = 0,
var status: String,
var total: BigDecimal
)
// BUG: order.status = "SHIPPED"; set.contains(order) → false (hash changed)
// BUG: Hibernate proxy.equals(entity) → false (proxy has lazy fields uninitialized)Correct: Regular Class with ID-Based Identity
@Entity
@Table(name = "orders")
class Order(
@Column(nullable = false)
var status: String,
@Column(nullable = false)
var total: BigDecimal
) {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
protected set
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Order) return false
return id != null && id == other.id
}
override fun hashCode(): Int = javaClass.hashCode()
// toString must NOT reference lazy collections
override fun toString(): String = "Order(id=$id, status=$status)"
}Key rules:
equalscompares by ID only — stable under dirty tracking and proxy unwrappinghashCodereturns class-based constant — avoidsSet/Mapcorruption after persisttoStringexcludes lazy-loaded relations — preventsLazyInitializationException- Constructor params are mutable entity fields; DB-generated
idis nullable with a protected setter
Uniqueness Constraints
When an API must be idempotent (e.g., "reserve stock for order X"), enforce uniqueness at both layers: database constraint for correctness, application check for clean errors.
Broken: No Duplicate Guard
@Service
class ReservationService(private val repo: ReservationRepository) {
@Transactional
fun createReservation(variantId: Long, orderId: String, qty: Int): Reservation {
// BUG: no check — duplicates silently accumulate
return repo.save(Reservation(variantId = variantId, orderId = orderId, quantity = qty))
}
}Correct: Database Constraint + Application Guard
@Entity
@Table(
name = "reservations",
uniqueConstraints = [
UniqueConstraint(columnNames = ["variant_id", "order_id"])
]
)
class Reservation(
@Column(name = "variant_id", nullable = false)
val variantId: Long,
@Column(name = "order_id", nullable = false)
val orderId: String,
@Column(nullable = false)
var quantity: Int
) {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
protected set
}
interface ReservationRepository : JpaRepository<Reservation, Long> {
fun findByVariantIdAndOrderId(variantId: Long, orderId: String): Reservation?
}
@Service
class ReservationService(private val repo: ReservationRepository) {
@Transactional
fun createReservation(variantId: Long, orderId: String, qty: Int): Reservation {
repo.findByVariantIdAndOrderId(variantId, orderId)?.let {
throw IllegalStateException(
"Reservation already exists for variant=$variantId, order=$orderId"
)
}
return repo.save(Reservation(variantId = variantId, orderId = orderId, quantity = qty))
}
}Key rules:
- Database constraint is mandatory — application checks alone have race conditions
- Application check provides clean error messages — without it, users get raw
DataIntegrityViolationException - Both layers together: application catches the common case, database catches the race
- Spring Data derives
findByXAndYqueries automatically
Query and Fetch Rules
- Diagnose N+1 by looking at actual query count or SQL logs, not by guessing from annotations.
- Prefer targeted fetch solutions:
@EntityGraph,JOIN FETCH, batch fetching, or DTO projection. - Be careful with collection fetch joins plus pagination — call out the tradeoff.
- Use indexes and uniqueness constraints to support real query patterns.
Common ORM Traps
- Bidirectional associations: maintain both sides in domain methods. Half-updated graphs cause subtle bugs.
orphanRemovalvs cascade remove: not interchangeable. Explain lifecycle semantics before choosing.- Lazy load triggers:
toString, debug logging, JSON serialization, and IDE inspection can all trigger lazy loads. - Bulk updates/deletes: bypass persistence context and lifecycle callbacks. Subsequent reads may be stale.
- Multiple bag fetches: can cause Cartesian explosion. Verify the ORM can execute collection-heavy fetch plans safely.
Set+ mutable equality: collection membership can break after entity state changes.@Version: the clearest optimistic concurrency mechanism when concurrent updates matter.open-in-viewdisabled: DTO mapping touching lazy fields must happen inside a transaction boundary.
Guardrails
- Do not use
data classfor JPA entities. - Do not recommend
FetchType.EAGEReverywhere to silence lazy loading symptoms. - Do not expose entities directly through API responses by default.
- Do not claim an N+1 fix without explaining how the fetch plan changes query behavior.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

