Search code examples
javajdbi

Bean mapper with @SqlQuery and @RegisterBeanMapper cant instantiate JDBI V3


I cant not use Jdbi with a Dao Interface as the documentation shows, see http://jdbi.org/#_reflection_mappers it throws next exception:

Exception in thread "main" java.lang.IllegalArgumentException: A bean, model.tipolog.TipoLog, was mapped which was not instantiable
List<TipoLog> tipoLogs1=jdbi.withExtension(TipoLogDao.class,dao->{
        return dao.listAllLogs();
});

public interface TipoLogDao {
    @SqlQuery("SELECT * FROM tamble")
    @RegisterBeanMapper(TipoLog.class)
    List<TipoLog> listAllLogs();
}

public class TipoLog {

    private String IdTipoLog;
    private String Nombre;
    private String Descripcion;
    private String Activo;

    @ConstructorProperties({"IdTipoLog", "Nombre", "Descripcion", "Activo"})
    public TipoLog(String IdTipoLog, String Nombre, String Descripcion, String Activo) {
        this.IdTipoLog = IdTipoLog;
        this.Nombre = Nombre;
        this.Descripcion = Descripcion;
        this.Activo = Activo;
    }
}

Solution

  • Note: This solution works, but if you want to use a specific constructor (not the default one), then this answer is not the one you are looking for. As said by Jigar Shah, Use @RegisterConstructorMapper instead of @RegisterBeanMapper. A BeanMapper uses only the default constructor and set properties values. To use a specific constructor, the solution is to use a ConstructorMapper.

    Your TipoLog class needs a default constructor. This works:

    User.java

    import java.beans.ConstructorProperties;
    
    public class User {
        int id;
        String name;
    
        // required default constructor
        public User() {
            super();
        }
    
        @ConstructorProperties({ "id", "name" })
        public User(int id, String name) {
            super();
            this.id = id;
            this.name = name;
        }
    
        // getter, setter, hashCode, equals, toString
    }
    

    UserDao.java

    import java.util.List;
    
    import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
    import org.jdbi.v3.sqlobject.statement.SqlQuery;
    import org.jdbi.v3.sqlobject.statement.SqlUpdate;
    
    public interface UserDao {
        @SqlUpdate("CREATE TABLE user (id INTEGER PRIMARY KEY, name VARCHAR)")
        void createTable();
    
        @SqlUpdate("INSERT INTO user(id, name) VALUES (?, ?)")
        void insertPositional(int id, String name);
    
        @SqlQuery("SELECT * FROM user ORDER BY name")
        @RegisterBeanMapper(User.class)
        List<User> listUsers();
    }
    

    ConstructorPropertiesExplore.java

    import java.util.List;
    import static org.assertj.core.api.Assertions.*;
    import org.jdbi.v3.core.Jdbi;
    import org.jdbi.v3.sqlobject.SqlObjectPlugin;
    
    public class ConstructorPropertiesExplore {
    
        public static void main(String[] args) {
            Jdbi jdbi = Jdbi.create("jdbc:h2:mem:test");
            jdbi.installPlugin(new SqlObjectPlugin());
    
            List<User> users = jdbi.withExtension(UserDao.class, dao -> {
                dao.createTable();
                dao.insertPositional(0, "Alice");
                dao.insertPositional(1, "Bob");
                dao.insertPositional(2, "Clarice");
                dao.insertPositional(3, "David");
    
                return dao.listUsers();
            });
    
            assertThat(users).containsExactly(new User(0, "Alice"), new User(1, "Bob"), new User(2, "Clarice"),
                    new User(3, "David"));
        }
    
    }