我正在寻找内容过滤的结果。我的实体(为简洁起见)如下所示:

节点:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Node {
    @Id
    @GeneratedValue
    public Integer id;
}


现场:

@Entity
public class Scene extends Node {
    @OneToMany(mappedBy = "scene", /*fetch = FetchType.EAGER, */cascade = CascadeType.ALL)
    public List<Source> sources;
}


资源:

@Entity
public class Source extends Node {
    @ManyToOne
    public Scene scene;

    @Enumerated(EnumType.ORDINAL)
    public SourceType type;
}


以下是我希望实现的过滤器示例。

给定SourceTypes的集合,我希望选择所有场景,以便该场景由这些类型中的每一个的源引用。我使用带有以下谓词的QueryDSL来实现此目的:

private Predicate filterBySourceType(Collection<SourceType> it) {
    BooleanBuilder bb = new BooleanBuilder();

    for (SourceType st : it)
        bb.and(QScene.scene.sources.any().type.eq(st));

    return bb.getValue();
}


这些谓词的一系列组合在一起给出整体查询。当只选择一个SourceType时,结果查询如下所示:

Hibernate: select count(scene0_.id) as col_0_0_ from Scene scene0_ inner join Node scene0_1_ on scene0_.id=scene0_1_.id where exists (select 1 from Source source1_ inner join Node source1_1_ on source1_.id=source1_1_.id where (source1_.id in (select sources2_.id from Source sources2_ inner join Node sources2_1_ on sources2_.id=sources2_1_.id where scene0_.id=sources2_.scene_id)) and source1_.type=?)

我相信上面发生的是交叉连接,结果(2k个场景,1k个源),查询需要花费几秒钟的时间。

我尝试切换到具体的类多态性,以消除没有明显改善性能的Node连接。

我如何优化该谓词?

最佳答案

事实证明,您可以使用JPASubQuery获取CollectionExpression并写出查询,类似于使用普通旧SQL编写查询的方式。

        bb.and(QScene.scene.in(
                new JPASubQuery()
                        .from(source)
                        .where(source.type.eq(st))
                        .list(source.scene)
        ));

09-15 17:14
查看更多