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

使用JOOQ转换器实现java.sql.Timestamp与java.time.Instant互转查询失效问题

问题原因
  • 代码中存在多处语法和定义错误,导致绑定了转换器的自定义字段没有被正确识别:
    1. User类中created字段定义时错误复用了name作为变量名,构造字段名时误用了不存在的table.getCreated()方法,同时重复调用了Converter.of()方法
    2. 插入语句指定的字段和实际传入的数值不匹配,代码中写的User.firstName、User.lastName并没有提前定义
  • 核心的查询时转换器不生效问题,是因为你调用select().from(User.table)时使用的是无参数的select(),相当于执行select *,jOOQ会返回无类型绑定的通用Record,默认使用JDBC原生的Timestamp类型,不会自动应用你自定义User.created字段绑定的转换器。
修复方案
  1. 先修正User类的字段定义:
public class User {
    private static final Converter<Timestamp, Instant> MY_CONVERTER= Converter.of(
        Timestamp.class,
        Instant.class,
        t -> t == null ? null : t.toInstant(),
        i -> i == null ? null : Timestamp.from(i)
    );
    public static Table<?> table = DSL.table("user");
    public static Field<String> name = DSL.field(DSL.name(table.getName(), "name"), String.class);
    // 修正变量名、字段构造参数、转换器绑定逻辑
    public static Field<Instant> created = DSL.field(DSL.name(table.getName(), "created"), 
        SQLDataType.TIMESTAMP.asConvertedDataType(MY_CONVERTER));    
}
  1. 修正插入语句的字段参数,和传入值对应:
dslContext.insertInto(User.table, User.name, User.created)
    .values(user.getName(), user.getCreated())
    .execute();
  1. 修正查询逻辑,触发转换器生效,两种方案可选:
  • 方案一(推荐):查询时明确指定自定义的字段,返回的Record会自动应用转换器:
public Result<Record> getAll() {
    // 明确指定要查询的自定义字段,不要用无参数select()
    return dslContext.select(User.name, User.created).from(User.table).fetch();
}

修改后调用record.get(User.created)就会直接返回Instant类型,不需要额外转换。

  • 方案二:如果确实需要查询全表所有字段,也可以在取值时显式指定转换器:
public static UserDto from(Record record) {
    UserDto user = new UserDto();
    user.setName(record.get(User.name));
    // 取值时显式传入转换器做转换
    user.setCreated(record.get(User.created, MY_CONVERTER));
    return user;
}

内容的提问来源于stack exchange,提问作者ChambreNoire

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 12:15:05