【问题标题】:Spring data jpa Specification: How to filter a parent object by its children object propertySpring data jpa 规范:如何通过子对象属性过滤父对象
【发布时间】:2017-12-18 11:04:50
【问题描述】:

我的实体类正在关注

@Entity
@table
public class User {

    @OneToOne
    private UserProfile userProfile;

    // others
}


@Entity
@Table
public class UserProfile {

    @OneToOne
    private Country country;
}

@Entity
@Table
public class Country {
    @OneToMany
    private List<Region> regions;
}

现在我想获取特定地区的所有用户。我知道 sql 但我想通过 spring data jpa Specification 来做到这一点。以下代码不应该工作,因为区域是一个列表,我正在尝试与单个值匹配。如何获取区域列表并与单个对象进行比较?

 public static Specification<User> userFilterByRegion(String region){


        return new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                return criteriaBuilder.equal(root.get("userProfile").get("country").get("regions").get("name"), regionalEntity);
            }
        };
    }

编辑:感谢您的帮助。实际上我正在寻找以下 JPQL 的等效条件查询

SELECT u FROM User u JOIN FETCH u.userProfile.country.regions ur WHERE ur.name=:<region_name>

【问题讨论】:

    标签: spring hibernate spring-boot spring-data-jpa jpa-criteria


    【解决方案1】:

    试试这个。这应该工作

    criteriaBuilder.isMember(regionalEntity, root.get("userProfile").get("country").get("regions"))
    

    您可以通过覆盖 Region 类中的 Equals 方法(也是 Hashcode)来定义相等的条件

    【讨论】:

    • 感谢您的帮助,但它不适用于我的情况。我需要用 jpa 标准查询翻译以下内容。 FROM User u JOIN FETCH u.userProfile.country.regions ur WHERE ur.name
    【解决方案2】:

    我的代码片段

    // string constants make maintenance easier if they are mentioned in several lines
    private static final String CONST_CLIENT = "client";
    private static final String CONST_CLIENT_TYPE = "clientType";
    private static final String CONST_ID = "id";
    private static final String CONST_POST_OFFICE = "postOffice";
    private static final String CONST_INDEX = "index";
    ...
    
    @Override
    public Predicate toPredicate(Root<Claim> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        List<Predicate> predicates = new ArrayList<Predicate>();
        // we get list of clients and compare client's type
        predicates.add(cb.equal(root
                    .<Client>get(CONST_CLIENT)
                    .<ClientType>get(CONST_CLIENT_TYPE)
                    .<Long>get(CONST_ID), clientTypeId));
        // Set<String> indexes = new HashSet<>();
        predicates.add(root
                    .<PostOffice>get(CONST_POST_OFFICE)
                    .<String>get(CONST_INDEX).in(indexes));
        // more predicates added
        return return andTogether(predicates, cb);
    }
    
    private Predicate andTogether(List<Predicate> predicates, CriteriaBuilder cb) {
        return cb.and(predicates.toArray(new Predicate[0]));
    }
    

    如果你确定你只需要一个谓词,那么使用 List 可能会有点过头了。

    【讨论】:

      猜你喜欢
      • 2014-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-31
      • 1970-01-01
      • 2020-04-20
      相关资源
      最近更新 更多