在我的应用程序中,我在两个实体之间有以下映射:
@Entity
public class Applicant {
private Integer id;
....
private Set<Document> documents;
... Getters and Setters ...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "applicant", cascade = CascadeType.ALL)
public Set<Document> getDocuments() {
return documents;
}
public Applicant setDocuments(Set<Document> documents) {
this.documents = documents;
return this;
}
}
文件:
public class Document {
private Long id;
private Applicant applicant;
... Getters and Setters ...
@ManyToOne
public Applicant getApplicant() {
return applicant;
}
public Document setApplicant(Applicant applicant) {
this.applicant = applicant;
return this;
}
}
我想使用Spring Data Specification(org.springframework.data.jpa.domain)使用findAll(Spec spec)方法过滤ApplicantRepository中的一些申请人。
但是,我的问题是我想要创建一个规范,其中包含参数Set和构建规范以过滤未链接到一个(不是全部)此文档的申请人。 / p>
我尝试了不同的东西,但没有一个可以工作......我不知道我是否遗忘了什么。 第一个是使用criteriaBuilder和value方法......
public static Specification<Applicant> applicantHasDoc(final Set<Document> documents) {
return new Specification<Applicant>() {
@Override
public Predicate toPredicate(Root<Applicant> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
/*
Problem during parsing the query :
select *
from
applicant applicant0_ cross join document documents1_
where
applicant0_.id=documents1_.applicant
and (. in (? , ?))
*/
Expression<Set<Document>> documentExpression = root.get(Applicant_.documents);
return cb.in(documentExpression).value(documents);
};
}
返回GrammarSQL异常......您可以在代码中看到SQL查询(在申请人字段上简化)。
第二种解决方案是直接在申请人的ROOT上使用元模型和In:
public static Specification<Applicant> applicantHasDoc(final Set<Document> documents) {
return new Specification<Applicant>() {
@Override
public Predicate toPredicate(Root<Applicant> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
/*
Error with this type of criteria : Parameter value [com.myapp.entity.Document@1b275eae] did not match expected type [java.util.Set (n/a)]
*/
return root.get(Applicant_.documents).in(documents);
}
};
}
我在代码中添加了每个解决方案的结果......但没有一个能够正常工作。
本规范的主要目的是与其他人一起使用:
List<Applicant> applicants = findAll(where(applicantHasDoc(documents).and(otherSpec(tags)).and(anotherSpec(mobilities), page);
所以我只能在Spring Data JPA规范中工作。
其他信息:我正在使用H2数据库。
感谢您的帮助。
答案 0 :(得分:4)
我找到了正确的方法,并且我的所有尝试都很糟糕,因为我在想“像对象”而不是在SQL中......但是CriteriaQuery是构建SQL查询的“对象包装器”。
所以,我在SQL中编写了我想要的查询,并找到了解决方案:
我想要的SQL是:
select *
from applicant applicant0_ inner join document documents1_ on applicant0_.id=documents1_.applicant where documents1_.id in (? , ?)
所以我的谓词似乎如下:
public static Specification<Applicant> applicantHasDoc(final Set<Document> documents) {
return new Specification<Applicant>() {
@Override
public Predicate toPredicate(Root<Applicant> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
SetJoin<Applicant, Document> documentApplicantJoin = root.join(Applicant_.documents);
return documentApplicantJoin.in(documents);
}
};
}