Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate Spring数据休息:";日期为空”;查询引发postgres异常_Hibernate_Postgresql_Jpa_Spring Data_Spring Data Rest - Fatal编程技术网

Hibernate Spring数据休息:";日期为空”;查询引发postgres异常

Hibernate Spring数据休息:";日期为空”;查询引发postgres异常,hibernate,postgresql,jpa,spring-data,spring-data-rest,Hibernate,Postgresql,Jpa,Spring Data,Spring Data Rest,我使用SpringBoot和DataREST在Java8中创建了一个简单的微服务,并获得了一个postgres异常 我的实体: @Entity public class ArchivedInvoice implements Serializable { ... @Column private String invoiceNumber; @Column private java.sql.Date invoiceDate; ... } 我的存储库界面

我使用SpringBoot和DataREST在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);
    ...
}

但当我删除“:invoiceDate IS NULL”部分时,它就可以工作了。如何检查invoiceDate参数是否为null?

当您将JPA与Postgres一起使用时,如果您想在稍后检查所需条件之前检查参数是否为null,则会出现一种奇怪的行为,这将导致错误

发生此错误的原因是,在读取查询时,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)" 
    )

我相信@Bonifacio是正确的,因为在执行
为空测试时,Postgres无法确定
@Param(“invoiceDate”)
参数的类型。我有一些类似于您的查询,它们在内存H2数据库中的行为与预期相同,但在Postgres集成测试中失败

我可以通过将参数转换为如下日期来绕过此问题:

@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)" 
    )

在Postgres9.5中,我对LocalDateTime类型的字段和FieldTimestamp也有类似的问题。 我是这样解决的:

    @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);
@Query(“选择c”
+“来自合同c”
+“哪里”
+“(:idContract为NULL或c.idContract=:idContract)和”
+“(强制转换(:dtCancelInitial为java.time.LocalDateTime)为NULL或(c.dtCancel>=:dtCancelInitial和c.dtCancel<:dtCancelFinal))”
+“c.IDC合同订单”)
列出FindContractConsultacanceLamento(@Param(“idContract”)Long idContract、@Param(“dtCancelInitial”)LocalDateTime dtCancelInitial、@Param(“dtCancelFinal”)LocalDateTime dtCancelFinal);

我花了一些时间研究这个问题,因为我真的想比较querys中的“dateisnull”,结果如下:

当您使用“强制转换(foo.date as date)为null”时,如果该字段不为null,则可以正常工作。如果字段为空,则抛出此异常:

org.postgresql.util.PSQLException: ERROR: cannot cast type bytea to date
解决方案是使用聚结:

coalesce(:date, null) is null
无论是否有现场测试数据,它都可以正常工作

我的查询示例:

@Query("SELECT c "
        + " FROM Entity c "
        + " WHERE "
        + "       and ( (coalesce(:dateFrom, null) is null and coalesce(:dateUntil, null) is null) "
        + "             or ((coalesce(c.date, null) is not null) "
        + "                 and ( "
        + "                        ((coalesce(:dateFrom, null) is null and coalesce(:dateUntil, null) is not null) and c.date <= :dateUntil) "
        + "                     or ((coalesce(:dateUntil, null) is null and coalesce(:dateFrom, null) is not null) and c.date >= :dateFrom)"
        + "                     or (c.date between :dateFrom and :dateUntil)"
        + "                 )"
        + "             )"
        + "       ) "
@Query(“选择c”
+“来自实体c”
+“哪里”
+and((coalesce(:dateFrom,null)为null,coalesce(:dateUntil,null)为null)
+或((合并(c.date,null)不为null)
+“和(”
+((coalesce(:dateFrom,null)为null,coalesce(:dateUntil,null)不为null)和c.date=:dateFrom)
+“或(c.日期介于:dateFrom和:dateUntil之间)”
+ "                 )"
+ "             )"
+ "       ) "

希望它对您有用!

您可以试试这个,不幸的是,它不起作用。但这是一个好主意!Thx!这对我来说适用于查询中的第一个日期参数,而不是发送日期参数。我在查询中有两个日期参数。它抱怨第二个日期参数相同。对于其他感兴趣的人,UUID的强制类型是“binary”而不是“other”或“varchar”这是对这个解决方案的一种解释:这似乎并没有回答这个问题。这个问题并没有提到
Contract
的表名。它可能没有回答这个问题,但它给了我很大的帮助,它显示了您也可以转换为Java类型,而我以前无法转换UUID(即使在另一个答案的评论中提到了“二进制”,我也喜欢coalesce解决方案;它比casting要短一些。
@Query("SELECT c "
        + " FROM Entity c "
        + " WHERE "
        + "       and ( (coalesce(:dateFrom, null) is null and coalesce(:dateUntil, null) is null) "
        + "             or ((coalesce(c.date, null) is not null) "
        + "                 and ( "
        + "                        ((coalesce(:dateFrom, null) is null and coalesce(:dateUntil, null) is not null) and c.date <= :dateUntil) "
        + "                     or ((coalesce(:dateUntil, null) is null and coalesce(:dateFrom, null) is not null) and c.date >= :dateFrom)"
        + "                     or (c.date between :dateFrom and :dateUntil)"
        + "                 )"
        + "             )"
        + "       ) "