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

JOOQ中如何用java.time.Duration实现过期对象查询?

解决JOOQ中TTL过期对象查询的类型兼容问题

核心思路

不要在Java端计算时间差再做比较,而是把过期时间的计算逻辑推到数据库端:判断当前时间是否大于created + time_to_live。这种方式完全绕开Java层的类型转换冲突,同时数据库端的时间运算性能更优,结果也更准确。

具体实现代码

修改fetchExpired方法如下:

public class MyObjectRepository {

  public Stream<MyObjectDto> fetchExpired() {
    return context
        .selectFrom(MY_OBJECT)
        .where(currentLocalDateTime().greaterThan(
            MY_OBJECT.CREATED.add(MY_OBJECT.TIME_TO_LIVE)
        ))
        .forUpdate()
        .skipLocked()
        .fetchStreamInto(MyObjectDto.class);
  }
}

方案优势

  • JOOQ的Field.add()原生支持timestamp与interval类型的加法运算,会直接生成对应SQL(比如PostgreSQL中的created + time_to_live),完全在数据库层面完成计算。
  • 保留了你原本的Duration强制类型配置,不需要修改API结构,满足简洁性要求。
  • 避免Java端计算时间差可能带来的时区、精度不一致问题。

备选方案(Java端比较场景)

如果因特殊需求必须在Java端处理差值比较,可以手动将Duration类型字段转换为JOOQ内置的YearToSecond类型:

public class MyObjectRepository {

  public Stream<MyObjectDto> fetchExpired() {
    return context
        .selectFrom(MY_OBJECT)
        .where(localDateTimeDiff(currentLocalDateTime(), MY_OBJECT.CREATED)
            .greaterThan(MY_OBJECT.TIME_TO_LIVE.convert(org.jooq.types.YearToSecond.class)))
        .forUpdate()
        .skipLocked()
        .fetchStreamInto(MyObjectDto.class);
  }
}

不过该方案依赖你配置的转换器,效率和简洁性不如第一种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 04:15:39