我有一个表,其中包含创建的时间戳(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
(