一尘不染

使用联接的Spring Data JPA规范的不同结果

hibernate

Specification使用以下查询任何Contact与某些ManagedApplication实体绑定的实体。我传入一个Collection<Long>包含ManagedApplication要搜索的实体ID的ID

public static Specification<Contact> findByApp(final Collection<Long> appIds) {
    return new Specification<Contact>() {
        @Override
        public Predicate toPredicate(Root<Contact> root, CriteriaQuery<?> query, CriteriaBuilder cb) {            
            final Predicate appPredicate = root.join(Contact_.managedApplications)
                .get(ManagedApplication_.managedApplicationId).in(appIds);
        }
    }
}

我将此规范传递给.findAll()我的方法,PagingAndSoringRepository以检索一个Page<Contact>包含所有Contact符合搜索条件的实体的。

这是Repository

@Repository
public interface PagingAndSortingContactRepository extends PagingAndSortingRepository<Contact, Long>, JpaSpecificationExecutor<Contact> {    
}

这就是我调用该.findAll()方法的方式。

final Page<Contact> contacts = pagingAndSortingContactRepository.findAll(ContactSpecification.findByApp(appIds), pageable);

这可以正常工作并返回与传入ID对应的Contact任何实体相关联的所有实体ManagedApplication。但是,由于我要.join()将该Contact实体与该ManagedApplication实体联接,因此如果一个应用ID列表中Contact有多个ManagedApplication实体,则查询将返回重复的Contact实体。

因此,我需要知道的是,如何仅Contact使用this从查询中返回不同的实体Specification

我知道CriteriaQuery有一个.distinct()可以向其传递布尔值的方法,但是我没有CriteriaQuerytoPredicate()my方法中使用实例Specification

这是我的元模型的相关部分。

Contact_.java:

@StaticMetamodel(Contact.class)
public class Contact_ {
    public static volatile SingularAttribute<Contact, String> firstNm;
    public static volatile SingularAttribute<Contact, String> lastNm;
    public static volatile SingularAttribute<Contact, String> emailAddress;
    public static volatile SetAttribute<Contact, ManagedApplication> managedApplications;
    public static volatile SetAttribute<Contact, ContactToStructure> contactToStructures;
}

ManagedApplication_.java

@StaticMetamodel(ManagedApplication.class)
public class ManagedApplication_ {
    public static volatile SingularAttribute<ManagedApplication, Integer> managedApplicationId;
}

阅读 184

收藏
2020-06-20

共1个答案

一尘不染

querytoPredicate方法中使用参数来调用不同的方法。

示例如下:

public Predicate toPredicate(Root<Contact> root, CriteriaQuery<?> query, CriteriaBuilder cb) {            
    final Predicate appPredicate = root.join(Contact_.managedApplications)
        .get(ManagedApplication_.managedApplicationId).in(appIds);
    query.distinct(true);
    ...
2020-06-20