Spring Data JPA + QueryDSL Query optimization
-
21-12-2019 - |
Pergunta
I have come across a weird behaviour when using QueryDSL integrated with Spring Data JPA:
I have a ManyToOne relation between Project and Person. If I get all the projects belonging to a user by owner id (foreign key) everything works as expected:
QProject project = QProject.project;
QPerson owner = project.owner;
List<Project> projects = from(project).leftJoin(owner).fetch()
.where(owner.id.eq(id)).list(project);
Generated query:
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=?
However, let's say we want to get all the projects belonging to a person by a field that isn't the foreign key (for instance the owner's name):
QProject project = QProject.project;
QPerson owner = project.owner;
List<Project> projects = from(project).leftJoin(owner).fetch()
.where(owner.name.eq(name)).list(project);
In these cases, the table Person is joined twice unnecessarily (notice person1_ and 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=?
Any idea why this is happening and how to avoid it?
Solução
You need to create an alias to ensure that the first join is reused in the where part
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);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow