Отличные результаты от спецификации Spring Data JPA, использующей join
у меня есть следующие Specification что я использую для запроса любого Contact сущности, которые привязаны к определенным ManagedApplication объекты. Я прохожу в Collection<Long>, который содержит идентификаторы ManagedApplication сущности, которые я ищу.
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);
это работает и возвращает все Contact сущности, которые привязаны к любому из ManagedApplication сущности, соответствующие переданным идентификаторам. Однако, поскольку я звоню .join() присоединиться к Contact сущности ManagedApplication лица, если один Contact несколько ManagedApplication сущности в списке идентификаторов приложений, затем запрос вернет дубликат Contact объекты.
так что я хочу знать, как я могу получить только отдельные Contact сущности, возвращенные из моего запроса с помощью этого Specification?
я знаю, что CriteriaQuery есть .distinct() метод, которому вы можете передать логическое значение, но я не использую CriteriaQuery экземпляр toPredicate() метод 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;
}
1 ответов
использовать в своем toPredicate метод для вызова метода distinct.
пример:
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);
...