规范中的JpaSpecificationExecutor JOIN + ORDER BY

时间:2016-05-13 07:31:00

标签: java mysql jpa spring-data-jpa criteria-api

我有一个使用JOIN和ORDER BY的查询,并希望使用Criteria Api在我的存储库中使用它。

我在这里找到了如何将这样的查询包装到CriteriaQuery(Link)中。

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
Join<Pet, Owner> owner = cq.join(Pet_.owners);
cq.select(pet);
cq.orderBy(cb.asc(owner.get(Owner_.lastName),owner.get(Owner_.firstName)));

另一方面,我找到了一些例子,将Criteria Api与JpaRepository(example)结合使用。

问题是存储库中的所有方法都需要一个规范:

T findOne(Specification<T> spec);

总是像这样构建:

public static Specification<PerfTest> statusSetEqual(final Status... statuses) {
    return new Specification<PerfTest>() {
        @Override

        public Predicate toPredicate(Root<PerfTest> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            return cb.not(root.get("status").in((Object[]) statuses));
        }
    };

}

所以一方面我知道如何创建CriteriaQuery,另一方面我需要一个基于Predicate构建的规范,我无法弄清楚如何将CriteriaQuery解析为Specification / Predicate。

1 个答案:

答案 0 :(得分:11)

尝试这样的事情(我假设宠物有很多主人):

public static Specification<Pet> ownerNameEqual(String ownerName) {
        return new Specification<Pet>() {
            @Override
            public Predicate toPredicate(Root<Pet> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Join<Pet, Owner> owners = root.join("owners");
                criteriaQuery.orderBy(criteriaBuilder.desc(root.get("id")));
                return criteriaBuilder.equal(owners.get("name"), ownerName);
            }
        };
    }

这只是一个搜索所有至少有一位所有者名称等于 ownerName

的宠物的示例

但您可以在存储库中添加方法List<Pet> findByOwnersNameOrderByIdDesc(String ownerName);(与规范等效)。