如何用jOOQ将数据库BIGINT类型日期转换为LocalDateTime?
问题:BIGINT存储的日期如何直接映射到CheckIn的LocalDateTime字段?
我数据库里的日期用Long类型(BIGINT)存储,现在要查询数据并映射到CheckIn记录,代码示例如下:
context.select(CHECKINS.CHECKIN_TIME, CHECKINS.CHECKOUT_TIME ).from(CHECKINS) .fetch(Records.mapping(CheckIn::new));
其中CHECKINS表的两个字段类型为TableField<CheckinsRecord, Long>,CheckIn记录定义为:
public record CheckIn(LocalDateTime checkIn, LocalDateTime checkOut) { }
请问能否在select语句中直接将CHECKINS.CHECKIN_TIME转换为LocalDateTime,还是需要后续再进行转换?
可以在select语句中直接转换,这是更简洁的方案
用JOOQ提供的类型转换能力,直接在查询阶段把BIGINT类型的时间戳转成LocalDateTime,这样Records.mapping(CheckIn::new)就能直接匹配构造方法的参数类型,不用额外处理。
具体实现代码
假设你的Long值是毫秒级时间戳,可以用两种方式实现:
方式1:利用数据库函数转换(依赖数据库支持)
context.select( // 将毫秒级时间戳转成秒,再用TO_TIMESTAMP转成日期类型 DSL.field("TO_TIMESTAMP({0} / 1000)", LocalDateTime.class, CHECKINS.CHECKIN_TIME), DSL.field("TO_TIMESTAMP({0} / 1000)", LocalDateTime.class, CHECKINS.CHECKOUT_TIME) ).from(CHECKINS) .fetch(Records.mapping(CheckIn::new));
如果是秒级时间戳,去掉/1000即可。
方式2:用JOOQ的convertFrom方法(类型更安全)
context.select( CHECKINS.CHECKIN_TIME.convertFrom(timestamp -> LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()) ), CHECKINS.CHECKOUT_TIME.convertFrom(timestamp -> LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()) ) ).from(CHECKINS) .fetch(Records.mapping(CheckIn::new));
后续转换的备选方案
如果不想在查询阶段处理,也可以先查询出Long值,再在映射时转换:
context.select(CHECKINS.CHECKIN_TIME, CHECKINS.CHECKOUT_TIME) .from(CHECKINS) .fetch(record -> new CheckIn( LocalDateTime.ofInstant(Instant.ofEpochMilli(record.get(CHECKINS.CHECKIN_TIME)), ZoneId.systemDefault()), LocalDateTime.ofInstant(Instant.ofEpochMilli(record.get(CHECKINS.CHECKOUT_TIME)), ZoneId.systemDefault()) ));
整体来说,优先推荐在select语句中直接转换,代码更简洁,也能减少内存中数据转换的开销。
内容的提问来源于stack exchange,提问作者homaxto
相关产品推荐
相关产品推荐

