You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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正确映射关联字段:

  1. 修改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;
}
  1. 用字段别名实现嵌套映射,让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 11:43:15