web-dev-qa-db-ja.com

結合を使用するSpring Data JPA仕様からの明確な結果

特定のSpecificationエンティティに関連付けられているContactエンティティのクエリに使用する次のManagedApplicationがあります。検索するManagedApplicationエンティティのIDを含む_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);
        }
    }
}
_

この仕様をPagingAndSoringRepository.findAll()メソッドに渡して、検索条件を満たすすべてのContactエンティティを含む_Page<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エンティティ。1つのContactにアプリIDのリストに複数のManagedApplicationエンティティがある場合、クエリは重複したContactエンティティ。

ですから、知っておく必要があるのは、このContactを使用してクエリから返された個別のSpecificationエンティティのみを取得するにはどうすればよいですか?

CriteriaQueryには.distinct()メソッドがあり、ブール値を渡すことができることは知っていますが、toPredicate()CriteriaQueryインスタンスを使用していません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;
}
_
19
Andrew Mairose

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);
    ...
44
Ish