SpringData和Querydsl生成非最佳查询

时间:2013-12-03 11:57:13

标签: spring-data querydsl

我正在使用JPA(Hibrenate v4.1.7),Spring Data(v1.4.1)和Query DSL(v3.2.3)在Postgres数据库上构建我的DAO层。

但为查询生成的SQL不适合过滤@ElementCollection关系(@OneToMany关系存在类似问题)

我有实体:

@Entity
@Table(name = "doc_documents")
public class Document {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ElementCollection(fetch = FetchType.LAZY)
    @CollectionTable(name = "doc_document_titles",
        joinColumns =
        @JoinColumn(name = "document_id"))
    @Column(name = "title")
    private List<String> titles = new ArrayList<>();
….
)

和存储库接口:

public interface DocumentRepo
        extends JpaRepository <Document, Long>, 
                QueryDslPredicateExecutor<Document> {
}

当我执行查询时:

Predicate crit = qDoc.titles.any().eq("x");
docRepo.findAll(crit);

执行此SQL:

select
    document0_.id as id10_
from
    doc_documents document0_ 
where
    exists (
        select
            1 
        from
            doc_documents document1_ 
        inner join
            doc_titles title2_ 
                on document1_.id= title2_.document_id 
        where
            document1_.id=document0_.id 
            and locthesaur2_.title = ?
    )

但我认为此查询的最佳SQL应该没有额外的内部联接:

select
    document0_.id as id10_
from
    doc_documents document0_ 
where
    exists (
        select
            1 
        from
            doc_titles title2_ 
        where
            title2_.document_id=document0_.id 
            and title2.title= ?
    )

额外的内部联接会严重破坏性能。 是否可以指示QueryDSL生成不同的查询,或者我可能只是做错了什么?

性能问题对我的应用程序至关重要,因此如果没有这种优化,我就无法使用QueryDSL来查询数据库(我的域比我在这里显示的要复杂得多)。

1 个答案:

答案 0 :(得分:0)

谓词在JPQL级别内部翻译成类似的内容

exists (select 1 
        from Document doc2 
        inner join doc2.titles as doc2_titles
        where doc2 = doc and doc2_titles = ?)

不能直接在from部分使用title,因为它不是实体。如果您想出一个更好的方法来表达这一点,请告诉我。

如果OneToMany存在类似问题,请为此创建一张票。