Spring Data JPA + QueryDSL查询优化

时间:2014-02-26 09:40:33

标签: spring jpa spring-data-jpa querydsl

使用与Spring Data JPA集成的QueryDSL时,我遇到了一种奇怪的行为:

我在Project和Person之间有一个ManyToOne关系。如果我按所有者ID(外键)获取属于用户的所有项目,则一切都按预期工作:

QProject project = QProject.project;
QPerson owner = project.owner;
List<Project> projects = from(project).leftJoin(owner).fetch()
    .where(owner.id.eq(id)).list(project);

生成的查询:

select
    project0_.id as id1_1_0_,
    person1_.id as id1_0_1_,
    project0_.creation_date as creation2_1_0_,
    project0_.name as name3_1_0_,
    project0_.owner as owner4_1_0_,
    person1_.name as name2_0_1_
from
    project project0_
left outer join
    person person1_
        on project0_.owner=person1_.id
where
    project0_.owner=?

但是,假设我们希望通过非外键字段(例如所有者的名字)获取属于某个人的所有项目:

QProject project = QProject.project;
QPerson owner = project.owner; 
List<Project> projects = from(project).leftJoin(owner).fetch()
    .where(owner.name.eq(name)).list(project);

在这些情况下,表Person不必要地连接两次(注意person1_和person2 _):

select
    project0_.id as id1_1_0_,
    person1_.id as id1_0_1_,
    project0_.creation_date as creation2_1_0_,
    project0_.name as name3_1_0_,
    project0_.owner as owner4_1_0_,
    person1_.name as name2_0_1_
from
    project project0_
left outer join
    person person1_
        on project0_.owner=person1_.id cross
join
    person person2_
where
    project0_.owner=person2_.id
    and person2_.name=?

知道为什么会这样,以及如何避免它?

1 个答案:

答案 0 :(得分:1)

您需要创建一个别名,以确保在where部分

中重用第一个连接
QProject project = QProject.project;
QPerson owner = new QPerson("owner");
List<Project> projects = from(project)
    .leftJoin(project.owner, owner).fetch()
    .where(owner.name.eq(name))
    .list(project);