【问题标题】:Criteria API order by time between two LocalDateTime两个 LocalDateTime 之间的 Criteria API order by time
【发布时间】:2019-02-11 12:40:12
【问题描述】:

给定一个具有两个 LocalDateTime 类型的日期字段的实体:

class MyEntity {

    private LocalDateTime start;
    private LocalDateTime lastUpdate;

}

我想用条件 api 编写一个查询,按这两个日期之间的时间对结果集进行排序。

/* ... */
Root<MyEntity> root = query.from(MyEntity.class);
Order order = ???
root.orderBy(cb.desc(order));
/* ... */

到目前为止我的想法:

  • CriteriaBuilder#diff 希望它的参数来自 Number,而 LocalDateTime 不这样做
  • CriteriaBuilder#treat 也许以某种方式将其视为时间戳?毕竟它作为时间戳存储在数据库中

ps:

  • 使用 EclipseLink 2.7.3
  • 寻找不与特定数据库绑定的解决方案

【问题讨论】:

    标签: jpa eclipselink criteria-api


    【解决方案1】:

    您认为cb.treat(..) 会进行向下转换的想法不会奏效,因为Number 不会扩展/继承LocalDateTime。即使有可能,也会出现问题,因为没有办法直接在数据库端将数据库timestamp 类型转换为任何Number

    我找到了this question,这可能会对您有所帮助。接受的答案使用标准(?)SQL函数TIMESTAMPDIFF,这应该是完全独立于实现的解决方案。您可以根据该答案进行一些通用排序。

    但是,一个选项也可以为持续时间/间隔添加一个新的计算字段,例如:

    private Duration duration;
    
    @PrePersist // update on each persist
    private void calcDuration() {
        duration = Duration.between(start, lastUpdate);
    }
    

    那么排序会是这样的:

    Path<Long> duration = root.get("duration");  // duration is stored as bigint or like
    criteriaQuery.orderBy(criteriaBuilder.desc(duration)); // or .asc(..)
    

    duration 自然会消耗 db 中的额外空间 - 它通常应该只是瞬态和/或计算值 - 但它也可能带来一些性能提升。

    【讨论】:

    • 考虑到比较麻烦的 timstamps 我去额外的数据库字段。
    猜你喜欢
    • 1970-01-01
    • 2010-12-19
    • 2016-03-09
    • 2013-04-30
    • 2013-11-11
    • 2011-10-09
    • 1970-01-01
    • 2013-11-02
    • 2016-10-31
    相关资源
    最近更新 更多