在一對多或者多對多的時候。如果通過一的一方取獲得多的一方的數據。除了第一次查詢表的數據以外。每獲得一條多的一方的數據就查詢一次。 如:通過學生表的記錄查詢成績表的記錄。 一個學生就查詢一次,50個學生就查詢50次。 如果需要查詢50個學生的成績,需要查詢資料庫的次數為 第一次查詢學生的記錄+50次查 ...
在一對多或者多對多的時候。如果通過一的一方取獲得多的一方的數據。除了第一次查詢表的數據以外。每獲得一條多的一方的數據就查詢一次。
如:通過學生表的記錄查詢成績表的記錄。
一個學生就查詢一次,50個學生就查詢50次。
如果需要查詢50個學生的成績,需要查詢資料庫的次數為 第一次查詢學生的記錄+50次查詢成績的記錄。這個情況我們成為 N+1.
//需求:查詢所有的學生,以及所有學生都有查詢他的成績
@Test
public void find(){
//1.獲得學生信息
EntityManager manager = JpaUtils.getEntityManager();
TypedQuery<Student> query = manager.createQuery("select s from Student s", Student.class);
List<Student> students = query.getResultList();
for (Student student : students) {
System.out.println("學生名:"+student.getStuName());
//每個學生都有獲得他的成績
List<Result> results = student.getResults();
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 }