【问题标题】:JPA where clause anyJPA where 子句
【发布时间】:2011-01-27 01:56:18
【问题描述】:

在 JPA 中,查询是:

Query q = entityManager.createQuery("select o from Product o WHERE o.category = :value");
q.setParameter("category", category);

如何在 JPA 中将类别设置为任何类别?所以如果传递了空类别,我简单地忽略类别参数,选择所有产品。

【问题讨论】:

标签: java jpa


【解决方案1】:

如何在 JPA 中将类别设置为任何类别?所以如果传递了空类别,我简单地忽略类别参数,选择所有产品。

您必须在此处动态构建查询。使用 HQL(这是一个简化的示例):

Map<String, Object> params = new HashMap<String, Object>();
StringBuffer hql = new StringBuffer("from Product p");
boolean first = true;

if (category != null) {
    hql.append(first ? " where " : " and ");
    hql.append("p.category = :category");
    params.put("category", category);
}

// And so on...

Query query = session.createQuery(hql.toString());

Iterator<String> iter = params.keySet().iterator();
while (iter.hasNext()) {
    String name = iter.next();
    Object value = params.get(name);
    query.setParameter(name, value);
}

List results = query.list()

但实际上,我的建议是在这里使用 Criteria API:

Criteria criteria = session.createCriteria(Product.class);
if (category != null) {
    criteria.add(Expression.eq("category", category);
}
// And so on...
List results = criteria.list();

复杂的动态查询要简单得多。

【讨论】:

【解决方案2】:

要归档参数成为可选参数,您可以编写查询而无需使用 Criteria API:

select o from Product o WHERE :value is null or :value='' or o.category = :value

【讨论】:

  • 您好,我想知道是否可以使用来自这篇文章stackoverflow.com/questions/570229/… 的查询等集合进行这种评估。所以这个查询在我的项目中不起作用如下: FROM Foo WHERE Id = :id AND (:barlist is null or Bar in (:barlist))
【解决方案3】:

你几乎是对的。

Query query = entityManager.createQuery("select o from Product o WHERE o.category = :value");
query.setParameter("value", category);

在 setParamater 中 "value"(精确文本)应与查询中的 ":value" 匹配。

【讨论】:

    【解决方案4】:

    如何在 JPA 中将类别设置为任何类别?所以如果空类别 通过了,我简单地忽略category参数,选择所有产品。

    您可以将类别设置为“%”。 if (category == null) query.setParameter("category", "%"); else query.setParameter("category", category);

    【讨论】:

      【解决方案5】:

      从 CATEGORY=* 的产品中选择 *

      我认为您也是 SQL 新手。

      WHERE CATEGORY = * 并不意味着“任何类别”(它甚至不是有效的 SQL)。

      在 SQL 和 JPA 中,如果你想要任何类别,你根本就没有 WHERE 子句(或者在 SQL 中你可以有 WHERE CATEGORY IS NOT NULL)。

      【讨论】:

      • 抱歉错误的 SQL 查询:) 您的解决方案“WHERE CATEGORY IS NOT NULL”很好,但我必须创建另一个查询。有没有其他方法可以保存一个查询?
      【解决方案6】:

      Pascal Thivent 给了很好的answer 推荐使用Criteria。然而,他的回答中的Criteria 是纯粹的Hibernate 标准。以JPA Criteria 为例:

      private List<Result> getProduct(String category) {
          CriteriaBuilder builder = entityManager.getCriteriaBuilder();
          CriteriaQuery<Product> criteria = builder.createQuery(Product.class);
          Root<Product> productRoot = criteria.from(Product.class);
      
          if (category != null)
              criteria.where(builder.equal(productRoot.get("category"), category))    
          }
      
          entityManager.createQuery(criteria).getResultList();
      }
      

      【讨论】:

        【解决方案7】:

        就设计模式而言,您试图实现的目标是违反直觉的。让我们考虑一下忽略所有 JPA 和其他的 SQL 术语中的问题。

        您的 JPQL 对应的 SQL 查询如下所示

        SELECT o.* FROM product o WHERE o.category = 'SOME_CAT';
        

        现在,如果您传递 null 而不是类别 SOME_CAT,SQL 将是这样的

        SELECT o.* FROM product o WHERE o.category IS NULL;
        

        没有 SQL 标准可以反转结果集更改参数值,除非您的 SQL 如下所示

        SELECT o.* FROM product o WHERE o.category IS NOT NULL;
        

        相似的 JPQL 看起来像

        SELECT o FROM Product o WHERE o.category <> :param
        

        您可以看到我们需要反转逻辑操作而不是操作参数。除非您使用 if else 条件动态构建 JPQL,否则没有实现此行为的标准方法。

        我更喜欢一个单独的方法处理程序,一个用于过滤类别,另一个用于列出所有类别而不管类别。

        【讨论】:

          猜你喜欢
          • 2011-06-25
          • 1970-01-01
          • 1970-01-01
          • 2015-01-30
          • 1970-01-01
          • 2012-01-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多