JDBI/Postgress Select 日期时间比较查询失败
JDBI/Postgress Select query failed with datetime comparison
后处理版本:10.4
table 列 name/type: updated_at timestamp(6) with time zone
SQL查询:
final String SELECT_PAYMENT_INFO_QUERY =
"SELECT i.code, p.*
FROM information i
INNER JOIN product p ON i.ref = p.information_ref
WHERE p.reference = :reference AND p.type = :paymentMethodType AND p.error_state = :errorState
AND p.updated_at IS NOT NULL AND p.updated_at >= :queryFromTime
ORDER BY p.updated_at ASC
FETCH FIRST :numberOfRows ROWS ONLY"
Java方法:
public List<ProductInformationDTO> retrieveProductInformations(
ZonedDateTime fetchFromTime, int noOfRecords)
{
try
{
return dbi.inTransaction((HandleCallback<List<ProductInformationDTO>, Exception>) handle ->
{
final List<ProductInformationDTO> productInfos = handle.createQuery(SELECT_PAYMENT_INFO_QUERY)
.bind("reference", "ABCD")
.bind("paymentMethodType", "CREDIT_CARD")
.bind("errorState", "COMPLETED_WITH_ERRORS")
.bind("queryFromTime", fetchFromTime.toOffsetDateTime())
.bind("numberOfRows", noOfRecords)
.map(productInfoMapper)
.list();
return productInfos;
});
}
catch (Exception e)
{
LOG.error("Failed to complete the retrieve operation.", e);
throw new TransactionException(e);
}
}
此查询和方法适用于 H2 数据库。但是,当使用 Postgress 数据库进行测试时,出现以下异常
org.jdbi.v3.core.statement.UnableToExecuteStatementException: org.postgresql.util.PSQLException: ERROR: syntax error at or near ""
Position: 234 [statement:"SELECT i.code, p.* FROM information i INNER JOIN product p ON i.ref = p.information_ref WHERE p.reference = :reference AND p.type = :paymentMethodType AND p.error_state = :errorState AND p.updated_at IS NOT NULL AND p.updated_at >= :queryFromTime ORDER BY p.updated_at ASC FETCH FIRST :numberOfRows ROWS ONLY", arguments:{positional:{}, named:{queryFromTime:2021-04-15T16:28:20.365795+12:00,numberOfRows:10,paymentMethodType:CREDIT_CARD,reference:ABCD,errorState:COMPLETED_WITH_ERRORS}, finder:[]}]
at org.jdbi.v3.core.statement.SqlStatement.internalExecute(SqlStatement.java:1794)
at org.jdbi.v3.core.result.ResultProducers.lambda$getResultSet(ResultProducers.java:64)
at org.jdbi.v3.core.result.ResultIterable.lambda$of[=14=](ResultIterable.java:54)
at org.jdbi.v3.core.result.ResultIterable.stream(ResultIterable.java:228)
at org.jdbi.v3.core.result.ResultIterable.collect(ResultIterable.java:284)
at org.jdbi.v3.core.result.ResultIterable.list(ResultIterable.java:273)
at au.com.abcd.products.v2.database.store.dao.ProductsDaoImpl.lambda$retrieveProductInformations(ProductsDaoImpl.java:260)
at org.jdbi.v3.core.Handle.inTransaction(Handle.java:424)
at org.jdbi.v3.core.Jdbi.lambda$inTransaction(Jdbi.java:375)
at org.jdbi.v3.core.Jdbi.withHandle(Jdbi.java:341)
at org.jdbi.v3.core.Jdbi.inTransaction(Jdbi.java:375)
at au.com.abcd.products.v2.database.store.dao.ProductsDaoImpl.retrievePaymentIntents(IntentDaoImpl.java:251)
at au.com.abcd.products.v2.business.services.complete.ProductServiceImpl.reProcessProducts(ProductServiceImpl.java:114)
at au.com.abcd.products.v2.business.background.TransactionReProcessManager.lambda$reProcessProducts(TransactionReProcessManager.java:81)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near ""
Position: 234
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2532)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2267)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:312)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:448)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:369)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:153)
at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:142)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:114)
at com.sun.proxy.$Proxy120.execute(Unknown Source)
at org.jdbi.v3.core.statement.SqlLoggerUtil.wrap(SqlLoggerUtil.java:31)
at org.jdbi.v3.core.statement.SqlStatement.internalExecute(SqlStatement.java:1786)
... 16 common frames omitted
我也尝试使用 fetchFromTime.toLocalDateTime() 但得到了同样的异常。
您不能在 FETCH FIRST
(或 LIMIT
)子句中使用位置参数。假设您可以容忍 运行 本机查询,一种解决方法是改用 ROW_NUMBER
:
SELECT *
FROM
(
SELECT i.code, p.*, ROW_NUMBER() OVER (ORDER BY p.updated_at) rn
FROM information i
INNER JOIN product p ON i.ref = p.information_ref
WHERE p.reference = :reference AND p.type = :paymentMethodType AND
p.error_state = :errorState AND p.updated_at IS NOT NULL AND
p.updated_at >= :queryFromTime
) t
WHERE rn <= :numberOfRows
后处理版本:10.4
table 列 name/type: updated_at timestamp(6) with time zone
SQL查询:
final String SELECT_PAYMENT_INFO_QUERY =
"SELECT i.code, p.*
FROM information i
INNER JOIN product p ON i.ref = p.information_ref
WHERE p.reference = :reference AND p.type = :paymentMethodType AND p.error_state = :errorState
AND p.updated_at IS NOT NULL AND p.updated_at >= :queryFromTime
ORDER BY p.updated_at ASC
FETCH FIRST :numberOfRows ROWS ONLY"
Java方法:
public List<ProductInformationDTO> retrieveProductInformations(
ZonedDateTime fetchFromTime, int noOfRecords)
{
try
{
return dbi.inTransaction((HandleCallback<List<ProductInformationDTO>, Exception>) handle ->
{
final List<ProductInformationDTO> productInfos = handle.createQuery(SELECT_PAYMENT_INFO_QUERY)
.bind("reference", "ABCD")
.bind("paymentMethodType", "CREDIT_CARD")
.bind("errorState", "COMPLETED_WITH_ERRORS")
.bind("queryFromTime", fetchFromTime.toOffsetDateTime())
.bind("numberOfRows", noOfRecords)
.map(productInfoMapper)
.list();
return productInfos;
});
}
catch (Exception e)
{
LOG.error("Failed to complete the retrieve operation.", e);
throw new TransactionException(e);
}
}
此查询和方法适用于 H2 数据库。但是,当使用 Postgress 数据库进行测试时,出现以下异常
org.jdbi.v3.core.statement.UnableToExecuteStatementException: org.postgresql.util.PSQLException: ERROR: syntax error at or near "" Position: 234 [statement:"SELECT i.code, p.* FROM information i INNER JOIN product p ON i.ref = p.information_ref WHERE p.reference = :reference AND p.type = :paymentMethodType AND p.error_state = :errorState AND p.updated_at IS NOT NULL AND p.updated_at >= :queryFromTime ORDER BY p.updated_at ASC FETCH FIRST :numberOfRows ROWS ONLY", arguments:{positional:{}, named:{queryFromTime:2021-04-15T16:28:20.365795+12:00,numberOfRows:10,paymentMethodType:CREDIT_CARD,reference:ABCD,errorState:COMPLETED_WITH_ERRORS}, finder:[]}] at org.jdbi.v3.core.statement.SqlStatement.internalExecute(SqlStatement.java:1794) at org.jdbi.v3.core.result.ResultProducers.lambda$getResultSet(ResultProducers.java:64) at org.jdbi.v3.core.result.ResultIterable.lambda$of[=14=](ResultIterable.java:54) at org.jdbi.v3.core.result.ResultIterable.stream(ResultIterable.java:228) at org.jdbi.v3.core.result.ResultIterable.collect(ResultIterable.java:284) at org.jdbi.v3.core.result.ResultIterable.list(ResultIterable.java:273) at au.com.abcd.products.v2.database.store.dao.ProductsDaoImpl.lambda$retrieveProductInformations(ProductsDaoImpl.java:260) at org.jdbi.v3.core.Handle.inTransaction(Handle.java:424) at org.jdbi.v3.core.Jdbi.lambda$inTransaction(Jdbi.java:375) at org.jdbi.v3.core.Jdbi.withHandle(Jdbi.java:341) at org.jdbi.v3.core.Jdbi.inTransaction(Jdbi.java:375) at au.com.abcd.products.v2.database.store.dao.ProductsDaoImpl.retrievePaymentIntents(IntentDaoImpl.java:251) at au.com.abcd.products.v2.business.services.complete.ProductServiceImpl.reProcessProducts(ProductServiceImpl.java:114) at au.com.abcd.products.v2.business.background.TransactionReProcessManager.lambda$reProcessProducts(TransactionReProcessManager.java:81) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829) Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near "" Position: 234 at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2532) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2267) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:312) at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:448) at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:369) at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:153) at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:142) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:114) at com.sun.proxy.$Proxy120.execute(Unknown Source) at org.jdbi.v3.core.statement.SqlLoggerUtil.wrap(SqlLoggerUtil.java:31) at org.jdbi.v3.core.statement.SqlStatement.internalExecute(SqlStatement.java:1786) ... 16 common frames omitted
我也尝试使用 fetchFromTime.toLocalDateTime() 但得到了同样的异常。
您不能在 FETCH FIRST
(或 LIMIT
)子句中使用位置参数。假设您可以容忍 运行 本机查询,一种解决方法是改用 ROW_NUMBER
:
SELECT *
FROM
(
SELECT i.code, p.*, ROW_NUMBER() OVER (ORDER BY p.updated_at) rn
FROM information i
INNER JOIN product p ON i.ref = p.information_ref
WHERE p.reference = :reference AND p.type = :paymentMethodType AND
p.error_state = :errorState AND p.updated_at IS NOT NULL AND
p.updated_at >= :queryFromTime
) t
WHERE rn <= :numberOfRows