有两个具有多对多关系的实体类,我正在尝试创建一个查询,该查询测试一个表中所有实体是否存在任何关系。我被困了,因为似乎没有办法通过Criteria API引用JoinTable。
示例实体:
@Entity
@Table(name="man")
public class Man {
@Id
@GeneratedValue
private Long id;
}
@Entity
@Table(name="woman")
public class Woman {
@Id
@GeneratedValue
private Long id;
@ManyToMany
@JoinTable(
name="man_woman",
joinColumns=
@JoinColumn(name="woman_id", referencedColumnName="id"),
inverseJoinColumns=
@JoinColumn(name="man_id", referencedColumnName="id")
)
private Set<Man> men;
}
我想使用条件API创建一个查询,这会产生SQL,例如:
select m.id,
case when exists(select * from man_woman mw where mw.man_id=m.id) then 1 else 0
from man;
到目前为止,我提出的最好成绩如下:
CriteriaQuery<Tuple> criteriaQuery = criteriaBuilder.createTupleQuery();
Root<Man> from = criteriaQuery.from(Man.class);
Subquery<Long> subquery = criteriaQuery.subquery(Long.class);
Root<Woman> sub_from = subquery.from(Woman.class);
SetJoin<Woman, Man> setJoin = sub_from.join(Woman_.men);
subquery.select(sub_from.get(Woman_.id));
subquery.where(from.in(setJoin.get(Man_.id)));
criteriaQuery.multiselect(from.alias("man_entity"),
criteriaBuilder.selectCase()
.when(
criteriaBuilder.exists(subquery)
, true)
.otherwise(false)
.alias("knows_any_women")
);
return em.createQuery(criteriaQuery).getResultList()
导致SQL包含额外的连接:
select m.id,
case when exists(select w.id
from woman w
inner join man_woman mw on w.id = mw.woman_id
inner join man m2 on m2.id = mw.man_id
where m.id in (m2.id)
)
then 1 else 0
from man;
我想这句话最终会被优化为看起来像我想要的那样 - 但有没有办法让它从一开始变得更简单?