JOOQ localDateTimeDiff with java.time.Duration's



我有一个表,其中包含创建的时间戳(timestamp(和生存时间(interval(。

CREATE TABLE my_object (
id uuid NOT NULL PRIMARY KEY,
created timestamp NOT NULL,
time_to_live interval NOT NULL
);

现在我想找到所有对象,它们的TTL在哪里结束。我试过这样的东西:

public class MyObjectRepository {
public Stream<MyObjectDto> fetchExpired() {
return context
.selectFrom(MY_OBJECT)
.where(localDateTimeDiff(currentLocalDateTime(), MY_OBJECT.CREATED)
.greaterThan(MY_OBJECT.TIME_TO_LIVE))
// ^- compile-error, no overload accepts TableField<MyObjectRecord, Duration>
.forUpdate()
.skipLocked()
.fetchStreamInto(MyObjectDto.class);
}
}

也许这里的大问题是,我在java.time.Duration中强制键入了TTL。但是对于干净的API,我不能将类型更改为DayToSecond

<!-- others -->
<forcedType>
<userType>java.time.Duration</userType>
<converter>org.jooq.Converter.ofNullable(
org.jooq.types.YearToSecond.class, Duration.class,
yearToSecond -> yearToSecond.toDuration(), duration -> org.jooq.types.YearToSecond.valueOf(duration)
)
</converter>
<includeTypes>INTERVAL</includeTypes>
</forcedType>
<!-- others -->

我如何在JOOQ中做到这一点?

将Duration类方法from()与TTL一起使用以创建具有TTL间隔的Duration实例,然后将Duration方法addTo()与创建时间一起使用以获得TTL过期的时刻。将该时刻与当前时间进行比较,如果当前时间在您的过期时间之后,则您的记录将过期。请参阅此处的持续时间Javadoc

我的解决方案有点像Michael Gantmans的答案,但我没有让它发挥作用。

所以。。。我稍微更改了一下SQL表。新模式如下:

CREATE TABLE my_object (
id uuid NOT NULL PRIMARY KEY,
created timestamp NOT NULL,
valid_until timestamp NOT NULL
);

有了新的模式,JOOQ工作起来非常容易。代码简化为:

public Stream<MyObjectDto> fetchExpired() {
return context
.selectFrom(MY_OBJECT)
.where(MY_OBJECT.VALID_UNTIL.lessThan(ZonedDateTime.now()))
.fetchStreamInto(MyObjectDto.class);
}

新模式还有其他一些优点:

  • 性能更高,因为每次运行都不能重新计算eol时间
  • 更高性能的²,因为valid_until可以被索引
  • 不破坏API,因为如果需要,可以计算Duration的TTL(valid_until - created(

最新更新