-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Issue: Redundant JOIN
Generated with @EntityGraph
in Spring Data JPA Query Methods
When using @EntityGraph
in a repository method that relies on query generation by method name (without explicitly defining a query using @Query
or @NamedQuery
), redundant JOIN
statements are generated if the method name references a relationship that is also included in the attributePaths
of @EntityGraph
.
Environment:
- Java 21
- Spring Boot 3.4.0 (Spring Data 3.4.0)
Steps to Reproduce:
You can reproduce this issue using this sample project. The project includes two test cases, one of which fails due to the issue.
I captured the generated SQL statements using a Hibernate interceptor and verified the occurrence count of JOIN
operations.
Entities:
Here are the entity definitions:
@Setter
@Getter
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Nationalized
@Column(length = 255, unique = true, nullable = false)
private String name;
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Company company;
}
@Setter
@Getter
@Entity
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Nationalized
@Column(length = 255, unique = true, nullable = false)
private String name;
private boolean enable;
}
Repository Methods:
The EmployeeRepository
contains the following two methods:
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
@EntityGraph(attributePaths = "company")
Set<Employee> findAllByCompanyEnableIsTrue();
@EntityGraph(attributePaths = "company")
@Query("""
SELECT e
FROM Employee e
WHERE e.company.enable
""")
Set<Employee> findAllByCompanyEnableIsTrueUsingQuery();
}
Generated SQL Queries:
For the first method (findAllByCompanyEnableIsTrue
), which relies on the method name for query generation, the following SQL is generated:
select
e1_0.id,
e1_0.company_id,
c2_0.id,
c2_0.enable,
c2_0.name,
e1_0.name
from employee e1_0
join company c1_0 on c1_0.id = e1_0.company_id
join company c2_0 on c2_0.id = e1_0.company_id
where c1_0.enable
As shown, there is a redundant JOIN
.
However, for the second method (findAllByCompanyEnableIsTrueUsingQuery
), which uses an explicitly defined query, the generated SQL is:
select
e1_0.id,
e1_0.company_id,
c1_0.id,
c1_0.enable,
c1_0.name,
e1_0.name
from employee e1_0
join company c1_0 on c1_0.id = e1_0.company_id
where c1_0.enable
This query avoids the redundant JOIN
.
Expected Behavior:
The query generated for the method using the method name (findAllByCompanyEnableIsTrue
) should avoid redundant JOIN
statements, similar to the query generated by findAllByCompanyEnableIsTrueUsingQuery
.
Observed Behavior:
Using @EntityGraph
with query methods generated by method name causes redundant JOIN
operations when a relationship is referenced in both the method name and the attributePaths
of @EntityGraph
.
Additional Information:
Please let me know if further clarification or additional examples are needed.