来自使用连接的Spring Data JPA规范的不同结果 [英] Distinct results from Spring Data JPA Specification that uses join

查看:149
本文介绍了来自使用连接的Spring Data JPA规范的不同结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下规范,用于查询任何联系人与某些 ManagedApplication 个实体。我传入一个集合< Long> ,其中包含我正在搜索的 ManagedApplication 实体的id。

  public static Specification< Contact> findByApp(final Collection< Long> appIds){
return new Specification< Contact>(){
@Override
public Predicate toPredicate(Root< Contact> root,CriteriaQuery< CriteriaBuilder cb){
final Predicate appPredicate = root.join(Contact_.managedApplications)
.get(ManagedApplication_.managedApplicationId).in(appIds);
}
}
}

我将此规范传递给 .findAll()我的的方法PagingAndSoringRepository 检索页面<联系人> ,它将包含符合搜索标准的所有联系人实体。



这是

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

以下是我如何调用 .findAll()方法。

 最后一页< Contact> contacts = pagingAndSortingContactRepository.findAll(ContactSpecification.findByApp(appIds),可分页); 

这个工作并返回所有联系人实体绑定到与传入的ID相对应的任何 ManagedApplication 实体。但是,由于我调用 .join()联系人 c> 联系人实体与 ManagedApplication 实体一起加入 c $ c>在app id列表中有多个 ManagedApplication 实体,那么查询将返回重复的 Contact 实体。

所以我需要知道的是,我怎么才能使用这个查询返回从我的查询返回的不同的 Contact 规范?



我知道 CriteriaQuery code> .distinct()方法,您可以传递一个布尔值,但我没有使用 CriteriaQuery code> toPredicate()我的规范的方法



我见过的相关部分

Contact_.java:

  @StaticMetamodel(Contact。类)
public class Contact_ {
public static volatile SingularAttribute< Contact,String> firstNm;
public static volatile SingularAttribute< Contact,String> lastNm;
public static volatile SingularAttribute< Contact,String>电子邮件地址;
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;


解决方案使用<$ c $在您的 toPredicate 方法中使用c> query 参数来调用不同的方法。



如下:

pre $ public Predicate toPredicate(Root< Contact> root,CriteriaQuery<?>查询,CriteriaBuilder cb){
final谓词appPredicate = root.join(Contact_.managedApplications)
.get(ManagedApplication_.managedApplicationId).in(appIds);
query.distinct(true);
...


I have the following Specification that I use to query for any Contact entities that are tied to certain ManagedApplication entities. I pass in a Collection<Long> that contains the ids of the ManagedApplication entities that I am searching for.

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.

Here is the Repository.

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

And here is how I'm calling the .findAll() method.

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.

So what I need to know is, how can I get only distinct Contact entities returned from my query using this Specification?

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.

Here are the relevant sections of my metamodels.

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

解决方案

Use the query parameter in your toPredicate method to invoke the distinct method.

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

这篇关于来自使用连接的Spring Data JPA规范的不同结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆