No default constructor found with Java record and BeanPropertyRowMapper

Jan Bodnar :

I am playing with the new Java 14 and Spring Boot. I have used the new cool record instead of a regular Java class for data holders.

package com.zetcode.model;

public record City(Long id, String name, Integer population) {

}

Later in my service class, I use Spring BeanPropertyRowMapper to fetch data.

   @Override
    public City findById(Long id) {

        String sql = "SELECT * FROM cities WHERE id = ?";

        return jtm.queryForObject(sql, new Object[]{id},
                new BeanPropertyRowMapper<>(City.class));
    }

I end up with the following error:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zetcode.model.City]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.zetcode.model.City.<init>()
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:145) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]

How to add a default constructor for a record or is there any other way to fix this?

slesh :

Just declare it explicitly by providing default for fields:

public record City(Long id, String name, Integer population) {
    public City() {
        this(0L, "", 0)
    }
}

An important note. BeanPropertyRowMapper scans setters/getters to inflate your record instance, as record is immutable, there is not setter and it's not compatible with java beans specification, you'll get and empty record. Please, read this SO. The only way to create a record is by using a constructor. So, you have two options: either use plain java bean or implement your custom row mapper.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=237346&siteId=1
Recommended