2015-10-08 11 views
6

ManagedApplicationエンティティに関連付けられているContactエンティティのクエリには、次のようなSpecificationがあります。私が探しているManagedApplicationエンティティのIDを含むCollection<Long>を渡します。Springデータとの明確な結果結合を使用するJPA仕様

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); 
     } 
    } 
} 

私は、検索条件に一致するすべてのContactのエンティティが含まれますPage<Contact>を取得するために私のPagingAndSoringRepository.findAll()方法には、この仕様書を渡します。

ここにはRepositoryがあります。

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

そして、ここで私は.findAll()メソッドを呼んでいる方法です。

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

は、これが動作し、渡されたIDに対応ManagedApplicationエンティティのいずれかに関連付けられているすべてのContactエンティティを返します。しかし、私は1つの場合は、ManagedApplicationエンティティとContactエンティティに参加する.join()を呼び出していますので、 Contactには、アプリIDのリストに複数のManagedApplicationエンティティが含まれている場合、クエリは重複するContactエンティティを返します。

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

私はCriteriaQueryはあなたにブール値を渡すことができますが、私は私のSpecificationtoPredicate()方法でCriteriaQueryインスタンスを使用していない.distinct()方法を持っていることを知っています。

ここに私のメタモデルの関連セクションがあります。

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; 
} 

答えて

20

明確なメソッドを呼び出すために、あなたのtoPredicate方法でqueryパラメータを使用します。以下

サンプル:

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); 
    ... 
+0

ええ、それは働きます! –

+0

このソリューションをありがとう、それは素晴らしい動作します! また、この明確なステートメントを必要とするすべての述語に 'query.distinct(true)'を追加する必要があります。このステートメントを任意の述部に追加して、それを全照会で機能させるだけでは不十分です。 –