使用@Query JPA批注将null参数传递给本机查询

时间:2017-03-15 14:38:15

标签: postgresql hibernate jpa spring-boot

在Spring Boot应用程序中,我有一个在postgresql服务器上执行的SQL查询,如下所示:

@Query(value = "select count(*) from servers where brand= coalesce(?1, brand) " +
        "and flavour= coalesce(?2, flavour) ; ",
        nativeQuery = true)
Integer icecreamStockCount(String country, String category);

然而,

执行方法时出现以下错误:

ERROR: COALESCE types bytea and character varying in PostgreSQL

如何将String value = null传递给查询?

**注意:**我发现我的问题与JPA Query to handle NULL parameter value

不同

4 个答案:

答案 0 :(得分:4)

你不需要合并,试试这个

@Query("select count(*) from servers where (brand = ?1 or ?1 is null)" +
        " and (flavour = ?2 or ?2 is null)")
Integer icecreamStockCount(String country, String category);

答案 1 :(得分:1)

如果您确实需要使用本地查询,则存在问题,因为尚未实现改进,请参见hibernate。如果您不需要使用母语,则可以执行(where ?1 is null or field like ?1)。假设您确实需要本地, 您可以先将String设置为空,然后调用存储库,然后再处理String,这就像:

@Query(value = "select count(*) from servers where (?1 like '' or brand like ?1) " +
    "and (?2 like '' or flavour like ?2)",
    nativeQuery = true)
Integer icecreamStockCount(String country, String category);

对于本机查询情况,总是有javax.persistence.EntityManager bean作为选项,我建议使用它代替以前的方法。在这里,您可以按自己的方式将查询附加到查询中,如下所示:

String queryString = "select count(*) from servers ";
if (!isNull(country)) queryString += "where brand like :country";
Query query = entityManager.createNativeQuery(queryString);
if (!isNull(country)) query.setParameter("country", country);
return query.getResultList();

观察:

  1. 较新的版本改进了此“ +”串联字符串。但是,您可以使用StringBuilder或String Format随意构建自己的queryString,这没关系。
  2. 在使用SQL注入时要小心,setParameter方法避免这种问题,有关更多信息,请参见此Sql Injection Baeldung

答案 2 :(得分:1)

遇到此错误时,我最终使用ORCAST的组合来解决此问题。

SELECT COUNT(*)
FROM servers
WHERE (?1 IS NULL OR brand = CAST(?1 AS CHARACTER VARYING))
AND (?2 IS NULL OR flavour = CAST(?2 AS CHARACTER VARYING))

即使?1?2brandflavor都是可为空的字段,此方法仍然有效。

请注意,为null传递?1的意思是“所有服务器,不论品牌如何”,而不是“所有没有品牌的服务器”。对于后者,您可以按以下方式使用IS DISTINCT FROM

SELECT COUNT(*)
FROM servers
WHERE (CAST(?1 AS CHARACTER VARYING) IS NOT DISTINCT FROM brand)
AND (CAST(?2 AS CHARACTER VARYING) IS NOT DISTINCT FROM flavour)

最后,无法在SQL中将某些参数类型(例如BooleanBYTEA强制转换为BOOLEAN,在这种情况下,您需要进行两次强制转换:

SELECT COUNT(*)
FROM servers
WHERE (?1 IS NULL OR is_black = CAST(CAST(?1 AS CHARACTER VARYING) AS BOOLEAN))

在我眼中,这是Hibernate中的一个问题,可以通过将Java null参数作为纯SQL NULL传递而不是将null解释为类型{{1 }}。

答案 3 :(得分:0)