java面试之n+1问题

Wesley13
• 阅读 598

在一对多或者多对多的时候。如果通过一的一方取获得多的一方的数据。除了第一次查询表的数据以外。每获得一条多的一方的数据就查询一次。

如:通过学生表的记录查询成绩表的记录。

一个学生就查询一次,50个学生就查询50次。

如果需要查询50个学生的成绩,需要查询数据库的次数为 第一次查询学生的记录+50次查询成绩的记录。这个情况我们成为 N+1.

//需求:查询所有的学生,以及所有学生都有查询他的成绩

@Test

public void find(){

//1.获得学生信息

EntityManager manager = JpaUtils.getEntityManager();

TypedQuery query = manager.createQuery("select s from Student s", Student.class);

List students = query.getResultList();

for (Student student : students) {

System.out.println("学生名:"+student.getStuName());

//每个学生都有获得他的成绩

List 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 }
点赞
收藏
评论区
推荐文章
Easter79 Easter79
3年前
sql优化之大数据量分页查询(mysql)
当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时就需要使用分页查询。对于数据库分页查询,也有很多种方法和优化的点。谈优化前的准备工作为了对下面列举的一些优化进行测试,需要使用已有的一张表作为实际例子。表名:order\_history。描述:某个业务的订单历史表。主要字段
kenx kenx
3年前
MySQL查询结果集字符串操作之多行合并与单行分割
前言我们在做项目写sql语句的时候,是否会遇到这样的场景,就是需要把查询出来的多列,按照字符串分割合并成一列显示,或者把存在数据库里面用逗号分隔的一列,查询分成多列呢,常见场景有,文章标签,需要吧查询多个标签合并成一列,等,需要怎么去实现呢,这就涉及到MySQL的字符串操作groupconcat场景再现我想把查询多列数据合并成一列显示用逗号分隔
Wesley13 Wesley13
3年前
SQL 查询:查询学生平均成绩
  编程萌新,因为遇到这么个SQL查询的问题:在一张表A里有如下字段:学生姓名、学科名、学科成绩。写一条SQL语句查出各科平均成绩并按学生姓名分组,按如下格式显示:学生姓名|语文|数学|英语。一开始遇到的时候挺懵的,有印象但是却忘了怎么写了,接下来就是查阅资料并亲自上手测试是否可行~  第一次代码修修改改如下,此时还是在只用一张表来查询(无法实现上述
Stella981 Stella981
3年前
Mybaits一对多映射结果集丢失数据问题
       目前JavaWeb开发使用最多的项目架构还是MVC,数据库持久层使用一般会选择用mybatis或者hibernate框架。对于mybatis和hibernate之间的区别大家自行百度,今天主要是记录下最近使用mybatis开发遇到的一个问题。_问题描述_:A表和B表是一对多的关系,因此在查询的时候使用了mybatis的一对多结
Wesley13 Wesley13
3年前
Mysql 查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
 查询所有课程的成绩第2名到第3名的学生信息及该课程成绩1\.查询课程ID为‘01’的课程的成绩第2名到第3名的学生信息及该课程成绩SELECT  d.,c.排名,c.s_score,c.c_idFROM  (SELECTa.s_id,a.s_score,a.c_id,@i:@i1AS排名FROMs
Wesley13 Wesley13
3年前
mysql2_4
连接查询将多张表进行记录的连接(按照某个指定的条件进行数据拼接)  最终结果是:记录数有可能变化,字段书一定会增加(至少两张表的合并)  连接查询的意义:在用户查看数据的时候,需要显示的数据来自多张表。  连接查询分类sql中将连接查询分成四类:内连接,外连接,自然连接,交叉连接  1.交叉连接:crossjoi
Wesley13 Wesley13
3年前
mysql——索引——概念
一、索引索引由数据库表中一列或者多列组合而成,其作用是提高对表中数据的查询速度。索引是创建在表上面的,是对数据表中一列或者多列的值进行排序的一种结构。通过索引,查询数据时可以不必读完记录的所有信息,而只是查询索引列。索引优点:提高检
Wesley13 Wesley13
3年前
MySQL学习笔记4——DQL
DQL(数据查询语言)一、基本查询1.字段(列)控制1)查询所有列SELECT\FROM表名;\"\"表示查询所有列2)查询指定列SELECT列1\,列2,...,列n\FROM表名;3)让完全重复的记录只显示一次当查询结果中的多行记录一模一样时,只显示一行。一般查询所有列时
百亿规模京东实时浏览记录系统的设计与实现 | 京东云技术团队
浏览记录系统主要用来记录京东用户的实时浏览记录,并提供实时查询浏览数据的功能。在线用户访问一次商品详情页,浏览记录系统就会记录用户的一条浏览数据,并针对该浏览数据进行商品维度去重等一系列处理并存储。然后用户可以通过我的京东或其他入口查询用户的实时浏览商品记录,实时性可以达到毫秒级。目前本系统可以为京东每个用户提供最近200条的浏览记录查询展示。
研发日常踩坑-Mysql分页数据重复 | 京东云技术团队
踩坑描述:写分页查询接口,orderby和limit混用的时候,出现了排序的混乱情况在进行第N页查询时,出现与第一前面页码的数据一样的记录。问题在MySQL中分页查询,我们经常会用limit,如:limit(0,20)表示查询第一页的20条数据,limit