java 来自使用 join 的 Spring Data JPA 规范的不同结果
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33025213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Distinct results from Spring Data JPA Specification that uses join
提问by Andrew Mairose
I have the following Specificationthat I use to query for any Contactentities that are tied to certain ManagedApplicationentities. I pass in a Collection<Long>that contains the ids of the ManagedApplicationentities that I am searching for.
我有以下Specification用于查询Contact与某些ManagedApplication实体相关联的任何实体的以下内容。我传入一个Collection<Long>包含ManagedApplication我正在搜索的实体的 ID 。
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);
}
}
}
I pass this specification to the .findAll()method of my PagingAndSoringRepositoryto retrieve a Page<Contact>that will contain all Contactentities that meet the search criteria.
我将此规范传递给.findAll()my的方法PagingAndSoringRepository以检索Page<Contact>将包含Contact满足搜索条件的所有实体的 。
Here is the Repository.
这是Repository.
@Repository
public interface PagingAndSortingContactRepository extends PagingAndSortingRepository<Contact, Long>, JpaSpecificationExecutor<Contact> {
}
And here is how I'm calling the .findAll()method.
这是我调用该.findAll()方法的方式。
final Page<Contact> contacts = pagingAndSortingContactRepository.findAll(ContactSpecification.findByApp(appIds), pageable);
This works and returns all Contactentities that are tied to any of the ManagedApplicationentities that correspond to the ids passed in. However, since I am calling .join()to join the Contactentity with the ManagedApplicationentity, if one Contacthas multiple ManagedApplicationentities in the list of app ids, then the query will return duplicate Contactentities.
这有效并返回与传入的 id 对应的Contact任何实体相关联的所有实体ManagedApplication。 但是,由于我正在调用.join()将Contact实体与ManagedApplication实体连接,如果应用程序 id 列表中Contact有多个ManagedApplication实体,则查询将返回重复的Contact实体。
So what I need to know is, how can I get only distinct Contactentities returned from my query using this Specification?
所以我需要知道的是,如何Contact使用 this 从我的查询中只返回不同的实体Specification?
I know that CriteriaQueryhas a .distinct()method that you can pass a boolean value to, but I am not using the CriteriaQueryinstance in the toPredicate()method of my Specification.
我知道CriteriaQuery有一个.distinct()方法可以将布尔值传递给它,但我没有CriteriaQuery在toPredicate()我的Specification.
Here are the relevant sections of my metamodels.
这是我的元模型的相关部分。
Contact_.java:
联系人_.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
ManagedApplication_.java
@StaticMetamodel(ManagedApplication.class)
public class ManagedApplication_ {
public static volatile SingularAttribute<ManagedApplication, Integer> managedApplicationId;
}
回答by Ish
Use the queryparameter in your toPredicatemethod to invoke the distinct method.
使用方法中的query参数toPredicate来调用不同的方法。
Sample below:
示例如下:
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);
...

