java面试之n+1问题

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

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

一个学生就查询一次,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 1 package cn.gzsxt.test; 2 2 3 3 import java.util.List; 4 4 5 5 import javax.persistence.EntityManager; 6 6 import javax.persistence.EntityTransaction; 7 7 import javax.persistence.TypedQuery; 8 8 9 9 import org.junit.Test; 1010 1111 import cn.gzsxt.entity.Result; 1212 import cn.gzsxt.entity.Student; 1313 import cn.gzsxt.utils.JpaUtils; 1414 1515 public class StudentTest { 1616 //需求:通过ID查询所有学生表的记录,同时查询该学生的对应的成绩的信息! 1717 @Test 1818 public void findResultByStudent(){ 1919 EntityManager entityManager = JpaUtils.getEntityManager(); 2020 TypedQuery<Student> createQuery = entityManager.createQuery("select s from Student s",Student.class); 2121 List<Student> students = createQuery.getResultList(); 2222 for (Student student : students) { 2323 System.out.println("学生名:"+student.getStuName()); 2424 List<Result> results = student.getResults(); 2525 for (Result result : results) { 2626 System.out.println(result.getResSubject()+":"+result.getResScore()); 2727 } 2828 } 2929 entityManager.close(); 3030 } 3131 //需求:通过ID查询所有学生表的记录,同时查询该学生的对应的成绩的信息!解决n+1问题 3232 @Test 3333 public void findResultByStudent2(){ 3434 EntityManager entityManager = JpaUtils.getEntityManager(); 3535 TypedQuery<Student> createQuery = entityManager.createQuery("select distinct s from Student s inner join fetch s.results",Student.class); 3636 List<Student> students = createQuery.getResultList(); 3737 for (Student student : students) { 3838 System.out.println("学生名:"+student.getStuName()); 3939 List<Result> results = student.getResults(); 4040 for (Result result : results) { 4141 System.out.println(result.getResSubject()+":"+result.getResScore()); 4242 } 4343 } 4444 entityManager.close(); 4545 } 4646 }
点赞
收藏

评论区

加载中...

相关推荐

sql优化之大数据量分页查询(mysql)

当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时就需要使用分页查询。对于数据库分页查询,也有很多种方法和优化的点。谈优化前的准备工作为了对下面列举的一些优化进行测试,需要使用已有的一张表作为实际例子。表名:order\_history。描述:某个业务的订单历史表。主要字段

SQL 查询:查询学生平均成绩

  编程萌新,因为遇到这么个SQL查询的问题:在一张表A里有如下字段:学生姓名、学科名、学科成绩。写一条SQL语句查出各科平均成绩并按学生姓名分组,按如下格式显示:学生姓名|语文|数学|英语。一开始遇到的时候挺懵的,有印象但是却忘了怎么写了,接下来就是查阅资料并亲自上手测试是否可行~  第一次代码修修改改如下,此时还是在只用一张表来查询(无法实现上述

MySQL查询结果集字符串操作之多行合并与单行分割

前言我们在做项目写sql语句的时候,是否会遇到这样的场景,就是需要把查询出来的多列,按照字符串分割合并成一列显示,或者把存在数据库里面用逗号分隔的一列,查询分成多列呢,常见场景有,文章标签,需要吧查询多个标签合并成一列,等,需要怎么去实现呢,这就涉及到MySQL的字符串操作groupconcat场景再现我想把查询多列数据合并成一列显示用逗号分隔

Mybaits一对多映射结果集丢失数据问题

       目前JavaWeb开发使用最多的项目架构还是MVC,数据库持久层使用一般会选择用mybatis或者hibernate框架。对于mybatis和hibernate之间的区别大家自行百度,今天主要是记录下最近使用mybatis开发遇到的一个问题。_问题描述_:A表和B表是一对多的关系,因此在查询的时候使用了mybatis的一对多结

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

mysql2_4

连接查询将多张表进行记录的连接(按照某个指定的条件进行数据拼接)  最终结果是:记录数有可能变化,字段书一定会增加(至少两张表的合并)  连接查询的意义:在用户查看数据的时候,需要显示的数据来自多张表。  连接查询分类sql中将连接查询分成四类:内连接,外连接,自然连接,交叉连接  1.交叉连接:crossjoi