JPA 标准产生一个只有一个问题点的查询

JPA criteria produce a query with just a one question point

在我们的数据库中我们有缓存系统,查询绑定参数是敏感的。

我创建了以下查询:

@Override
public Predicate toPredicate(Root<Position> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
    query.distinct(true);
    final Collection<Predicate> predicates = new ArrayList<>();

    Join<Position, ManagersPositions> managersPositionsJoin = root.join("managersPositions", JoinType.INNER);

    Predicate managerPredicate = criteriaBuilder.equal(managersPositionsJoin.get("managerId"), managerId);
    predicates.add(managerPredicate);

    if (onlyDirect) {
        Predicate equalsDirect = criteriaBuilder.equal(managersPositionsJoin.get("isDirect"), true);
        predicates.add(equalsDirect);
    }
    return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}

它产生以下查询:

select
   distinct position0_.id as id1_69_0_,
   ...
where managerspo1_.manager_id=22
and managerspo1_.is_direct=?

我必须发送带有 2 个绑定参数的请求,例如:

where managerspo1_.manager_id=?
and managerspo1_.is_direct=?

如何解决第一个“?”的问题?

使用CriteriaBuilder.parameter()添加多个参数:

    ParameterExpression<Integer> managerIdParam = 
        criteriaBuilder.parameter( Integer.class );
    ParameterExpression<Boolean> isDirectParam = 
        criteriaBuilder.parameter( Boolean.class );
    Predicate managerPredicate = 
        criteriaBuilder.equal(managersPositionsJoin.get("managerId"), 
        managerIdParam);
    Predicate equalsDirect = 
        criteriaBuilder.equal(managersPositionsJoin.get("isDirect"), isDirectParam);

我还没有找到解决我的问题的方法,我的决定是 "hand-create" 没有指定的实体管理器查询。

final String queryString = "select distinct pos from Position pos " +
            "inner join pos.managersPositions mn " +
            "where mn.managerId = :managerId and mn.isDirect = :isDirect ";

    TypedQuery<Position> query = entityManager.createQuery(
            queryString,
            Position.class);
    query.setParameter("managerId", managerEmployeeId);
    query.setParameter("isDirect", true);

因为当我创建 criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])); 时,它只生成一个只有一个参数的谓词。

也试过将规格分成2份,结果不成功:

Specification.where(firstSpecification).and(secondSpecification)