【问题标题】:JPA criteria produce a query with just a one question pointJPA 标准产生一个只有一个问题点的查询
【发布时间】:2019-07-31 14:37:53
【问题描述】:

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

我创建了以下查询:

@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()
  • criteriaBuilder.parameter() with criteriaBuilder.equal(..., parameter) 具有相同的结果。

标签: java jpa-2.0 hibernate-criteria


【解决方案1】:

使用 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);

【讨论】:

  • 不幸的是,它没有帮助。
【解决方案2】:

我还没有找到解决问题的方法,我的决定是在没有规范的情况下使用实体管理器“手动创建”查询。

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()])); 时,它只创建了一个带有 one 参数的 one 谓词。

也尝试将规范一分为二,结果不成功:

Specification.where(firstSpecification).and(secondSpecification)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    相关资源
    最近更新 更多