使用JOOQ插入数据时设置数据库当前时间戳替代JVM时间
你当前基于UpdatableRecord的代码可以通过以下几种方式实现需求,无需传入JVM生成的时间:
方案1:直接传入jOOQ内置时间函数(无需修改表结构,适配现有代码写法)
删除原有代码里的disclaimerRecord.setAcceptedAt(LocalDateTime.now());行,替换为给字段设置SQL级时间表达式,jOOQ生成SQL时会直接将函数拼入语句,不会传入Java侧生成的时间参数:// 对应数据库CURRENT_TIMESTAMP,返回类型匹配LocalDateTime disclaimerRecord.set(Disclaimer.DISCLAIMER.ACCEPTED_AT, DSL.currentLocalDateTime());最终生成的INSERT语句会包含
ACCEPTED_AT = CURRENT_TIMESTAMP片段,直接取数据库执行语句时刻的当前时间。如果你的字段是带时区的时间类型,替换为DSL.currentOffsetDateTime()或DSL.currentTimestamp()匹配字段类型即可。方案2:依托数据库字段默认值(长期维护成本最低)
直接在数据库层给accepted_at字段设置默认值:ALTER TABLE disclaimer ALTER COLUMN accepted_at SET DEFAULT CURRENT_TIMESTAMP;重新生成jOOQ代码后,业务代码里完全不需要调用
setAcceptedAt方法,执行store()时jOOQ不会将该字段加入INSERT的列列表,数据库会自动填充默认当前时间。如果需要插入后拿到数据库生成的时间值,可以在jOOQ配置中开启withReturningAllOnUpdatableRecord(true),插入完成后Record会自动取回数据库生成的字段值,无需额外查询。方案3:改用显式INSERT DSL写法
如果不使用UpdatableRecord的store方法,直接编写DSL插入语句也可以直接指定服务端时间:dslContext.insertInto(Disclaimer.DISCLAIMER) .set(Disclaimer.DISCLAIMER.DISCLAIMER_FOR_ID, acknowledgeDisclaimerReq.getDealListingId()) .set(Disclaimer.DISCLAIMER.DISCLAIMER_FOR_TYPE, "DEAL") .set(Disclaimer.DISCLAIMER.ACCEPTED_AT, DSL.currentLocalDateTime()) .set(Disclaimer.DISCLAIMER.ACCEPTED_BY_OWNER_ID, acknowledgeDisclaimerReq.getLoggedInOwnerId()) .execute();
注意:如果采用方案2的默认值方式,后续更新记录时不要调用
setAcceptedAt方法,否则会覆盖数据库自动生成的原始时间。
内容的提问来源于stack exchange,提问作者Mayuran

