我正在使用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来查询数据库(我的域比我在这里显示的要复杂得多)。
答案 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存在类似问题,请为此创建一张票。