【发布时间】:2020-06-15 19:13:42
【问题描述】:
我需要根据只有在 5 次关联后才能找到的数据来获取一些实体。我想避免在途中加入所有表并使用 IN 子句。
这是我发现的仅使用几个实体的简单实现:
@Entity
public class Foo {
@Id
private Long idFoo;
private String name;
}
@Entity
public class Bar {
@Id
private Long idBar;
@ManyToOne
@JoinColumn(name = "idFoo")
private Foo foo;
}
假设我需要根据 Bar 属性列出所有 Foo 对象,比如说 idBar:
class FilterFooByIdBar extends Specification<Foo> {
public Predicate toPredicate(Root<Foo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
var subquery = query.subquery(Foo.class);
var barRoot = subquery.from(Bar.class);
subquery.select(barRoot.get("foo"))
.where(builder.equal(barRoot.get("idBar"), 1L));
return root.in(subquery);
}
}
这可行,但生成的 SQL 是这样的:
select foo0_.idFoo, foo0_.name
from Foo foo0_
where foo0_.idFoo in (
select bar1_.idFoo
from Bar bar1_ cross join Foo foo2_
where bar1_.idFoo=foo2_.idFoo
and bar1_.idBar=1
);
我认为子查询内的连接是无用的,违背了我的目标,我想做这样的事情:
select foo0_.idFoo, foo0_.name
from Foo foo0_
where foo0_.idFoo in (
select bar1_.idFoo
from bar bar1_
where bar1_.idBar=1
);
有没有办法改变规范并实现它?
【问题讨论】:
标签: java hibernate spring-data