The prefixes in the registered mappers apply to top level beans. So your Child bean is correctly mapped using the "c" prefix. However, the "@Nested" annotation does not provide any additional information what columns to use for the nested bean. So JDBI tries to map columns with the "c" prefix onto the "Parent" bean, which does not work. Replace the @Nested
annotation with @Nested("p")
to signal JDBI that this nested bean uses a different prefix. However, as this is a nested Bean, JDBI uses a nested prefix (which is c_p). So select the columns for the parent as p_id as c_p_id
.
This code works with JDBI 3.33.0 (where there are some changes to the bean mapping logic):
@Test
void testParentChild() {
handle.execute("create table child (id integer not null, parent_id integer, created timestamp)");
handle.execute("create table parent(id integer, created timestamp)");
handle.execute("insert into parent (id, created) values (1, now())");
handle.execute("insert into parent (id, created) values (2, now())");
handle.execute("insert into parent (id, created) values (3, now())");
handle.execute("insert into child(id, parent_id, created) values(1, 1, now())");
handle.execute("insert into child(id, parent_id, created) values(2, 1, now())");
handle.execute("insert into child(id, parent_id, created) values(3, 1, now())");
handle.execute("insert into child(id, parent_id, created) values(4, 2, now())");
handle.execute("insert into child(id, parent_id, created) values(5, 2, now())");
handle.execute("insert into child(id, parent_id, created) values(6, 2, now())");
handle.execute("insert into child(id, parent_id, created) values(7, 3, now())");
handle.execute("insert into child(id, parent_id, created) values(8, 3, now())");
handle.execute("insert into child(id, parent_id, created) values(9, 3, now())");
ParentChildDao dao = handle.attach(ParentChildDao.class);
Child c = dao.getChild(4);
assertThat(c).isNotNull();
assertThat(c.getParent()).isNotNull();
assertThat(c.getParent().getId()).isEqualTo(2);
}
public static class Child {
private int id;
private Parent parent;
private Instant created;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Parent getParent() {
return parent;
}
@Nested("p")
public void setParent(Parent parent) {
this.parent = parent;
}
public Instant getCreated() {
return created;
}
public void setCreated(Instant created) {
this.created = created;
}
}
public static class Parent {
private int id;
private Instant created;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Instant getCreated() {
return created;
}
public void setCreated(Instant created) {
this.created = created;
}
}
public interface ParentChildDao {
@SqlQuery("SELECT c.id as c_id, c.created as c_created,p.id as c_p_id FROM child as c INNER JOIN parent p on p.id = c.parent_id WHERE c.id = :id")
@RegisterBeanMapper(value=Child.class, prefix="c")
@RegisterBeanMapper(value=Parent.class)
Child getChild(int id);
}