【问题标题】:How to exclude the where condition from the native query when the parameter is null当参数为空时如何从本机查询中排除 where 条件
【发布时间】:2022-01-26 11:20:48
【问题描述】:

我正在为我的应用程序使用 spring boot v2.6.1 和 Postgres DB。我的一个存储库中有以下方法。

@Query(value = "SELECT * from subscriptions s " +
            "WHERE (:merchantID is NULL OR s.created_by = cast(:merchantID AS text)) " +
            "AND (:status is NULL or s.status IN (:status))", nativeQuery = true)
    List<Subscription> findWithStatus (@Param("merchantID")String merchantID, @Param("status") List<String> status);

当参数'status'不为空时,它工作正常。但是当它为 null 时会抛出异常

org.postgresql.util.PSQLException:错误:运算符不存在:字符变化 = bytea

据此,我了解到即使指定参数为空,该条件也不会从查询中排除。我认为问题是检查 :status is null 中的参数是否为空,所以我只是将列表参数更改为 String 并传递了一个空值,仍然是抛出相同的异常。所以问题不在于 :status is null 而是查询中的 IN 运算符。

当参数为null时,如何用IN运算符排除这个条件?

【问题讨论】:

  • 提供两种方法,让调用者自己决定。
  • 为了简单的问题陈述,我减少了参数的数量并在这里发布。实际上,我有三个 List 类型的参数。所以在这种情况下我需要有两种以上的方法,这不会很好
  • “看起来不好”?您实际上提供了一个名为 findWithStatus 的方法,但您想省略状态。这意味着该方法的全部含义发生了变化。所以……提供几种方法!只有一种行为不同的方法……这对我来说并不好。
  • 尝试使用s.status = ANY(:status) 而不是s.status IN (:status),它应该可以工作。如果它有效,我会写一个更详细的答案来说明它为什么有效:)
  • @Seelenvirtuose 如果过滤器仅按状态,我会这样做。我的实际方法名为 findWithFilter ,它有五个参数,五个中三个是列表类型,五个中只有一个参数不为空,其余四个可以为空。

标签: java spring spring-boot jpa spring-data-jpa


【解决方案1】:

如果您想使用这种原生查询近似值,一种解决方案是添加一个额外的布尔参数,指示状态列表是否为空。

@Query(value = "SELECT * from subscriptions s " +
            "WHERE (:merchantID is NULL OR s.created_by = cast(:merchantID AS text)) " +
            "AND (:statusIsNull or s.status IN (:status))", nativeQuery = true)
    List<Subscription> findWithStatus (@Param("merchantID")String merchantID, @Param("statusIsNull") Boolean statusIsNull, @Param("status") List<String> status);

所以函数调用应该是这样的:

Boolean statusIsNull = (statusList == null || statusList.isEmpty()) ? true : false;

List<Subscription> subscriptionList = findWithStatus (merchantID, statusIsNull, statusList);

但我真的建议使用 JPA Criteria API 来构建动态查询。

问候。

【讨论】:

  • 您实际上并不需要单独的变量,因为您可以在查询本身中做出选择。将"AND (:status is NULL or s.status IN (:status))", nativeQuery = true) 适配为"AND (CASE WHEN :status is NULL THEN true ELSE s.status IN (:status) END;)", nativeQuery = true)
  • 是的!两种解决方案都运行良好。
  • 非常感谢您的宝贵时间
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-18
  • 2015-12-31
  • 1970-01-01
  • 1970-01-01
  • 2020-12-28
相关资源
最近更新 更多