【问题标题】:Not able to query for SQL ignore part of WHERE, if parameter is null如果参数为空,则无法查询 SQL 忽略 WHERE 的一部分
【发布时间】:2019-02-19 07:06:55
【问题描述】:

您好,我能够获取时间范围之间的数据。 但如果我指定 OR :#{#orgSearch.createdTime.startDateTime} IS NULL 那么我得到异常

这是我的@Query

 @Query(value = "select o from Organization  o  where (o.createdAt  >:#{#orgSearch.createdTime.startDateTime} OR  :#{#orgSearch.createdTime.startDateTime}  IS NULL)  AND  (o.createdAt <:#{#orgSearch.createdTime.endDateTime}) OR  :#{#orgSearch.createdTime.endDateTime}  IS NULL ")

但我得到了如下异常......

Caused by: org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $2
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2103)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1836)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:273)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:114)
    at com.sun.proxy.$Proxy139.executeQuery(Unknown Source)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70)
    ... 95 more

有什么帮助吗?..

【问题讨论】:

  • 这是在 JPQL 中?那么它不应该发生在 Hibernate 5 中。如果是原生查询,那么还没有解决方案。
  • @coladict ,是的,这是 JPA 原生查询。是否有任何解决方案可用于此?有什么帮助吗?
  • 一种可能的解决方法是在执行查询之前将其设置为非空值,这将确定类型,然后将其设置为空,但我没有尝试过。问题出在 postgresql 服务器上,他们拒绝修复它,因为它“按预期工作”。

标签: postgresql spring-boot jpa spring-data-jpa


【解决方案1】:

我在使用 PostgreSQL 和 Instants 时也遇到过这个问题。 我为此使用的解决方法是将参数手动转换为时间戳 所以如果你的查询是这样的:

OR  :#{#orgSearch.createdTime.endDateTime}  IS NULL "

我会尝试类似:

OR  CAST(:#{#orgSearch.createdTime.endDateTime} AS TIMESTAMP) IS NULL "

希望对你有帮助

【讨论】:

    【解决方案2】:

    所以,我测试了我之前提到的这个小变通方法,它适用于 5.0-5.3 类型系统。假设您在 Java 中的时间戳类是 java.time.Instant,这可以工作

    if (timestamps == null) {
        query.setParameter("ts", java.time.Instant.EPOCH);
    }
    query.setParameter("ts", timestamp);
    

    从那时起,您的下一个问题来自关闭OR 之前的圆括号:

    ... (o.createdAt <:#{#orgSearch.createdTime.endDateTime}) OR  :#{#orgSearch.createdTime.endDateTime}  IS NULL 
    

    这一切都假设您自己使用entityManager.createNativeQuery(...) 创建查询,或者可能使用命名的本机查询,因为那些 Spring 生成的实现无法为您添加解决方法。

    【讨论】:

      【解决方案3】:

      解决办法是强制PostgreSQL将参数解释为时间戳。

      参考此查询并相应地进行查询。

      SELECT *
      FROM log
      WHERE CASE
        WHEN $P{timestampFrom}::TIMESTAMP IS NULL THEN TIMESTAMP >= '-infinity'
        ELSE TIMESTAMP >= $P{timestampFrom}
        END
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-18
        • 1970-01-01
        • 2019-07-20
        • 1970-01-01
        相关资源
        最近更新 更多