简体   繁体   English

来自使用 join 的 Spring Data JPA 规范的不同结果

[英]Distinct results from Spring Data JPA Specification that uses join

I have the following Specification that I use to query for any Contact entities that are tied to certain ManagedApplication entities.我有以下Specification ,用于查询与某些ManagedApplication实体相关联的任何Contact实体。 I pass in a Collection<Long> that contains the ids of the ManagedApplication entities that I am searching for.我传入一个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 PagingAndSoringRepository to retrieve a Page<Contact> that will contain all Contact entities that meet the search criteria.我将此规范传递给我的PagingAndSoringRepository.findAll()方法以检索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 Contact entities that are tied to any of the ManagedApplication entities that correspond to the ids passed in. However, since I am calling .join() to join the Contact entity with the ManagedApplication entity, if one Contact has multiple ManagedApplication entities in the list of app ids, then the query will return duplicate Contact entities.这有效并返回绑定到与传入的 id 相对应的任何ManagedApplication实体的所有Contact实体。但是,由于我调用.join()Contact实体与ManagedApplication实体连接起来,如果一个Contact有多个ManagedApplication实体,则查询将返回重复的Contact实体。

So what I need to know is, how can I get only distinct Contact entities returned from my query using this Specification ?所以我需要知道的是,如何使用此Specification从我的查询中只获取不同的Contact实体?

I know that CriteriaQuery has a .distinct() method that you can pass a boolean value to, but I am not using the CriteriaQuery instance in the toPredicate() method of my Specification .我知道CriteriaQuery有一个.distinct()方法,您可以将一个布尔值传递给它,但我没有在我的SpecificationtoPredicate()方法中使用CriteriaQuery实例。

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托管应用程序_.java

@StaticMetamodel(ManagedApplication.class)
public class ManagedApplication_ {
    public static volatile SingularAttribute<ManagedApplication, Integer> managedApplicationId;
}

Use the query parameter in your toPredicate method to invoke the distinct method.toPredicate方法中使用query参数来调用不同的方法。

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

a new static method could be added可以添加一个新的静态方法

public static Specification<Object> distinct() {
    return (root, query, cb) -> {
        query.distinct(true);
        return null;
    };
}

where later you could add when creating your Specification稍后您可以在创建规范时添加

Specification.where(
    YourStaticClassWhereYouCreatedTheUpperMethod.distinct().and(..))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM