【问题标题】:How to send empty list to IN clause如何将空列表发送到 IN 子句
【发布时间】:2020-01-16 19:23:50
【问题描述】:

我想使用这个 SQL 查询:

String hql = "select e from " + Terminals.class.getName() + " e WHERE e.merchantId IN :merchant_ids";
        TypedQuery<Terminals> query = entityManager.createQuery(hql, Terminals.class).setParameter("merchant_ids", merchant_ids);
        List<Terminals> merchants = query.getResultList();

但我得到错误:the right syntax to use near ') 所以IN (....) 中的 IN 子句列表不能为空。这个问题有解决办法吗?

【问题讨论】:

  • 我在链接中找不到解决方案。如您所见,我的代码中没有(...)
  • 当您有一个空列表并且您正在寻找该列表中的内容时,您真的期望得到结果吗?这样的查询一定会失败。事实上,您的代码让您寻找 ID,如果搜索列表中没有,那么结果中应该没有。你在做什么我的家伙?
  • 在我的情况下,当列表 Merchant_ids 为空时,我不需要从终端表中获取结果。一般的想法是我正在寻找与分配的商家 ID 匹配的终端
  • 想一想,如果您正在搜索空列表中的内容,您将获得空结果或所有结果,因此行为未定义,因此出现错误。如何处理空列表是您必须自己弄清楚并决定的实现细节。

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


【解决方案1】:

我不熟悉hibernate,但由于它是一个SQL错误,以下应该可以工作:

TypedQuery<Terminals> query = entityManager
.createQuery(hql, Terminals.class)
.setParameter("merchant_ids",merchant_ids.size()==0?null:merchant_ids);

但正如@Richard Barker 所提到的,最好的解决方案是在列表为空时甚至不执行查询。 当您已经知道查询不会返回任何内容时,您甚至可以节省不必要的数据库调用。

【讨论】:

    【解决方案2】:

    我经常遇到这种情况。我找不到合适的解决方案。由于您使用的是 Spring JPA 但我有一些解决方法可以建议您。

    1. 实现 EntityManger 并在运行时创建 SQL 查询。因此,您可以填充您的位置原因和所有内容。 像这样:entityManager.createNativeQuery(sql.toString())

    2. 实施if-else 块。检查列表是否为空,如果错误则调用实际查询(带 IN 块),否则编写另一个不带 IN 块的查询。

    我再说一遍,这可能不是一个合适的解决方案。但我认为这是正确的解决方法。

    【讨论】:

      【解决方案3】:

      不执行查询是允许的,甚至很好:

      if (merchant_ids.isEmpty()) {
          return new ArrayList<>();
      } else {
          String hql = "select e from " + Terminals.class.getName()
                  + " e WHERE e.merchantId IN :merchant_ids";
         return entityManager.createQuery(hql, Terminals.class)
              .setParameter("merchant_ids", merchant_ids)
              .getResultList();
      }
      

      我不知道如果通过null 而不是一个空列表会发生什么; SQL ... IN NULL 可以。另一方面,它可能会进行全表扫描以返回 0 个结果。

      如果 x IN() 不会产生 0 条记录(当有 OR ... 时),那么:

      if (merchant_ids.isEmpty()) {
          merchant_ids.add(-1);
          String hql = "select e from " + Terminals.class.getName() + ...
      

      【讨论】:

      • hm.... 空参数应该用什么?商家ids.add(0);或merchant_ids.add(-1);?
      • 没有出现的值。按照惯例,ID 号是非零正数,0 也是可能的,因为 java 在 indexOf 和从零开始的索引中使用 -1,我个人倾向于 -1,但数据库列定义可以使用无符号数字或其他,
      【解决方案4】:

      我按照@Rambler 的建议创建了一个返回 null 的方法:

          public static <T> Collection<T> nullIfEmpty(Collection<T> collection) {
              return (collection == null || collection.isEmpty()) ? null : collection;
          }
      

      这更容易就地添加,但我同意最好不要调用数据库。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-23
        • 2011-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多