Java 为什么连接获取或实体图生成n+;1具有多对多关系?
我试图使用实体图和一些数据,我遇到了n+1查询 我用SpringBoot2.2.6和一些表创建了一个新项目 正如我所理解的,使用Fetch或entitygraph应该只生成一个查询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
@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=?