在一对多或者多对多的时候。如果通过一的一方取获得多的一方的数据。除了第一次查询表的数据以外。每获得一条多的一方的数据就查询一次。
如:通过学生表的记录查询成绩表的记录。
一个学生就查询一次,50个学生就查询50次。
如果需要查询50个学生的成绩,需要查询数据库的次数为 第一次查询学生的记录+50次查询成绩的记录。这个情况我们成为 N+1.
//需求:查询所有的学生,以及所有学生都有查询他的成绩
@Test
public void find(){
//1.获得学生信息
EntityManager manager = JpaUtils.getEntityManager();
TypedQuery
List
for (Student student : students) {
System.out.println("学生名:"+student.getStuName());
//每个学生都有获得他的成绩
List
for (Result result : results) {
System.out.println("分数:"+result.getResScore()+",科目:"+result.getResSubject());
}
}
manager.close();
}
对于一些对性能要不高的内部系统,其实N+1问题是可以接受。但对于要求性能高的系统是不可以使用的。
解决N+1问题的方法就是通过连接表查询,在JPQL里面通过fetch 设置生成SQL语句的策略
1 package cn.gzsxt.test;
2
3 import java.util.List;
4
5 import javax.persistence.EntityManager;
6 import javax.persistence.EntityTransaction;
7 import javax.persistence.TypedQuery;
8
9 import org.junit.Test;
10
11 import cn.gzsxt.entity.Result;
12 import cn.gzsxt.entity.Student;
13 import cn.gzsxt.utils.JpaUtils;
14
15 public class StudentTest {
16 //需求:通过ID查询所有学生表的记录,同时查询该学生的对应的成绩的信息!
17 @Test
18 public void findResultByStudent(){
19 EntityManager entityManager = JpaUtils.getEntityManager();
20 TypedQuery<Student> createQuery = entityManager.createQuery("select s from Student s",Student.class);
21 List<Student> students = createQuery.getResultList();
22 for (Student student : students) {
23 System.out.println("学生名:"+student.getStuName());
24 List<Result> results = student.getResults();
25 for (Result result : results) {
26 System.out.println(result.getResSubject()+":"+result.getResScore());
27 }
28 }
29 entityManager.close();
30 }
31 //需求:通过ID查询所有学生表的记录,同时查询该学生的对应的成绩的信息!解决n+1问题
32 @Test
33 public void findResultByStudent2(){
34 EntityManager entityManager = JpaUtils.getEntityManager();
35 TypedQuery<Student> createQuery = entityManager.createQuery("select distinct s from Student s inner join fetch s.results",Student.class);
36 List<Student> students = createQuery.getResultList();
37 for (Student student : students) {
38 System.out.println("学生名:"+student.getStuName());
39 List<Result> results = student.getResults();
40 for (Result result : results) {
41 System.out.println(result.getResSubject()+":"+result.getResScore());
42 }
43 }
44 entityManager.close();
45 }
46 }