首页 文章

具有多个参数的JPA Criteria API

提问于
浏览
30

我需要创建一个使用带有多个参数的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实现同样的目标?

3 回答

  • 72

    概念是构造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<A> customer = cq.from(A.class);
    
        //Constructing list of parameters
        List<Predicate> predicates = new ArrayList<Predicate>();
    
        //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();
    
  • 0

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

    Update: Providing a concrete example

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

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

    首先创建一个Criteria Builder

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

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

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

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

  • 5

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

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

    有:

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

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

相关问题