java 中的 Postgres 重叠符号不是 运行

Postgres overlapping symbol not running in java

我有一个查询要针对 table 中的两个时间戳列测试两个日期是否重叠。 查询在数据库客户端中运行良好,但是当我将它添加到我的 java 代码中时,它因异常错误而失败。 我需要知道如何格式化查询中的 && 符号才能正常工作。

SELECT count(*) 
FROM attendance_jobs 
WHERE tsrange( start_date, end_date) && tsrange(TIMESTAMP '2019-04-22', TIMESTAMP '2019-03-22 ')

这是我的 java 代码:

long count = jdbi.withHandle(handle -> {
            return handle.createQuery("select count(*) from attendance_jobs where tsrange(start_date, end_date) && tsrange(timestamp :start_date, timestamp :end_date)")
                .bind("start_date", start_date)
                .bind("end_date", end_date)
                .mapTo(Long.class)
                    .findOnly();
        });

start_dateend_date 数据类型是时间戳。

org.jdbi.v3.core.statement.UnableToExecuteStatementException: org.postgresql.util.PSQLException: ERROR: syntax error at or near ""

这只是猜测,但我认为您应该看看 :start_date:end_date 的用法 再次:

如果start_dateend_date(java变量)是时间戳类型应该删除 timestamp 前缀到 :start_date:end_date查询。正如documentation所说,jdbi支持java类型Timestamp

Out of the box, Jdbi supports the following types as SQL statement arguments:
* ...
* java.sql: Blob, Clob, Date, Time, and Timestamp
* ...

所以我猜你必须使用这样的查询:

long count = jdbi.withHandle(handle -> {
        return handle.createQuery("select count(*) from attendance_jobs where tsrange(start_date, end_date) && tsrange(:start_date, :end_date)")
            .bind("start_date", start_date)
            .bind("end_date", end_date)
            .mapTo(Long.class)
                .findOnly();
    });

此外,但这可能是个人口味,我建议对绑定变量和数据库列使用不同的拼写。后者带有下划线(就像你所做的那样),另一个是驼峰式,所以如果你使用相似的名字就不会那么混乱。此外,在 java 变量中使用下划线并不常见,因此代码在我的拼写中看起来类似于:

Timestamp startDate = ...;
Timestamp endDate = ...;
String queryString = "select count(*) from attendance_jobs "
        + "where tsrange(start_date, end_date) && tsrange(:startDate, :endDate)";
long count = jdbi.withHandle(handle -> {
        return handle.createQuery(queryString)
            .bind("startDate", startDate)
            .bind("endDate", endDate)
            .mapTo(Long.class)
            .findOnly();
    });