Ho il seguente Specification
che utilizzo per richiedere qualsiasi entità Contact
legata a determinate entità ManagedApplication
. Passo in uno Collection<Long>
che contiene gli ID delle entità ManagedApplication
che sto cercando.Risultati distinti da Dati Spring Data Specifica che utilizza join
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);
}
}
}
mi passano questa specifica al metodo della mia PagingAndSoringRepository
.findAll()
per recuperare un Page<Contact>
che conterrà tutti i Contact
entità che soddisfano i criteri di ricerca.
Questo è il Repository
.
@Repository
public interface PagingAndSortingContactRepository extends PagingAndSortingRepository<Contact, Long>, JpaSpecificationExecutor<Contact> {
}
Ed ecco come lo chiamo il metodo .findAll()
.
final Page<Contact> contacts = pagingAndSortingContactRepository.findAll(ContactSpecification.findByApp(appIds), pageable);
funziona e restituisce tutti Contact
le entità che sono legati ad uno qualsiasi degli ManagedApplication
entità che corrispondono agli ID passati. Tuttavia, dal momento che sto chiamando .join()
di aderire al soggetto Contact
con l'entità ManagedApplication
, se uno Contact
ha più entità ManagedApplication
nell'elenco degli ID app, quindi la query restituirà le entità duplicate Contact
.
Quindi, quello che devo sapere è, come posso ottenere solo le entità distinte Contact
restituite dalla mia query utilizzando questo Specification
?
so che CriteriaQuery
ha un metodo .distinct()
che è possibile passare un valore booleano, ma non sto usando l'istanza CriteriaQuery
nel metodo della mia Specification
toPredicate()
.
Ecco le sezioni pertinenti dei miei metamodelli.
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;
}
Sì, funziona! –
Grazie per questa soluzione, funziona benissimo! Inoltre, per chiarire, è necessario aggiungere 'query.distinct (true)' a ogni predicato che richiede questa distinta dichiarazione. Non è sufficiente aggiungere questa dichiarazione a qualsiasi predicato e farlo funzionare per l'intera query .. –