目录
今天学习的课程是mybatis中的多表查询,SQL中的多表查询主要有一对多,一对一,多对多, 本章主要讲解的是多表联查和加上懒加载的多表查询 所以讲解的就是对一和对多
数据准备
数据库准备
create table classes
(
cid int auto_increment comment '班级主键id'
primary key,
cname varchar(10) not null comment '班级名称'
);
create table student
(
id int auto_increment comment '主键id
'
primary key,
name varchar(10) not null comment '姓名',
age tinyint not null comment '年龄',
cid int not null comment '班级id'
);
实体类
package com.example.pojo;
import lombok.Data;
/**
* @author:Dikk
* @create: 2023-06-18 19:34
* @Description: Student
*/
@Data
public class Student {
/**
* 学生id
*/
private Integer id;
/**
* 学生姓名
*/
private String name;
/**
* 学生年龄
*/
private Integer age;
/**
* 学生所属班级
*/
private Classes classes;
}
package com.example.pojo;
import lombok.Data;
import java.util.List;
/**
* @author:Dikk
* @create: 2023-06-18 19:35
* @Description: Classes
*/
@Data
public class Classes {
/**
* 班级id
*/
private Integer cid;
/**
* 班级名称
*/
private String cname;
/**
* 班级对应的学生集合
*/
private List<Student> studentList;
}
src中的mapper层接口
package com.example.mapper;
import com.example.pojo.Classes;
import org.apache.ibatis.annotations.Mapper;
/**
* @author:Dikk
* @create: 2023-06-18 19:24
* @Description: ClassesMapper
*/
@Mapper
public interface ClassesMapper {
/**
* 根据班级id查询班级信息
*
* @param cid
* @return
*/
Classes selectByCid(Integer cid);
/**
* 根据班级id查询班级信息 懒加载使用
*
* @param cid
* @return
*/
Classes selectClassesByCid(Integer cid);
/**
* 根据cid查询班级 懒加载
* @return
*/
Classes selectByCidLazy(Integer cid);
}
package com.example.mapper;
import com.example.pojo.Student;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author:Dikk
* @create: 2023-06-18 19:24
* @Description: StudentMapper
*/
@Mapper
public interface StudentMapper {
/**
* 查询全部学生 懒加载
*
* @return
*/
List<Student> selectAllLazy();
/**
* 根据班级id查询学生
*
* @param cid
* @return
*/
List<Student> selectByCid(Integer cid);
/**
* 查询全部学生
*
* @return
*/
List<Student> selectAll();
}
1.对一的多表查询
mybatis中的mapper.xml
<!--
id="classesMap" 映射map的名称 type 返回值的数据类型
这里的<id ====> 和 <result ====> 使用效果是一样的,只是语义不同,id为主键
column 表示为表中的字段名 property 为实体类中对应的属性
collection 在MyBatis中,collection是一个关键字,用于指定一个实体类与另一个实体类之间的关联关系。它通常用于一对多或多对多的关系中。
property 关联的实体类对象 ofType 关联实体类的全类名
此处的id和result和上面用法相同
-->
<resultMap id="classesMap" type="com.example.pojo.Classes">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
<collection property="studentList" ofType="com.example.pojo.Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
</collection>
</resultMap>
<select id="selectByCid" resultMap="classesMap">
select *
from classes c,
student s
where c.cid = #{cid}
and c.cid = s.cid;
</select>
xml中的studentmap标签的详细注解及作用讲解:
id="studentMap" 映射map的名称 type 返回值的数据类型 这里的<id ====> 和 <result ====> 使用效果是一样的,只是语义不同,id为主键 column 表示为表中的字段名 property 为实体类中对应的属性 association 在MyBatis中,association是一个关键字,用于指定一个实体类与另一个实体类之间的关联关系。 property 关联的实体类对象 javaType 关联实体类的全类名 此处的id和result和上面用法相同
其中的对应关系如下图
方法测试
可以看到查到了所有学生的信息以及对应的班级信息
对多查询的多表查询
mybatis中的mapper.xml
<!--
id="classesMap" 映射map的名称 type 返回值的数据类型
这里的<id ====> 和 <result ====> 使用效果是一样的,只是语义不同,id为主键
column 表示为表中的字段名 property 为实体类中对应的属性
collection 在MyBatis中,collection是一个关键字,用于指定一个实体类与另一个实体类之间的关联关系。它通常用于一对多或多对多的关系中。
property 关联的实体类对象 ofType 关联实体类的全类名
此处的id和result和上面用法相同
-->
<resultMap id="classesMap" type="com.example.pojo.Classes">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
<collection property="studentList" ofType="com.example.pojo.Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
</collection>
</resultMap>
<select id="selectByCid" resultMap="classesMap">
select *
from classes c,
student s
where c.cid = #{cid}
and c.cid = s.cid;
</select>
xml中的classesMap中的标签详解:
id="classesMap" 映射map的名称 type 返回值的数据类型 这里的<id ====> 和 <result ====> 使用效果是一样的,只是语义不同,id为主键 column 表示为表中的字段名 property 为实体类中对应的属性 collection 在MyBatis中,collection是一个关键字,用于指定一个实体类与另一个实体类之间的关联关系。它通常用于一对多或多对多的关系中。 property 关联的实体类对象 ofType 关联实体类的全类名 此处的id和result和上面用法相同
对应关系如下
方法测试
从测试结果中可以看出查出班级和班级对应的学生信息集合
懒加载 :
这时我们发现,在查询过程中,在班级查询的时候无论我们是否需要学生信息的时候,SQL语句都会帮我们查询,这时候就需要引入懒加载,什么是懒加载
MyBatis中的懒加载(Lazy Loading)是一种延迟加载机制,用于优化数据访问性能。它的核心思想是在真正需要访问数据时才去执行SQL语句,以减少不必要的查询操作。
具体来说,当一个对象被查询出来后,如果该对象有关联的其他对象(比如一对多关系),默认情况下MyBatis会立即从数据库中查询这些关联对象并将其填充到该对象中。但如果使用了懒加载,则只有在真正访问这些关联对象时才会触发查询操作,否则它们就只是空值或者null。
使用懒加载可以减少不必要的数据库查询,提高系统的性能和响应速度。但需要注意的是,懒加载可能会带来一些额外的开销,比如增加了代码复杂度以及可能导致多次查询等问题,在实际使用时需要谨慎考虑。
以下,我们测试懒加载的具体使用效果
对一多表查询 懒加载
mybatis中的xml
<resultMap id="studentMapLazy" type="com.example.pojo.Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<association property="classes"
javaType="com.example.pojo.Classes"
column="cid"
select="com.example.mapper.ClassesMapper.selectByCid"
fetchType="lazy"/>
</resultMap>
<select id="selectAllLazy" resultMap="studentMapLazy">
select *
from student;
</select>
其中开启懒加载是用 fetchType标签, lazy则表示为懒加载
其中需要重点注意的是 association标签中的 colum标签中的cid表示的并不是classes类中的cid属性,而是student表中的cid字段
方法测试
尝试进行懒加载,只查询学生的信息,不查询班级的信息
由上面的sql语句可以看到,我们只需要学生的信息,而不需要班级信息时,sql就只会执行查询学生部分的语句
对多的多表查询 懒加载
mybatis中的xml
<resultMap id="classesMapLazy" type="com.example.pojo.Classes">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
<collection property="studentList"
ofType="com.example.pojo.Student"
column="cid"
select="com.example.mapper.StudentMapper.selectByCid"
fetchType="lazy">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
</collection>
</resultMap>
<select id="selectByCidLazy" resultMap="classesMapLazy">
select *
from classes
where cid = #{cid};
</select>
方法测试
懒加载测试查询全部信息
以上就是懒加载和多表联查的全部学习内容,共勉
联想:
在学习的过程中,又发现了一些问题,既然在方法中都已经通过SQL查出了班级的所有信息,那是如何执行懒加载的,通过在查询语句和sout语句中间加入log打印日志并查看控制台的输出日志中发现,查询班级的SQL语句是必须执行的,懒加载的是否执行则是看下面的语句中是否有使用到,根据使用的情况再选择是否加载
如有错误,希望在评论区指正,阿里嘎多