Kotlin with JPA: How to Defeat Default Constructor Hell

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Meet the "Default Constructor Hell" in Kotlin + JPA

\n\n

If you've ever tried to make Kotlin work with JPA (Java Persistence API), you've likely encountered a situation where Hibernate throws an exception like this when starting the application:

\n\n
org.hibernate.InstantiationException: No default constructor for entity: com.example.User\n
\n\n

Sound familiar? It sure does. This is the problem that has gathered thousands of views on Stack Overflow and earned the grim name "Kotlin with JPA: default constructor hell".

\n\n

In this article, we'll calmly, step by step, break down:

\n
    \n
  • Why this error occurs in the first place
  • \n
  • Why Kotlin "doesn't want" to generate an empty constructor
  • \n
  • Three proven ways to solve the problem (from simple to professional)
  • \n
  • Which method to choose for your project
  • \n
\n\n

Let's go!

\n\n

Why does Hibernate require a no-argument constructor?

\n\n

Let's start with Java. In classic Java, we are used to writing:

\n\n
public class User {\n    private Long id;\n    private String name;\n\n    // Mandatory empty constructor\n    public User() {}\n\n    // Getters, setters...\n}\n
\n\n

Hibernate (and any JPA implementation) uses reflection to create objects. When it reads a row from the database, it needs to create an instance of the User class, and then populate the fields via reflection. For this, it needs a constructor without parameters (default constructor).

\n\n

In Java, the compiler automatically creates an empty constructor if you haven't defined any other constructor. Therefore, the problem usually doesn't arise.

\n\n

What's special about Kotlin?

\n\n

Kotlin is a language with a strong emphasis on immutability and safety. Take a look at a typical Kotlin class:

\n\n
data class User(\n    val id: Long = 0,\n    val name: String = ""\n)\n
\n\n

Two key things are happening here:

\n
    \n
  • All properties are declared in the primary constructor
  • \n
  • Properties are declared as val (immutable) and have default values
  • \n
\n\n

Kotlin does not generate a separate empty constructor if you have a primary constructor with parameters. Even if all parameters have default values, this is not considered a "real" no-argument constructor at the JVM bytecode level.

\n\n

When Hibernate tries to call User.class.newInstance() via reflection, it doesn't find an empty constructor — and crashes with an error.

\n\n

Method 1: The Simplest — Explicitly Add a Secondary Constructor

\n\n

The most straightforward path is to add a second, empty constructor manually:

\n\n
data class User(\n    val id: Long = 0,\n    val name: String = ""\n) {\n    // Secondary constructor without parameters\n    constructor() : this()\n}\n
\n\n

Here, constructor() : this() means: "call the primary constructor with default values".

\n\n

Pros:

\n
    \n
  • Very simple and clear
  • \n
  • Requires no plugins or additional configuration
  • \n
\n\n

Cons:

\n
    \n
  • You need to write this constructor for every entity
  • \n
  • If you have 10-15 entities, it becomes tedious
  • \n
  • Easy to forget to add
  • \n
\n\n

Method 2: Use an open class and make all properties var

\n\n

Many examples online suggest this solution:

\n\n
open class User {\n    var id: Long = 0\n    var name: String = ""\n}\n
\n\n

Here, we make the class open (so Hibernate can create proxies), and the properties — var (mutable). And there's no primary constructor — meaning Kotlin will generate a default empty constructor.

\n\n

Pros:

\n
    \n

Blogs

Book Recommendations