JOOQ查询嵌套对象报错:无Integer与UserEntity转换器问题解决
数据库中User与Project是一对多关联关系,尝试用JOOQ将关联查询结果映射为单个对象,执行代码如下:
dsl.select() .from(PROJECT.join(USERS) .on(USERS.ID.eq(PROJECT.ID_USERS))).where(PROJECT.ID.eq(id)) .fetchOneInto(ProjectEntity.class)
UserEntity实体类定义:
@Getter @Setter @AllArgsConstructor @NoArgsConstructor public class UserEntity { private int id; private String username; private String password; private String email; //private List<ProjectEntity> projects; }
ProjectEntity实体类定义:
@Getter @Setter @AllArgsConstructor @NoArgsConstructor public class ProjectEntity { private Integer id; private String name; private String description; private String location; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") private LocalDateTime creationDate; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") private LocalDateTime lastModifiedDate; private Integer idUsers; }
执行时报错:
org.jooq.exception.DataTypeException: No Converter found for types java.lang.Integer and com.xmobots.domain.entities.UserEntity
你用select()查询了PROJECT和USERS两张表的所有字段,JOOQ在映射到ProjectEntity时,会尝试把查询结果里的每个字段都匹配到实体类的属性上。但查询结果包含了User表的字段(比如id、username等),而ProjectEntity里没有对应能接收这些字段的属性,JOOQ在字段匹配时出现类型混淆——比如把User表的Integer类型id字段,误尝试映射到某个不存在的UserEntity类型属性上,导致找不到合适的类型转换器,抛出异常。
说白了就是:查出来的字段太多,超出了ProjectEntity能接收的范围,多余的User字段无法正确映射,引发类型转换错误。
根据需求不同,有两种常用处理方式:
方式一:只查询Project表字段(不需要User数据时)
如果只需要ProjectEntity的数据,不需要关联的User信息,直接查询Project表的字段即可,避免返回多余字段:
dsl.select(PROJECT.fields()) .from(PROJECT) .where(PROJECT.ID.eq(id)) .fetchOneInto(ProjectEntity.class);
方式二:映射包含UserEntity的扩展实体(需要User数据时)
如果需要把关联的User信息一并映射到对象里,可以修改ProjectEntity添加UserEntity属性,再让JOOQ正确映射关联字段:
- 修改ProjectEntity,新增UserEntity属性:
@Getter @Setter @AllArgsConstructor @NoArgsConstructor public class ProjectEntity { private Integer id; private String name; private String description; private String location; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") private LocalDateTime creationDate; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") private LocalDateTime lastModifiedDate; private Integer idUsers; // 添加关联的User实体 private UserEntity user; }
- 用字段别名实现嵌套映射,让JOOQ把User字段对应到user属性下:
dsl.select( PROJECT.ID, PROJECT.NAME, PROJECT.DESCRIPTION, PROJECT.LOCATION, PROJECT.CREATION_DATE, PROJECT.LAST_MODIFIED_DATE, PROJECT.ID_USERS, USERS.ID.as("user.id"), USERS.USERNAME.as("user.username"), USERS.PASSWORD.as("user.password"), USERS.EMAIL.as("user.email") ) .from(PROJECT.join(USERS).on(USERS.ID.eq(PROJECT.ID_USERS))) .where(PROJECT.ID.eq(id)) .fetchOneInto(ProjectEntity.class);
或者自定义映射逻辑,手动拆分记录到两个实体后组合:
ProjectEntity project = dsl.select() .from(PROJECT.join(USERS).on(USERS.ID.eq(PROJECT.ID_USERS))) .where(PROJECT.ID.eq(id)) .fetchOne(record -> { ProjectEntity p = record.into(PROJECT).into(ProjectEntity.class); UserEntity u = record.into(USERS).into(UserEntity.class); p.setUser(u); return p; });
内容的提问来源于stack exchange,提问作者Mark Philips

