JPA where子句any

17

JPA中的查询语句是:

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

如何在JPA中将类别设置为任意类别?如果传递了null类别,则只需忽略类别参数,选择所有产品。


这个指南提供了一些使用Criteria以及其他更硬编码的替代方案的示例。https://www.tutorialspoint.com/hibernate/hibernate_quick_guide.htm - Andrei-Niculae Petre
7个回答

19

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

您需要在此处动态构建查询。使用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();

处理复杂动态查询时要简单得多。


1
Criteria是动态查询的更好解决方案。Expression.eq已经被弃用了,相反你可以使用Restrictions.eq。 - Gere
这个指南提供了一些使用Criteria以及其他更硬编码的替代方案的示例。https://www.tutorialspoint.com/hibernate/hibernate_quick_guide.htm - Andrei-Niculae Petre

4
为了使参数变得可选,您可以编写一个查询而不必使用Criteria API:
select o from Product o WHERE :value is null or :value='' or o.category = :value

你好,我想知道是否可以使用类似于这篇帖子中的查询(https://dev59.com/nnRB5IYBdhLWcg3wn4YL)来对集合进行评估。所以,我的项目中以下查询不起作用: FROM Foo WHERE Id = :id AND (:barlist is null or Bar in (:barlist)) - André Luís Tomaz Dionisio

2

你的说法基本正确,只需要稍作修改。

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

在 setParameter 方法中,"value"(确切文本)应该和查询语句中的 ":value" 匹配。


1
我怎样在JPA中将类别设为任意类别?所以如果传递了null类别,我会简单地忽略类别参数,选择所有产品。
您可以将类别设置为“%”。 if (category == null) query.setParameter("category", "%"); else query.setParameter("category", category);

0

SELECT * FROM PRODUCT WHERE CATEGORY=*

我想你也是SQL新手。

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

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


抱歉,SQL查询有误:)你的解决方案“WHERE CATEGORY IS NOT NULL”很好,但我必须创建另一个查询。是否还有其他方法可以节省一个查询? - Ke.

0
你正在尝试实现的东西在设计模式方面是相反直觉的。让我们忽略所有 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,否则没有标准的方法来实现这种行为。

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


0

Pascal Thivent提供了相当不错的答案,建议使用Criteria。但是他在答案中提到的Criteria是纯粹的Hibernate Criteria。使用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();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接