Mybatis学习笔记(二)
八、多表联合查询
(一) 多表联合查询概述
在开发过程中单表查询不能满足项目需求分析功能,对于复杂业务来讲,关联的表有几张,甚至几十张并且表与表之间的关系相当复杂。为了能够实业复杂功能业务,就必须进行多表查询,在mybatis中提供了多表查询的结果时映射标签,可以实现表之间的一对一、一对多、多对一、多对多关系映射。
(二) MyBatis实现一对一查询
1. 构建数据库表
person(个人表) IdCard(身份证表)
CREATE TABLE person(
p_id INT NOT NULL AUTO_INCREMENT,
p_name VARCHAR(30),
PRIMARY KEY(p_id)
);#IdCard表
CREATE TABLE idcard(
c_id INT NOT NULL AUTO_INCREMENT,
c_cardno VARCHAR(18),
c_uselife DATE,
c_person_id INT NOT NULL,
PRIMARY KEY(c_id),
FOREIGN KEY(c_person_id) REFERENCES person(p_id),
UNIQUE KEY(c_cardno));INSERT INTO person(p_name) VALUES('张三'),('李四');INSERT INTO idcard(c_cardno,c_uselife,c_person_id)
VALUES('110112199012127821','2029-10-10',1);
INSERT INTO idcard(c_cardno,c_uselife,c_person_id)
VALUES('120114199911103491','2030-12-01',2);
2.准备项目环境

3.嵌套结果方式查询
3.1实体类创建
Person
package com.jn.entity;public class Person {private Integer id;private String name;public Person() {}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Person{" +"id=" + id +", name='" + name + '\'' +'}';}
}
IdCard
package com.jn.entity;import java.util.Date;public class IdCard {private Integer id;private String cardno;private Date useLife;public IdCard() {}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getCardno() {return cardno;}public void setCardno(String cardno) {this.cardno = cardno;}public Date getUserLife() {return useLife;}public void setUserLife(Date userLife) {this.useLife = userLife;}@Overridepublic String toString() {return "IdCard{" +"id=" + id +", cardno='" + cardno + '\'' +", userLife=" + useLife +'}';}
}
3.2编写sql语句
实现查询个人信息时,也要查询个人所对应的身份证信息。
select p.*,c.* from
person p,
idcard c
where p.p_id=c.c_person_id and p.p_id=1;

3.3编写PersonIdCard类
package com.jn.entity;import java.util.Date;public class PersonIdCard extends Person{private String cardno;private Date useLife;public String getCardno() {return cardno;}public void setCardno(String cardno) {this.cardno = cardno;}public Date getUseLife() {return useLife;}public void setUseLife(Date useLife) {this.useLife = useLife;}
}
3.4定义持久层接口
PersonDao
package com.jn.dao;import com.jn.entity.PersonIdCard;public interface PersonDao {public PersonIdCard getPersonById(int id);
}
3.5定义 PersonDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jn.dao.PersonDao"><select id="getPersonById" resultMap="PersonResultMap">SELECT p.*,c.* from person p ,idcard c where p.p_id = c.c_person_id and p.p_id = 1;</select><resultMap id="PersonResultMap" type="PersonIdCard"><id column="p_id" property="id"></id><result column="p_id" property="id"></result><result column="p_name" property="name"></result><result column="c_cardno" property="cardno"></result><result column="c_uselife" property="useLife"></result></resultMap>
</mapper>
3.6创建 PersonTest 测试类
package com.jn.test;import com.jn.dao.PersonDao;
import com.jn.entity.PersonIdCard;
import com.jn.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;public class PersonTest {@Testpublic void testGetPersonById() throws Exception{//获取sqlSession对象SqlSession sqlSession = MyBatisUtils.getSession();//通过sqlSession获取PersonDao的代理对象PersonDao personDao = sqlSession.getMapper(PersonDao.class);PersonIdCard personIdCard = personDao.getPersonById(1);System.out.println(personIdCard);//commitsqlSession.close();MyBatisUtils.close(sqlSession);}
}
3.7测试结果

4.嵌套查询方式
前言
查的到底是什么?
查的是一个对象Person,这个对象不仅包含了Person里面的属性,同时还包含了一个IdCard对象。然后把两个表里面的信息整合以便于后续处理。
4.1添加idCard属性
在person类里面添加idCard属性
package com.jn.entity;public class Person {private Integer id;private String name;private IdCard idCard;public Person() {}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public IdCard getIdCard() {return idCard;}public void setIdCard(IdCard idCard) {this.idCard = idCard;}@Overridepublic String toString() {return "Person{" +"id=" + id +", name='" + name + '\'' +", idCard=" + idCard +'}';}
}
4.2持久层里面添加方法
package com.jn.dao;import com.jn.entity.Person;
import com.jn.entity.PersonIdCard;public interface PersonDao {public PersonIdCard getPersonById(Integer id);//嵌套查询的查询方法public Person getPersonById2(Integer id);
}
4.3持久层接口IdCardDao
package com.jn.dao;import com.jn.entity.Person;public interface IdCardDao {public Person getIdCardByPersonId(Integer id);
}
4.4定义 IdCardDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jn.dao.IdCardDao"><!--查询符合结果的IdCard对象并返回给命名空间IdCardDao下的getIdCardByPersonId函数,然后配合PersonDao.xml进行数据的联合查询
--><select id="getIdCardByPersonId" parameterType="int" resultMap="IdCardResult">select * from idcard where c_person_id = #{id}</select><resultMap id="IdCardResult" type="IdCard"><id column="c_id" property="id"></id><result column="c_id" property="id"></result><result column="c_cardno" property="cardno"></result><result column="c_uselife" property="useLife"></result></resultMap>
</mapper>
4.5PersonDao.xml 配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jn.dao.PersonDao"><!--嵌套结果的查询--><select id="getPersonById" resultMap="PersonResultMap">SELECT p.*,c.* from person p ,idcard c where p.p_id = c.c_person_id and p.p_id = 1;</select><resultMap id="PersonResultMap" type="PersonIdCard"><id column="p_id" property="id"></id><result column="p_id" property="id"></result><result column="p_name" property="name"></result><result column="c_cardno" property="cardno"></result><result column="c_uselife" property="useLife"></result></resultMap><!--嵌套查询的结果。根据id先查询到Person对象里面的字段信息,然后配合IdCard.xml查询返回的IdCard对象进行结合,然后返回一个getPersonById2函数的Person对象--><select id="getPersonById2" parameterType="int" resultMap="PersonResultMap2">select * from person where p_id = #{id}</select><resultMap id="PersonResultMap2" type="Person"><id column="p_id" property="id"></id><result column="p_name" property="name"></result><!--映射Person的复杂字段idCard对象属性--><association property="idCard" javaType="IdCard" column="p_id" select="com.jn.dao.IdCardDao.getIdCardByPersonId"></association></resultMap>
</mapper>
column:表示取上次查询出来的指定列的值,做为select属性所指定的查询的输入值。
select:表示指定的查询.
4.6加入测试方法
//测试嵌套查询@Testpublic void testNestedQueryById() throws Exception{//获取sqlSession对象SqlSession sqlSession = MyBatisUtils.getSession();//通过sqlSession获取PersonDao的代理对象PersonDao personDao = sqlSession.getMapper(PersonDao.class);Person person = personDao.getPersonById2(1);System.out.println(person);MyBatisUtils.close(sqlSession);}
4.7测试结果
到目前为止项目的结构目录

(三)MyBatis实现一对多查询
1.创建数据库表
department(部门表),employee(员工表)同时设定部门和员工表的关系
CREATE TABLE department(
d_id INT NOT NULL AUTO_INCREMENT,
d_name VARCHAR(100),
PRIMARY KEY(d_id)
);CREATE TABLE employee(
e_id INT NOT NULL AUTO_INCREMENT,
e_name VARCHAR(30),
e_gender VARCHAR(6),
e_age INT,
e_depart_id INT,
PRIMARY KEY(e_id),
FOREIGN KEY(e_depart_id) REFERENCES department(d_id)
);
-- 向 department 表中插入数据
INSERT INTO department (d_name) VALUES ('研发部');
INSERT INTO department (d_name) VALUES ('销售部');
INSERT INTO department (d_name) VALUES ('财务部');
INSERT INTO department (d_name) VALUES ('市场部');
INSERT INTO department (d_name) VALUES ('人力资源部');-- 向 employee 表中插入数据
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('张三', '男', 25, 1);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('李四', '女', 30, 1);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('王五', '男', 28, 2);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('赵六', '女', 32, 2);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('孙七', '男', 27, 3);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('周八', '男', 26, 1);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('吴九', '女', 29, 1);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('郑十', '男', 31, 2);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('钱十一', '女', 24, 3);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('刘十二', '男', 33, 4);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('陈十三', '女', 28, 4);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('杨十四', '男', 30, 5);
INSERT INTO employee (e_name, e_gender, e_age, e_depart_id) VALUES ('胡十五', '女', 27, 5);
2.嵌套结果的方式
2.1实体类创建
Department类
package com.jn.entity;public class Department {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
Employee类
package com.jn.entity;public class Employee {private int id;private String name;private String gender;private Integer age;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", name='" + name + '\'' +", gender='" + gender + '\'' +", age=" + age +'}';}
}
2.2编写sql查询语句
select d.*,e.* from department d,employee e where d.d_id=e.e_depart_id and d.d_id=1;

2.3Department加入List
把Employee属性变为List集合作为Department的属性
package com.jn.entity;import java.util.List;public class Department {private int id;private String name;private List<Employee> emps;public Department() {}public int getId(){return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<Employee> getEmps() {return emps;}public void setEmps(List<Employee> emps) {this.emps = emps;}@Overridepublic String toString() {return "Department{" +"id=" + id +", name='" + name + '\'' +", emps=" + emps +'}';}
}
2.4持久层DepartmentDao
package com.jn.dao;import com.jn.entity.Department;public interface DepartmentDao {public Department getDepartById(Integer id);
}
2.5映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jn.dao.DepartmentDao"><select id="getDepartById" parameterType="int" resultMap="getDepartmentMap">select d.*,e.* from department d,employee e where d.d_id=e.e_depart_id and d.d_id=#{id}</select><resultMap id="getDepartmentMap" type="Department"><id column="d_id" property="id"></id><result column="d_name" property="name"></result><collection property="emps" ofType="Employee"><id column="e_id" property="id"></id><result column="e_name" property="name"></result><result column="e_gender" property="gender"></result><result column="e_age" property="age"></result></collection></resultMap>
</mapper>
2.6测试方法
package com.jn.test;import com.jn.dao.DepartmentDao;
import com.jn.entity.Department;
import com.jn.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;public class DepartmentTest {@Testpublic void testGetDepartmentById() throws Exception{//获取sqlSession对象SqlSession sqlSession = MyBatisUtils.getSession();//通过sqlSession对象得到DepartmentDao的接口代理对象DepartmentDao departmentDao = sqlSession.getMapper(DepartmentDao.class);Department department = departmentDao.getDepartById(1);System.out.println(department.getName());department.getEmps().forEach(System.out::println);//closesqlSession.close();}
}
2.7测试结果

3.嵌套查询的方式
3.1定义EmployeeDao
package com.jn.dao;import com.jn.entity.Employee;import java.util.List;public interface EmployeeDao {public List<Employee> getEmployeeById(Integer id);
}
3.2定义 EmployeeDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jn.dao.EmployeeDao"><!--配置employee的查询语句,返回一个Employee对象的集合--><select id="getEmployeeById" parameterType="int" resultMap="getEmployeeResultMap">select * from employee where e_depart_id = #{id}</select><resultMap id="getEmployeeResultMap" type="Employee"><id column="e_id" property="id"></id><result column="e_name" property="name"></result><result column="e_gender" property="gender"></result><result column="e_age" property="age"></result></resultMap>
</mapper>
3.3 DepartmentDao添加
package com.jn.dao;import com.jn.entity.Department;public interface DepartmentDao {public Department getDepartById(Integer id);public Department getDepartById2(Integer id);
}
3.4DepartmentDao.xml添加
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jn.dao.DepartmentDao"><select id="getDepartById" parameterType="int" resultMap="getDepartmentMap">select d.*,e.* from department d,employee e where d.d_id=e.e_depart_id and d.d_id=#{id}</select><resultMap id="getDepartmentMap" type="Department"><id column="d_id" property="id"></id><result column="d_name" property="name"></result><collection property="emps" ofType="Employee"><id column="e_id" property="id"></id><result column="e_name" property="name"></result><result column="e_gender" property="gender"></result><result column="e_age" property="age"></result></collection></resultMap><select id="getDepartById2" parameterType="int" resultMap="getDepartmentMap2">select * from department where d_id=#{id}</select><resultMap id="getDepartmentMap2" type="Department"><id column="d_id" property="id"></id><result column="d_name" property="name"></result><collection property="emps" ofType="Employee" column="d_id" select="com.jn.dao.EmployeeDao.getEmployeeById"></collection></resultMap>
</mapper>
3.5测试方法
//嵌套查询@Testpublic void testGetDepartmentById2() throws Exception{//获取sqlSession对象SqlSession sqlSession = MyBatisUtils.getSession();//通过sqlSession对象得到DepartmentDao的接口代理对象DepartmentDao departmentDao = sqlSession.getMapper(DepartmentDao.class);Department department = departmentDao.getDepartById2(1);System.out.println(department.getName());department.getEmps().forEach(System.out::println);//closesqlSession.close();}
3.6测试结果

(三)MyBatis实现多对多查询
1.创建数据库表
CREATE TABLE student(sid INT NOT NULL AUTO_INCREMENT,sname VARCHAR(30),PRIMARY KEY (sid)
);CREATE TABLE teacher(tid INT NOT NULL AUTO_INCREMENT,tname VARCHAR(30),PRIMARY KEY (tid)
);CREATE TABLE student_teacher(s_id INT NOT NULL,t_id INT NOT NULL,PRIMARY KEY (s_id,t_id),FOREIGN KEY (s_id) REFERENCES student(sid),FOREIGN KEY (t_id) REFERENCES teacher(tid)
);
INSERT INTO student(sname) VALUES('张三'),('李四');
INSERT INTO teacher (tname) VALUES('刘老师'),('李老师');
INSERT INTO student(sname) VALUES('王五'),('赵六');
INSERT INTO teacher(tname) VALUES('张老师'),('王老师');
INSERT INTO student(sname) VALUES('孙七'),('周八');
INSERT INTO teacher(tname) VALUES('陈老师'),('杨老师');
INSERT INTO student(sname) VALUES('吴九'),('郑十');
INSERT INTO teacher(tname) VALUES('马老师'),('胡老师');
INSERT INTO student_teacher(s_id,t_id) VALUES(1,1),(1,2),(2,1),(3,3),(3,4),(4,3),(4,4),(5,5),(5,6),(6,5),(6,6),(7,7),(7,8),(8,7),(8,8);
2.嵌套结果方式
2.1创建数据模型
Student,Teacher,StudentTeacher
package com.jn.entity;public class Student {private int id;private int name;public int getId() {return id;}public void setId(int id) {this.id = id;}public int getName() {return name;}public void setName(int name) {this.name = name;}
}
package com.jn.entity;public class Teacher {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Teacher{" +"id=" + id +", name='" + name + '\'' +'}';}
}
package com.jn.entity;public class StudentTeacher {private int sid;private int tid;public int getSid() {return sid;}public void setSid(int sid) {this.sid = sid;}public int getTid() {return tid;}public void setTid(int tid) {this.tid = tid;}
}
2.2编写多对多的sql语句
select s.*,t.*,st.* from student s,teacher t,student_teacher st where s.sid = st.s_id and st.t_id=t.tid AND s.sid=1;

2.3S中加入List属性
package com.jn.entity;import java.util.List;public class Student {private int id;private String name;private List<StudentTeacher> studentTeacherList;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<StudentTeacher> getStudentTeacherList() {return studentTeacherList;}public void setStudentTeacherList(List<StudentTeacher> studentTeacherList) {this.studentTeacherList = studentTeacherList;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name=" + name +", studentTeacherList=" + studentTeacherList +'}';}
}
2.4ST加入Teacher属性
package com.jn.entity;public class StudentTeacher {private int sid;private int tid;private Teacher teacher;public int getSid() {return sid;}public void setSid(int sid) {this.sid = sid;}public int getTid() {return tid;}public void setTid(int tid) {this.tid = tid;}public Teacher getTeacher() {return teacher;}public void setTeacher(Teacher teacher) {this.teacher = teacher;}@Overridepublic String toString() {return "StudentTeacher{" +"sid=" + sid +", tid=" + tid +", teacher=" + teacher +'}';}
}
2.5tudentDao编写
package com.jn.dao;import com.jn.entity.Student;public interface StudentDao {public Student getStudentById(Integer id);}
2.6SudentDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jn.dao.StudentDao"><select id="getStudentById" parameterType="int" resultMap="getStudentMap">select s.*,t.*,st.* from student s,teacher t,student_teacher st where s.sid = st.s_id and st.t_id=t.tid AND s.sid=#{id}</select><resultMap id="getStudentMap" type="Student"><id column="sid" property="id"></id><result column="sname" property="name"></result><collection property="studentTeacherList" ofType="StudentTeacher"><result column="s_id" property="sid"></result><result column="t_id" property="tid"></result><association property="teacher" javaType="Teacher"><id column="tid" property="id"></id><result column="tname" property="name"></result></association></collection></resultMap>
</mapper>
2.7测试方法
package com.jn.test;import com.jn.dao.StudentDao;
import com.jn.entity.Student;
import com.jn.entity.StudentTeacher;
import com.jn.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.util.List;public class StudentTest {@Testpublic void testGetStudentById()throws Exception{SqlSession sqlSession = MyBatisUtils.getSession();StudentDao studentDao = sqlSession.getMapper(StudentDao.class);Student student = studentDao.getStudentById(1);System.out.println(student.getName());List<StudentTeacher> studentTeacherList = student.getStudentTeacherList();studentTeacherList.forEach(System.out::println);}
}
2.8测试结果

3.嵌套查询方式
3.1TeacherDao
package com.jn.dao;import com.jn.entity.Teacher;public interface TeacherDao {public Teacher getTeacherById(Integer id);
}
3.2TeacherDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jn.dao.TeacherDao"><select id="getTeacherById" parameterType="int" resultType="Teacher">select tid id,tname name from teacher where tid =#{id}</select>
</mapper>
3.3StudentTeacherDao
package com.jn.dao;import com.jn.entity.StudentTeacher;import java.util.List;public interface StudentTeacherDao {public List<StudentTeacher> getStudentTeacherBySid(Integer id);
}
3.4StudentTeacherDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jn.dao.StudentTeacherDao"><select id="getStudentTeacherBySid" parameterType="int" resultMap="getStudentTeacherMap">select * from student_teacher where s_id =#{id}</select><resultMap id="getStudentTeacherMap" type="StudentTeacher"><result column="s_id" property="sid"></result><result column="t_id" property="tid"></result><association property="teacher" column="t_id" javaType="Teacher"select="com.jn.dao.TeacherDao.getTeacherById"></association></resultMap>
</mapper>
3.5StudentDao添加方法
package com.jn.dao;import com.jn.entity.Student;public interface StudentDao {public Student getStudentById(Integer id);public Student getStudentById2(Integer id);}
3.6StudentDao.xml配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jn.dao.StudentDao"><select id="getStudentById" parameterType="int" resultMap="getStudentMap">select s.*,t.*,st.* from student s,teacher t,student_teacher st where s.sid = st.s_id and st.t_id=t.tid AND s.sid=#{id}</select><resultMap id="getStudentMap" type="Student"><id column="sid" property="id"></id><result column="sname" property="name"></result><collection property="studentTeacherList" ofType="StudentTeacher"><result column="s_id" property="sid"></result><result column="t_id" property="tid"></result><association property="teacher" javaType="Teacher"><id column="tid" property="id"></id><result column="tname" property="name"></result></association></collection></resultMap><!--嵌套查询--><select id="getStudentById2" parameterType="int" resultMap="getStudentMap2">select * from student where sid=#{id}</select><resultMap id="getStudentMap2" type="Student"><id column="sid" property="id"></id><result column="sname" property="name"></result><collection property="studentTeacherList" ofType="StudentTeacher" column="sid"select="com.jn.dao.StudentTeacherDao.getStudentTeacherBySid"></collection></resultMap></mapper>
3.7测试方法
//多对多的嵌套测试@Testpublic void testGetStudentById2()throws Exception{SqlSession sqlSession = MyBatisUtils.getSession();StudentDao studentDao = sqlSession.getMapper(StudentDao.class);Student student = studentDao.getStudentById2(1);System.out.println(student.getName());List<StudentTeacher> studentTeacherList = student.getStudentTeacherList();studentTeacherList.forEach(System.out::println);sqlSession.close();}
3.8测试结果

九、延迟加载策略
(一)简介
1.什么是延迟加载?
延迟加载(lazy load)是(也称为懒加载)关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。
延迟加载,可以简单理解为,只有在使用的时候,才会发出sql语句进行查询。
2.为什么要使用延迟加载?
减少访问数据库的频率,我们要访问的数据量过大时,明显用缓存不太合适,因为内存容量有限为了减少并发量,减少系统资源的消耗。
(二)局部延时加载
注意:只有在嵌套查询的时候才能用到延时加载
在mybatis中使用resultMap来实现一对一,一对多,多对多关系的操作。主要是通过 association、collection 实现一对一及一对多映射。association、collection 具备延迟加载功能。
1.现象演示
在进行查询上述Employee与Department关联信息的时候,正常查询结果:
显示了两条sql语句的查询
然后把department.getEmps().forEach(System.out::println);给注释了查看结果
还是查询了两条sql语句

2.局部解决
</resultMap>
相关联的查询标签上加 fetchType=”lazy”
fetchType默认值为eager 立即加载,Lazy为延时加载。

然后查看结果:
发现只执行了一条sql语句

然后不进行注释查看结果 :
正常执行

(三)全局延时加载
如果希望所有关联都需要延时加载,可以在mybatis的核心配置文件中进行配置,不用在collection或association中指定。默认全局开启。
1.配置setting
<settings>
<!--开启延时加载开关-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--关闭立即加载,实施按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>

2.测试
测试正常

相关文章:
Mybatis学习笔记(二)
八、多表联合查询 (一) 多表联合查询概述 在开发过程中单表查询不能满足项目需求分析功能,对于复杂业务来讲,关联的表有几张,甚至几十张并且表与表之间的关系相当复杂。为了能够实业复杂功能业务,就必须进行多表查询,…...
Google“Big Sleep“人工智能项目发现真实软件漏洞
据Google研究人员称,该公司的一个人工智能项目足够聪明,能够自行发现现实世界中的软件漏洞;Google的人工智能项目最近在开源数据库引擎 SQLite 中发现了一个之前未知的可利用漏洞。 该公司随后在正式软件发布之前报告了这一漏洞,这…...
npm入门教程5:package.json
一、package.json 文件的作用 依赖管理:列出项目所依赖的包(库)及其版本,便于其他开发者或自动化工具快速安装和更新这些依赖。元数据描述:提供项目的描述、作者、许可证等元信息,有助于项目的管理和维护。…...
docker-高级(待补图)
文章目录 数据卷(Volume)介绍查看方法删除方法绑定方法匿名绑定具名绑定Bind Mount 数据卷管理 网络bridge(桥接模式 默认)HOST(主机模式)Nonecontainer(指定一个容器进行关联网络共享)自定义(推荐)docker network 命令创建网络docker network create 实例展示-自定义实例展示-…...
Qt 文件目录操作
Qt 文件目录操作 QDir 类提供访问系统目录结构 QDir 类提供对目录结构及其内容的访问。QDir 用于操作路径名、访问有关路径和文件的信息以及操作底层文件系统。它还可以用于访问 Qt 的资源系统。 Qt 使用“/”作为通用目录分隔符,与“/”在 URL 中用作路径分隔符…...
Pandas 数据清洗
1.数据清洗定义 数据清洗是对一些没有用的数据进行处理的过程。很多数据集存在数据缺失、数据格式错误、错误数据或重复数据的情况,如果要使数据分析更加准确,就需要对这些没有用的数据进行处理。 2.清洗空值 DataFrame.dropna(axis0, howany, threshN…...
IO学习笔记
当前需求,希望进行游戏可以保存游戏进度,可以将游戏的进度保存到一个文本文件,每一次打完游戏更新文本内容,下一次打游戏读取游戏进度,这里就涉及到两个知识IO流和File的知识。 File类 概述 java.io.File 类是文件…...
汇编练习-1
1、要求 练习要求引自《汇编语言-第4版》实验10.3(P209页) -编程,将data段中的数据,以10进制的形式显示出来 data segment dw 123,12666,1,8,3,38 data ends 2、实现代码(可惜没找到csdn对8086汇编显示方式) assume cs:codedata segmentdw 16 dup(0) ;除…...
初识二叉树( 二)
初识二叉树 二 实现链式结构二叉树前中后序遍历遍历规则代码实现 结点个数以及高度等层序遍历判断是否为完全二叉树 实现链式结构二叉树 ⽤链表来表示⼀棵二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针…...
AcWing1077-cnblog
问题背景 给定一个树形结构的图,每个节点代表一个地点,每个节点有一个守卫的代价。我们希望以最低的代价在树的节点上放置守卫,使得整棵树的所有节点都被监控。可以通过三种方式覆盖一个节点: 由父节点监控。由子节点监控。自己…...
五、SpringBoot3实战(1)
一、SpringBoot3介绍 1.1 SpringBoot3简介 SpringBoot版本:3.0.5 https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started.introducing-spring-boot 到目前为止,你已经学习了多种配置Spring程序的方式…...
练习LabVIEW第三十三题
学习目标: 刚学了LabVIEW,在网上找了些题,练习一下LabVIEW,有不对不好不足的地方欢迎指正! 第三十三题: 用labview编写一个判断素数的程序 开始编写: LabVIEW判断素数,首先要搞…...
如何在服务器端对PDF和图像进行OCR处理
介绍 今天我想和大家分享一个我在研究技术资料时发现的很好玩的东西——Tesseract。这不仅仅是一个普通的库,而是一个用C语言编写的OCR神器,能够识别一大堆不同国家的语言。我一直在寻找能够处理各种文档的工具,而Tesseract就像是给了我一把…...
Windows 下实验视频降噪算法 MeshFlow 详细教程
MeshFlow视频降噪算法 Meshflow 视频降噪算法来自于 2017 年电子科技大学一篇高质量论文。 该论文提出了一个新的运动模型MeshFlow,它是一个空间平滑的稀疏运动场 (spatially smooth sparse motion field),其运动矢量 (motion vectors) 仅在网格顶点 (m…...
Python入门:如何正确的控制Python异步并发量(制并发量的关键技巧与易错点解析)
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 异步并发量控制 📒📝 Python异步并发简介📝 为什么要限制并发量🎈 资源管理🎈 服务稳定性📝 新手容易犯的错误🎈 忽略并发量限制🎈 错误设置并发量📝 设置并发量要注意的事情🎈 了解任务类型🎈 考虑系统资…...
qt QCheckBox详解
QCheckBox 是 Qt 框架中的一个控件,用于创建复选框,允许用户进行选择和取消选择。它通常用于表单、设置界面和任何需要用户选择的场景。 QCheckBox继承自QAbstractButton类,因此继承了按钮的特性。它表示一个复选框,用户可以通过…...
PAT甲级-1041 Be Unique
题目 题目大意 从一组数字中选出第一个唯一出现的数,输出该数。如果没有,则输出None。 思路 哈希的思想,将数值作为索引,对应该数值出现的次数,然后遍历数组即可。 注意第一个数字是指数字的个数,不是数…...
【jvm】如何设置堆内存大小
目录 1. 使用命令行参数设置2. idea中设置3. 注意事项 1. 使用命令行参数设置 1.在Java命令后添加-Xms和-Xmx参数。2.-Xms参数用于设置JVM的初始堆内存大小,等价于-XX:InitialHeapSize。3.-Xmx参数用于设置JVM的最大堆内存大小,等价于-XX:MaxHeapSize。…...
kernel源码分析 do_msgsnd read_msg
笔者分析的源码是v 5.11.22 链接:msg.c - ipc/msg.c - Linux source code v5.11.22 - Bootlin do_msgsnd static long do_msgsnd(int msqid, long mtype, void __user *mtext,size_t msgsz, int msgflg) {struct msg_queue *msq;struct msg_msg *msg;int err;str…...
掌握 CTE 技巧,实现连续日期和月份的 SQL 报表统计
在 SQL 查询中,报表统计往往涉及到特定时间段内的数据汇总,如每日、每月的销售数据等。然而,面对缺少数据的日期或月份,传统 SQL 查询可能会直接跳过这些日期,使得输出的报表在视觉上并不连续。本文将展示如何利用 CTE…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
