我有两个班,一个有很多孩子的父亲,像这样:
Class Person {
@ManyToMany
@JoinTable(name = "person_tag",
joinColumns = {@JoinColumn(name = "person_id",
referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "tag_id",
referencedColumnName = "id")})
List<Tag> tags;
}
Class Tag {
Long id
}
我需要构建一个Criteria Query来查找所有具有与Tag Ids列表匹配的标签的人
我将此关系保存在一个包含2列的新表中:person_id tag_id
我实现了以下解决方案:
private Specification<Person> generatePersonIdsSpecification(List<Long> ids) {
return (root, query, cb) -> {
Subquery<Person> sq = query.subquery(Person.class);
Root<Person> person = sq.from(Person.class);
ListJoin<Person, Tag> tagJoin = person.joinList("tags");
sq.select(person).distinct(true).where(tagJoin.get("id").in(ids));
return cb.in(root).value(sq);
};
}
但我得到:
引起:java.lang.IllegalArgumentException:请求的属性不是org.hibernate.jpa.criteria.path.AbstractFromImpl.joinList(AbstractFromImpl.java:497)〜[hibernate-entitymanager-4.3.11.Final.jar: 4.3.11.Final] at org.hibernate.jpa.criteria.path.AbstractFromImpl.joinList(AbstractFromImpl.java:484)〜[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
这样的查询可以构建如下:
List<Long> someTagIds ...
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> person = query.from(Person.class);
ListJoin<Person, Tag> tagJoin = person.joinList("tags");
query.select(person).distinct(true)
.where(tagJoin.get("id").in(someTagIds));
List<Person> result = em.createQuery(query).getResultList();
好的,所以我不是一起搜索所有标签,而是循环进入id并为每个id生成不同的规范:
private Specification<Person> generateByTagIdSpecification(Long id) {
return (root, query, cb) -> {
Subquery<Person> sq = query.subquery(Person.class);
Root<Person> person = sq.from(Person.class);
Join<Person, Tag> join = person.join("tags");
sq.select(person).distinct(true).where(cb.equal(join.get("id"), id));
return cb.in(root).value(sq);
};
}