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
相关产品推荐
相关产品推荐

