【问题标题】:JPA CriteriaQuery compare Timestamp ignore time portionJPA CriteriaQuery比较时间戳忽略时间部分
【发布时间】:2017-04-23 03:29:23
【问题描述】:

假设我在 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 中我没有这样做 - 失败不是一种选择,所以请告诉我们是如何失败的
  • @ScaryWombat 我收到此错误消息:ORA-01858:在需要数字的地方发现了一个非数字字符。我怀疑 cb.literal() 有问题。
  • 嘿,只要打印出条件查询和绑定参数的实际 sql,您就会知道问题出在哪里。我猜它是 TO_DATE 函数,它接受一个字符串参数,但不是日期类型参数。
  • @diufanman 是的,正确的。我还发现这是问题的根本原因。谢谢!

标签: java oracle jpa timestamp criteriaquery


【解决方案1】:

好像我找到了答案:

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"))));

那我在设置参数的时候,会设置要查询的日期的String格式。

谢谢!

【讨论】:

  • 此解决方案仅适用于 cb.equal。不适用于 cb.between、cb.greaterThan 等
  • 优秀。谢谢。
  • @jijo 我使用的是 Oracle 12c,它对 cb.greaterThan 和 cb.lessThan 都很好
  • 感谢您的解决方案,苦苦挣扎了两个星期,然后用这个解决方案解决了。
【解决方案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

【讨论】:

    【解决方案3】:

    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"))));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-23
      • 2014-09-21
      • 2019-03-17
      • 2012-02-18
      • 2016-02-14
      • 2012-05-08
      • 1970-01-01
      相关资源
      最近更新 更多