Java 如何避免在规范内使用子查询进行连接?

Java 如何避免在规范内使用子查询进行连接?,java,hibernate,spring-data,Java,Hibernate,Spring Data,我需要获取一些基于数据的实体,这些数据只能在5次关联后才能找到。我希望避免在中途加入所有表,并使用IN子句 下面是一个简单的实现,我发现它只使用了几个实体: @Entity public class Foo { @Id private Long idFoo; private String name; } @Entity public class Bar { @Id private Long idBar; @ManyToOne @Join

我需要获取一些基于数据的实体,这些数据只能在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);
    }
}
我认为子查询中的连接是无用的,与我的目标背道而驰,我想做如下事情:

select foo0_.idFoo, foo0_.name 
from Foo foo0_ 
where foo0_.idFoo in (
    select bar1_.idFoo 
    from bar bar1_  
    where bar1_.idBar=1
);

是否有必要更改规范并实现这一点

改用exists子查询,该子查询通常速度更快,如果使用最新的hibernate版本,还可以消除连接

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(cb.literal(1))
                .where(cb.and(
                   cb.equal(barRoot.get("idBar"), 1L),
                   cb.equal(barRoot.get("foo"), root)
                );

        return cb.exists(subquery);
    }
}
类过滤器foobyibar扩展了规范{
公共谓词toPredicate(根根、CriteriaQuery查询、CriteriaBuilder cb){
var subquery=query.subquery(Foo.class);
var barRoot=subquery.from(Bar.class);
subquery.select(cb.literal(1))
.在哪里(cb和(
cb.equal(barRoot.get(“idBar”),1L),
cb.equal(barRoot.get(“foo”),root)
);
返回cb.exists(子查询);
}
}

改用exists子查询,该子查询通常更快,并且如果您使用的是最新的hibernate版本,还允许消除联接

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(cb.literal(1))
                .where(cb.and(
                   cb.equal(barRoot.get("idBar"), 1L),
                   cb.equal(barRoot.get("foo"), root)
                );

        return cb.exists(subquery);
    }
}
类过滤器foobyibar扩展了规范{
公共谓词toPredicate(根根、CriteriaQuery查询、CriteriaBuilder cb){
var subquery=query.subquery(Foo.class);
var barRoot=subquery.from(Bar.class);
subquery.select(cb.literal(1))
.在哪里(cb和(
cb.equal(barRoot.get(“idBar”),1L),
cb.equal(barRoot.get(“foo”),root)
);
返回cb.exists(子查询);
}
}