Java 为什么连接获取或实体图生成n+;1具有多对多关系?

Java 为什么连接获取或实体图生成n+;1具有多对多关系?,java,hibernate,spring-boot,spring-mvc,spring-data,Java,Hibernate,Spring Boot,Spring Mvc,Spring Data,我试图使用实体图和一些数据,我遇到了n+1查询 我用SpringBoot2.2.6和一些表创建了一个新项目 正如我所理解的,使用Fetch或entitygraph应该只生成一个查询 @Setter @Getter @Entity @NoArgsConstructor public class Student { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; privat

我试图使用实体图和一些数据,我遇到了n+1查询

我用SpringBoot2.2.6和一些表创建了一个新项目

正如我所理解的,使用Fetch或entitygraph应该只生成一个查询

@Setter
@Getter
@Entity
@NoArgsConstructor
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String firstName;

    private String lastName;

    private String address;

    private LocalDate dateOfBirth;

    @ManyToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.ALL)
    private Level level;

    @ManyToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.ALL)
    private Department department;


    @ManyToMany(cascade = CascadeType.ALL)
    private Set<Formations> formations = new HashSet<>();

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", address='" + address + '\'' +
                ", dateOfBirth=" + dateOfBirth +
                ", level=" + level +
                ", formations=" + formations +
                '}';
    }
若我从addAttributeNodes和Query中删除了表单,它将按预期生成一个查询


需要帮助请

请同时发布生成的查询。您可以在
应用程序.properties
中使用
spring.jpa.show sql=true将它们写入控制台。您正在序列化student-这将初始化惰性关系。如果您将
join fetch f.students
添加到您的join fetch查询中,会有帮助吗?@Antoniossss,我认为所有关系提取模式在运行时都会使用连接提取进行重写。@DarioSeidl否,它会抛出一个错误。所以我想知道为什么在这个案例中添加f.student。正如您所看到的,我的根查询是Student。
 @Entity
 @Data
 @NoArgsConstructor
 @ToString(exclude = "students")
 public class Formations {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;    
    private String name;    
    @ManyToMany(mappedBy = "formations")
    @JsonIgnore
    private Set<Student> students = new HashSet<>();
    public Formations(String name) {
        this.name = name;
    }
}
 @Repository
 public interface StudentRepository extends JpaRepository<Student, Long>, 
 CustomStudentRepository {
 @Query("SELECT s FROM Student s  " +
        " join fetch s.level l " +
        " join fetch s.department d " +
        " join fetch s.formations f " +
        "  where s.id =:id ")
 Student fetchWithFormations(@Param("id") Long id);}
public class StudentRepositoryImpl implements CustomStudentRepository {

@PersistenceContext
private EntityManager em;

private static final String QUERY = " SELECT s FROM Student s join fetch s.formations  where s.id =:id ";

public Student findStudentByEntityGraph(Long id) {
    EntityGraph<Student> graph = this.em.createEntityGraph(Student.class);
    graph.addAttributeNodes("department", "level", "formations");

    return em.createQuery(QUERY, Student.class)
            .setParameter("id", id)
            .setHint("javax.persistence.loadgraph", graph)
            .getSingleResult();
}


public Student findStudentByFetch(Long id) {
    return em.createQuery(QUERY, Student.class).setParameter("id", id).getSingleResult();
}
// Generated Queries, I have 1 student with id 15 associated with 03 formations

Hibernate: select student0_.id as id1_3_0_, formations2_.id as id1_1_1_, department3_.id as id1_0_2_, level4_.id as id1_2_3_, student0_.address as address2_3_0_, student0_.date_of_birth as date_of_3_3_0_, student0_.department as departme6_3_0_, student0_.first_name as first_na4_3_0_, student0_.last_name as last_nam5_3_0_, student0_.level as level7_3_0_, formations2_.name as name2_1_1_, formations1_.students as students1_4_0__, formations1_.formations as formatio2_4_0__, department3_.name as name2_0_2_, level4_.name as name2_2_3_ from student student0_ inner join student_formations formations1_ on student0_.id=formations1_.students inner join formations formations2_ on formations1_.formations=formations2_.id left outer join department department3_ on student0_.department=department3_.id left outer join level level4_ on student0_.level=level4_.id where student0_.id=?
Hibernate: select students0_.formations as formatio2_4_0_, students0_.students as students1_4_0_, student1_.id as id1_3_1_, student1_.address as address2_3_1_, student1_.date_of_birth as date_of_3_3_1_, student1_.department as departme6_3_1_, student1_.first_name as first_na4_3_1_, student1_.last_name as last_nam5_3_1_, student1_.level as level7_3_1_ from student_formations students0_ inner join student student1_ on students0_.students=student1_.id where students0_.formations=?
Hibernate: select students0_.formations as formatio2_4_0_, students0_.students as students1_4_0_, student1_.id as id1_3_1_, student1_.address as address2_3_1_, student1_.date_of_birth as date_of_3_3_1_, student1_.department as departme6_3_1_, student1_.first_name as first_na4_3_1_, student1_.last_name as last_nam5_3_1_, student1_.level as level7_3_1_ from student_formations students0_ inner join student student1_ on students0_.students=student1_.id where students0_.formations=?
Hibernate: select students0_.formations as formatio2_4_0_, students0_.students as students1_4_0_, student1_.id as id1_3_1_, student1_.address as address2_3_1_, student1_.date_of_birth as date_of_3_3_1_, student1_.department as departme6_3_1_, student1_.first_name as first_na4_3_1_, student1_.last_name as last_nam5_3_1_, student1_.level as level7_3_1_ from student_formations students0_ inner join student student1_ on students0_.students=student1_.id where students0_.formations=?