JPA with Specification - 如何通过子集合内容过滤实体?

时间:2017-03-17 12:45:06

标签: java jpa filter specifications

我遇到了一个问题,即通过列表中的子项中的值过滤实体。 例如:

public class Father(){
  private String name;
  private Set<Child> childs;
}
public class Child(){
  private String name;
  private Integer age;
  private School school;
}
public class School(){
  private String name;
}

我想过滤所有在学校X有孩子的父亲。

这就是我所做的,但工作不正常:

 Specification specs = new Specificatrion(){
        @Override
        public Predicate toPredicate(Root<Father> root, CriteriaQuery<?> query, final CriteriaBuilder cb){
             Root<Child> childRoot = query.from(Child.class);
             Path<?> path = childRoot.get(Child_.school.name);
             Predicate pred = exp.in("School Name");
             return cb.and(pred);
         }
}

有人可以帮助我吗? 谢谢!

2 个答案:

答案 0 :(得分:1)

你的孩子必须要有一个反向的关系回到父亲那里,所以孩子可以在学校和父亲之间架起桥梁。

这样的事情会起作用:

@Entity
public class Father {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "father", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Child> childs = new HashSet<>();


@Entity
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private Integer age;

    @ManyToOne(cascade=CascadeType.ALL)
    private Father father;

    @OneToOne(cascade = CascadeType.PERSIST)
    private School school;

然后在你的FatherRepository:

@Query("select father from Child child join child.father father join child.school school where school.name=:school")
List<Father> findBySchool(@Param("school") String school);

答案 1 :(得分:0)

我知道太晚了。但可能会帮助某人。

我又有一个实体InwardInventory,该实体具有子实体InwardOutwardList的子列表,又具有子Product的列表。因此,要过滤具有特定产品的InwardInventory。

Specification<InwardInventory> finalSpec = null;

finalSpec = specbldr.whereChildFieldListContains(
                InwardInventory_.INWARD_OUTWARD_LIST,InwardOutwardList_.PRODUCT,Product_.PRODUCT_NAME,productNames));

specbldr.whereChildFieldListContains方法的通用定义

public Specification<T> whereChildFieldListContains(String childTableName, String gcTable,String fieldName, List<String> names) 
    {
        Specification<T> finalSpec = null;
        for(String name:names)
        {
            Specification<T> internalSpec = (Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb)
                -> cb.like(root.join(childTableName).join(gcTable).get(fieldName), "%"+name+"%" );
                finalSpec  = specOrCondition(finalSpec,internalSpec);
        }
        return finalSpec;
    }

让我知道您是否需要进一步的帮助