Spring Data Rest:“Date为null”查询抛出postgres异常

时间:2016-02-23 07:46:43

标签: hibernate postgresql jpa spring-data spring-data-rest

我使用Spring Boot和Data Rest在Java8中创建一个简单的微服务并获得postgres异常。

我的实体:

@Entity
public class ArchivedInvoice implements Serializable {
    ...
    @Column
    private String invoiceNumber;
    @Column
    private java.sql.Date invoiceDate;
    ...
}

我的存储库界面:

@RepositoryRestResource(collectionResourceRel = "archivedinvoices", path = "archivedinvoices")
public interface ArchivedInvoiceRepository extends PagingAndSortingRepository < ArchivedInvoice, Long > {
    ...
@RestResource(rel = "findByXYZ", path = "findByXYZ")
@Query(value = "SELECT ai FROM #{#entityName} ai WHERE "
        + "(:invoiceNumber IS NULL OR ai.invoiceNumber LIKE :invoiceNumber) AND "
        + "(:invoiceDate IS NULL OR ai.invoiceDate = :invoiceDate)" 
        )
public Page < ArchivedInvoice > findByXYZ(
        @Param("invoiceNumber") @Nullable String invoiceNumber,
        @Param("invoiceDate") @Nullable Date invoiceDate,
        Pageable p);
    ...
}

如果我打电话给“... / findByXYZ?invoiceDate = 2016-02-22”,我会收到以下错误消息:

org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
...
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
...
Caused by: org.postgresql.util.PSQLException: FEHLER: could not determine data type of parameter

但它有效,当我删除“:invoiceDate IS NULL”部分时。如果invoiceDate参数为null,我该如何检查?

4 个答案:

答案 0 :(得分:2)

I believe @Bonifacio is correct in that Postgres is not able to determine the type of your @Param("invoiceDate") parameter when performing the IS NULL test. I have queries similar to yours that behave as expected with an in memory H2 database, but fail with the Postgres integration tests.

I was able to get around this by casting the parameter to a date like so:

@Query(value = "SELECT ai FROM #{#entityName} ai WHERE "
    + "(:invoiceNumber IS NULL OR ai.invoiceNumber LIKE :invoiceNumber) AND "
    + "(cast(:invoiceDate as date) IS NULL OR ai.invoiceDate = :invoiceDate)" 
    )

答案 1 :(得分:1)

我在postgres 9.5中遇到类型为LocalDateTime的字段和字段Timestamp的类似问题。 我解决了它像这样转换它:

    @Query("SELECT c "
        + "FROM Contract c "
        + "WHERE "
        + "(:idContract IS NULL OR c.idContract = :idContract) AND "
        + "(CAST(:dtCancelInitial AS java.time.LocalDateTime) IS NULL OR (c.dtCancel >= :dtCancelInitial AND c.dtCancel < :dtCancelFinal)) "
        + "ORDER BY c.idContract")
List<Contract> findContratConsultaCancelamento(@Param("idContract") Long idContract, @Param("dtCancelInitial") LocalDateTime dtCancelInitial, @Param("dtCancelFinal") LocalDateTime dtCancelFinal);

答案 2 :(得分:0)

当你使用JPA和Postgres时,有一种奇怪的行为,当你想在以后检查所需的条件之前检查参数是否为空时会导致错误。

发生错误是因为在阅读查询时,JPA无法识别参数类型是什么,然后在解释查询时引发错误。

它的变通方法是切换参数条件的位置,首先检查所需条件是否为真,然后检查参数是否为空。

这样,JPA将能够识别正确的参数类型,并且不应再次引发错误。

尝试以下查询,看看它是否有效:

@Query(value = "SELECT ai FROM #{#entityName} ai WHERE "
    + "(:invoiceNumber IS NULL OR ai.invoiceNumber LIKE :invoiceNumber) AND "
    + "(ai.invoiceDate = :invoiceDate OR :invoiceDate IS NULL)" 
    )

答案 3 :(得分:0)

我花了一些时间研究这个问题,因为我真的很想在查询中比较“日期为空”,这就是结果:

当您使用“ cast(foo.date作为日期)为空”时,如果该字段不为空,则工作正常。如果该字段为null,则抛出此异常:

body-parser

解决方案是使用合并:

org.postgresql.util.PSQLException: ERROR: cannot cast type bytea to date

在测试现场是否有数据都可以正常工作。

我的查询示例:

coalesce(:date, null) is null

希望它对您有用!