Java 如果不为空,则比较日期

Java 如果不为空,则比较日期,java,postgresql,Java,Postgresql,我需要找到createdate>X的所有记录。X是一个sql.Timestamp,可能为null,在这种情况下,我只想返回所有记录。所以我试着:(createdAfter是时间戳) 但我得到的只是 org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $1 但是,如果在检查任意int是否为null时执行相同的查询: SELECT * FROM trades WHERE (:s

我需要找到createdate>X的所有记录。X是一个sql.Timestamp,可能为null,在这种情况下,我只想返回所有记录。所以我试着:(createdAfter是时间戳)

但我得到的只是

org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $1
但是,如果在检查任意int是否为null时执行相同的查询:

SELECT * 
FROM trades 
WHERE (:sInt ISNULL OR trades.insert_time > :createdAfter ) 

然后它就起作用了。怎么了

如果您想坚持使用这样的本机查询,没有简单的解决方案。
null
值被转换为
bytea
值。参见示例和

该值很难铸造或与
时间戳
值进行比较

问题不在于第一次比较,而是通过使用coalesce来处理,如:

COALESCE(:createdAfter) ISNULL
因为在实际值和数据类型之间没有比较关系。但是比较

sometimestamp::timestamp>null::bytea
(强制转换只是为了显示实际的类型,因此不起作用)

在过程和异常处理之后可能需要更多的逻辑,不确定

因此,如果JPQL或CriteriaQueries不可能,您只有不好的选项:

  • 通过字符串连接或其他方式设置参数来构造查询(不!也不确定realy是否有效)
  • 使用
    PreparedStatement
    查询,更多代码和工作
  • 如果使用Hibernate,也可以使用会话api,如

您可以尝试使用返回文本字符串的
pg_typeof
函数,并使用
CASE
语句强制进行比较(否则无法保证postgres将以正确的顺序短路OR)。然后,您可以通过转换为文本,然后再转换回时间戳来强制进行正确的转换,这虽然不雅观,但应该是有效的

SELECT *
FROM sample AS s
WHERE s.isActive
  AND 
    CASE WHEN pg_typeof( :createdAfter ) = 'bytea' THEN TRUE
       WHEN s.insert_time > ( ( :createdAfter )::text)::timestamp THEN TRUE
       ELSE FALSE 
    END
SELECT *
FROM sample AS s
WHERE s.isActive
  AND 
    CASE WHEN pg_typeof( :createdAfter ) = 'bytea' THEN TRUE
       WHEN s.insert_time > ( ( :createdAfter )::text)::timestamp THEN TRUE
       ELSE FALSE 
    END