具有多个参数的 JPA 标准 API

2022-09-01 02:15:25

我需要创建一个使用具有多个参数的JPA标准API的搜索方法。现在的问题是,不是每个参数都是必需的。因此,有些可能为 null,并且不应包含在查询中。我已经尝试使用CriterionBuilder进行了尝试,但我不知道如何使其工作。

使用休眠标准API,这相当容易。只需创建条件,然后添加限制。

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

如何使用 JPA 的标准 API 实现相同的目标?


答案 1

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

要查询的示例实体:

@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();

答案 2

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

更新:提供具体示例

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

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

首先创建条件生成器

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();

顺便说一句:实体管理器被注入到 EJB/Service/DAO 中的某个位置。


推荐