Yes, but a Kotlin data class is usually a poor default for a JPA entity. Kotlin’s JPA compiler plugin can address the no-argument-constructor requirement and, in Kotlin 2.3.20 and later, the class-openness needed for common lazy-loading patterns. It does not change the data class’s generated value-based equality, hash code, copy(), or toString(). Those behaviors may not fit entities whose identity and relationships change over their lifetime.
What Kotlin data classes generate—and why it matters for entities
Kotlin data classes are designed to hold data. For properties in the primary constructor, Kotlin generates equals(), hashCode(), toString(), component functions such as component1(), and copy(). See the Kotlin data classes documentation.
That generated behavior is value-oriented: the constructor properties determine the comparison and string representation. JPA entities, by contrast, are managed objects with persistence identity and potentially changing state. If a property used by generated equality or a hash code changes after an entity is placed in a hash-based collection, collection behavior can become surprising. This is a design risk, not a claim that every data-class entity will fail.
The generated copy() is also a shallow data copy, not a JPA operation. It does not mean “duplicate this entity safely” or preserve managed-entity semantics. Likewise, generated toString() may traverse constructor properties; consider whether that representation is appropriate for your entity and its relationships.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11#1 Best Overall
JPA mechanics Kotlin projects need to satisfy
No-argument constructor
Jakarta Persistence requires an entity class to have a public or protected no-argument constructor. Kotlin does not normally provide one for a class whose constructor requires arguments. The Kotlin no-arg compiler plugin can generate an additional synthetic zero-argument constructor for classes annotated with configured annotations. Kotlin and Java source code cannot call that synthetic constructor directly, but reflection can; that is the mechanism used for framework construction. The Kotlin no-arg plugin documentation describes the plugin and its JPA preset, which covers @Entity, @Embeddable, and @MappedSuperclass.
Non-final classes and members
Jakarta Persistence requires entity classes to be non-final, and persistent instance variables and methods must not be final. The Jakarta Persistence 4.0 Entity API documentation also specifies the entity constructor and class requirements; the Jakarta Persistence 3.2 specification provides the rules for that earlier specification version. Kotlin classes and their members are final by default. The Kotlin all-open plugin can open classes annotated with configured annotations.
Rank #2
Configure the Kotlin plugins for your project
For Gradle, Kotlin documents applying kotlin("plugin.jpa") with a plugin version aligned to the Kotlin compiler plugin used by the project. The JPA plugin wraps no-arg behavior and configures the JPA annotations for synthetic constructor generation. Plugin behavior is version-sensitive: starting with Kotlin 2.3.20, the JPA plugin also applies all-open with a JPA preset, intended to support lazy associations. On earlier Kotlin versions, check whether you need to configure all-open separately for your persistence provider and mapping annotations.
plugins {
kotlin("jvm") version "<your Kotlin version>"
kotlin("plugin.jpa") version "<the same Kotlin version>"
}
This is a configuration shape, not a tested, drop-in build file: use your project’s actual Kotlin version and existing plugin setup. If configuring all-open separately, ensure its annotation names match the persistence API in use. Projects using older javax.persistence annotations and projects using jakarta.persistence annotations must not assume the same annotation configuration will match both.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #3
A Kotlin data class cannot be declared open in ordinary source syntax; data classes also cannot be abstract, sealed, or inner, must have at least one primary-constructor parameter, and require all primary-constructor parameters to be val or var. Compiler-plugin transformation can adapt annotated classes for framework requirements, but does not remove the data class’s generated value semantics.
When to choose a data class or a regular entity class
| Use case | Usually the better fit | Reason |
|---|---|---|
| Persistent entity with mutable state, generated identity, or lazy relationships | Regular Kotlin class | It avoids automatically deriving entity equality, hashing, copying, and string output from constructor properties. You can define those behaviors deliberately for the entity’s identity and lifecycle. |
| Request or response data transferred between application layers | Data class | Value-style equality, destructuring, and copying are often useful for DTOs that are not managed entities. |
| Embeddable or other value-like mapped type | Possibly a data class | Value semantics may suit the role, but confirm constructor, openness, and mapping requirements for your Kotlin version and persistence provider. |
For a regular entity class, decide explicitly how identity works before implementing equality or hash codes. In particular, think through what happens when an identifier is assigned after persistence and when entity state changes while the object is in a set or map. There is no single property pattern—such as always making an ID nullable or mutable—that is correct for every application.
Quick Recap
Best Value
What the plugins do not solve
- Entity semantics: plugins handle construction and openness mechanics; they do not redesign generated data-class equality, hash codes, copying, or string output.
- Proxy compatibility: confirm the Kotlin plugin version, configured annotations, and persistence-provider behavior. Do not assume a class is proxy-ready simply because the project uses a JPA plugin, particularly on Kotlin versions before 2.3.20.
- Domain modeling: choose constructor properties, mutability, nullability, and relationship handling to match the entity lifecycle rather than relying on a plugin to make those choices.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

