Java 如何使用JPA中的规范连接多个列?

Java 如何使用JPA中的规范连接多个列?,java,jpa,specifications,criteria-api,criteriaquery,Java,Jpa,Specifications,Criteria Api,Criteriaquery,我正在尝试将查询转换为JPA规范,该查询包含带有或条件的连接操作 public class UserSpecification { public static Specification<User> UsersNotInSelectedOperations(final List<Long> operationId ){ return new Specification<User>() { @Override

我正在尝试将查询转换为JPA规范,该查询包含带有或条件的连接操作

public class UserSpecification {

    public static Specification<User> UsersNotInSelectedOperations(final List<Long> operationId ){

        return new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Join<User, Operation> userJoinOp = root.join("fk_user1_id");
                final Path<User> users = userJoinOp.get("id");
                return criteriaBuilder.not(users.in(operationId));
            }
        };
    }

}
以下是查询:

select u from User u inner join Operation o on (u.id = o.verificateur1 or u.id = o.verificateur2) where o.id not in (:ids)
我试图编写一个规范,但我在如何使用或条件连接多个列方面遇到了障碍

public class UserSpecification {

    public static Specification<User> UsersNotInSelectedOperations(final List<Long> operationId ){

        return new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Join<User, Operation> userJoinOp = root.join("fk_user1_id");
                final Path<User> users = userJoinOp.get("id");
                return criteriaBuilder.not(users.in(operationId));
            }
        };
    }

}

我希望有一个规范可以替换上面的查询

您可以尝试使用子查询而不是联接表达式

    public static Specification<User> UsersNotInSelectedOperations(final List<Long> operationIds) {
            return (root, query, builder) -> {
                    Subquery<Operation> subquery = query.subquery(Operation.class);
                    Root<Operation> operation = subquery.from(Operation.class);

                    Predicate predicate1_1 = builder.equal(operation.get("verificateur1").get("id"), root.get("id"));
                    Predicate predicate1_2 = builder.equal(operation.get("verificateur2").get("id"), root.get("id"));
    
                    Predicate predicate1 = builder.or(predicate1_1, predicate1_2); 
                    Predicate predicate2 = operation.get("id").in(operationIds).not();
    
                    subquery.select(operation).where(predicate1, predicate2);
    
                    return builder.exists(subquery);
            };
   }
公共静态规范用户未选择操作(最终列表操作ID){
返回(根、查询、生成器)->{
Subquery Subquery=query.Subquery(Operation.class);
根操作=子查询.from(operation.class);
谓词predicate1_1=builder.equal(operation.get(“verificateur1”).get(“id”)、root.get(“id”);
谓词predicate1_2=builder.equal(operation.get(“verificateur2”).get(“id”)、root.get(“id”);
谓词谓词1=builder.or(谓词1_1,谓词1_2);
谓词predicate2=operation.get(“id”).in(operationId).not();
选择(操作).where(谓词1,谓词2);
返回生成器.exists(子查询);
};
}
使用此规范,您可以得到如下HQL查询

from User u
where exists( // subquery ->
  from Operation o
  where (o.verificateur1.id = u.id or o.verificateur2.id = u.id) // predicate 1
  and o.id not in (:ids) // predicate 2
  // <- subquery
)
来自用户u
存在的位置(//子查询->
从o行动开始
其中(o.verificateur1.id=u.id或o.verificateur2.id=u.id)//谓词1
和o.id不在(:ids)//谓词2中

//你能解释一下这两行的作用吗:
Subquery-Subquery=query.Subquery(Operation.class);
Root-Operation=Subquery.from(Operation.class);
它从操作类创建子查询。使用此规范,您可以使用子查询而不是联接表达式获得HQL。结果将是相同的。非常有用的答案。谢谢!
from User u
where exists( // subquery ->
  from Operation o
  where (o.verificateur1.id = u.id or o.verificateur2.id = u.id) // predicate 1
  and o.id not in (:ids) // predicate 2
  // <- subquery
)