JPA CriteriaQuery 比较时间戳忽略时间部分

问题描述 投票:0回答:4

假设我在 Oracle DB 中有一个这样的列:

SOMETHING_TS     TIMESTAMP WITH TIME ZONE

我想使用 CriteriaQuery 按此列进行过滤。

我可以使用本机查询来实现此目的:

    SELECT * 
    FROM SOMETHING
    WHERE TRUNC(SOMETHING_TS) = TO_DATE('2016-12-08','YYYY-MM-DD');

但是在Java中我没有这样做,下面是我的示例代码:

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<MyClass> cq = cb.createQuery(MyClass.class);
    Date date = new Date();

    predicates.add(cb.equal(cb.function("TRUNC", Date.class, myClass.get("somethingTs")), cb.function("TO_DATE", Date.class, cb.parameter(Date.class, "somethingTs"), cb.literal("YYYY-MM-DD"))));

    Predicate[] predArray = new Predicate[predicates.size()];
    predicates.toArray(predArray);

    cq.where(predArray);

    TypedQuery<MyClass> query = em.createQuery(cq);
    query.setParameter("somethingDt", date);
java oracle jpa timestamp criteriaquery
4个回答
13
投票

看来我找到了答案:

predicates.add(cb.equal(cb.function("TRUNC", Date.class, myClass.get("somethingTs")), cb.function("TO_DATE", String.class, cb.parameter(String.class, "somethingTs"), cb.literal("YYYY-MM-DD"))));

然后当我设置参数时,我会设置要查询的日期的字符串格式。

谢谢!


2
投票

Javatar 的答案没有解决我的具体情况,但这里是对我有帮助的,以防它对任何人有帮助。

private List<MyClass> selectMyClassByDate(Date date) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<MyClass> cq = cb.createQuery(MyClass.class);
    Root<MyClass> myClass = cq.from(MyClass.class);
    cq.select(myClass);
    cq.where(cb.equal(cb.function("date", Date.class,
        myClass.get(MyClass_.timestamp)), date));
    final TypedQuery<MyClass> tq = em.createQuery(cq);
    log.fine(
        tq.unwrap(org.apache.openjpa.persistence.QueryImpl.class)
            .getQueryString());
    List<MyClass> myClassList = tq.getResultList();
    return myClassList;
}

抱歉这仅适用于 MYSQL


0
投票

Javatar 的答案即使有效也并不完美,因为 to_date 返回日期而不是字符串。使用参数也没有什么意义,最好使用文字。这是我的答案,对任何人都适用。

predicates.add(criteriaBuilder.lessThanOrEqualTo(criteriaBuilder.function("TRUNC", java.sql.Date.class, root.get("executionDateTime")),
                                                                 criteriaBuilder.function("TO_DATE", java.sql.Date.class, criteriaBuilder.literal(request.getExecutionToDate().toString()),
                                                                         criteriaBuilder.literal("yyyy-mm-dd"))));

0
投票

一个对我有用的简单解决方案。我创建一个日历变量来设置我想要比较的日期。但我把日期缩短到几天,并考虑小时、分钟和秒。

因此,我们的想法是使用 Calendar 来截断以防止使用 CriteriaBuilder.function()。

List<Predicate> predicates = new ArrayList<>();
Join<A, B> joinB = a.join("B");
Calendar startOfTheCurrentDay = GregorianCalendar.from(
                    ZonedDateTime.ofInstant(Instant.now().truncatedTo(ChronoUnit.DAYS), ZoneId.systemDefault()));

predicates.add(
    criteriaBuilder.lessThanOrEqualTo(
        criteriaBuilder.literal(startOfTheCurrentDay),
        joinB.<Calendar>get("expirationDate")
    )
);
© www.soinside.com 2019 - 2024. All rights reserved.