我Specification使用以下查询任何Contact与某些ManagedApplication实体绑定的实体。我传入一个Collection<Long>包含ManagedApplication要搜索的实体ID的ID 。
Specification
Contact
ManagedApplication
Collection<Long>
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符合搜索条件的实体的。
.findAll()
PagingAndSoringRepository
Page<Contact>
这是Repository。
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实体。
.join()
因此,我需要知道的是,如何仅Contact使用this从查询中返回不同的实体Specification?
我知道CriteriaQuery有一个.distinct()可以向其传递布尔值的方法,但是我没有CriteriaQuery在toPredicate()my方法中使用实例Specification。
CriteriaQuery
.distinct()
toPredicate()
这是我的元模型的相关部分。
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; }
query在toPredicate方法中使用参数来调用不同的方法。
query
toPredicate
示例如下:
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); ...