具有多个参数的JPA Criteria API

我需要创建一个使用带有多个参数的JPA Criteria API的搜索方法。 现在问题是不是每个参数都是必需的。 因此有些可能为null,并且它们不应包含在查询中。 我已经用CriteriaBuilder尝试了这个,但我看不出如何让它工作。

使用Hibernate Criteria API,这非常简单。 只需创建条件,然后添加限制。

Criteria criteria = session.createCriteria(someClass.class); if(someClass.getName() != null) { criteria.add(Restrictions.like("name", someClass.getName()); } 

我怎么能用JPA的Criteria API实现同样的目标?

概念是构造javax.persistence.Predicate数组,它只包含我们想要使用的谓词:

要查询的示例实体:

 @Entity public class A { @Id private Long id; String someAttribute; String someOtherAttribute; ... } 

查询本身:

  //some parameters to your method String param1 = "1"; String paramNull = null; CriteriaBuilder qb = em.getCriteriaBuilder(); CriteriaQuery cq = qb.createQuery(); Root customer = cq.from(A.class); //Constructing list of parameters List predicates = new ArrayList(); //Adding predicates in case of parameter not being null if (param1 != null) { predicates.add( qb.equal(customer.get("someAttribute"), param1)); } if (paramNull != null) { predicates.add( qb.equal(customer.get("someOtherAttribute"), paramNull)); } //query itself cq.select(customer) .where(predicates.toArray(new Predicate[]{})); //execute query and do something with result em.createQuery(cq).getResultList(); 

看看这个网站JPA Criteria API 。 有很多例子。

更新:提供一个具体的例子

让我们搜索余额低于特定值的帐户:

 SELECT a FROM Account a WHERE a.balance < :value 

首先创建一个Criteria Builder

 CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery accountQuery = builder.createQuery(Account.class); Root accountRoot = accountQuery.from(Account.class); ParameterExpression value = builder.parameter(Double.class); accountQuery.select(accountRoot).where(builder.lt(accountRoot.get("balance"), value)); 

要获取结果集参数并运行查询:

 TypedQuery query = entityManager.createQuery(accountQuery); query.setParameter(value, 1234.5); List results = query.getResultList(); 

BTW:entityManager被注入EJB / Service / DAO中的某个地方。

Mikko的回答很精彩。 只有改变我需要做的,是替换:

cq.select(customer).where(predicates.toArray(new Predicate[]{}));

有:

 Predicate [] predicatesarr = predicates.toArray(new Predicate[predicates.size()]); cq.select(customer).where(predicatesarr); 

某处从原始列表到数组的转换不起作用。