MyBatis学习存档(5)——联表查询
之前的数据库操作都是基于一张表进行操作的,若一次查询涉及到多张表,那该如何进行操作呢?
首先明确联表查询的几个关系,大体可以分为一对一和一对多这两种情况,接下来对这两种情况进行分析:
一、建立表、添加数据、反向生成
建立teacher、classes、student三张表,并添加几条数据用于后续操作




进行反向生成
二、一对一联表查询
一个班级(classes)只有一个班主任(teacher),即一对一的关系
仅仅通过反向生成的文件是无法进行联表查询的,因此需要进行一些改动
package com.pojo;
public class Teacher {
private Integer id;
private String name;
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 == null ? null : name.trim();
}
@Override
public String toString() {
return "Teacher [id=" + id + ", name=" + name + "]";
}
}
Teacher类
在Classes类中添加一个teacher的属性,删除多余的teacher_id:
package com.pojo;
public class Classes {
private Integer classId;
private String className;
private Teacher teacher; //一对一对应的teacher
public Integer getClassId() {
return classId;
}
public void setClassId(Integer classId) {
this.classId = classId;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Classes [classId=" + classId + ", className=" + className
+ ", teacher=" + teacher + "]";
}
}
Classes类
修改接口及mapper映射文件:此处有2种方法进行查询
在resultMap节点下添加一个association节点,其配置与resultMap类似,该节点可以用于处理“一对一“的类型关系
package com.mapper;
import com.pojo.Teacher;
public interface TeacherMapper {
Teacher selectTeacherById(Integer id);
}
TeacherMapper.java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mapper.TeacherMapper" >
<resultMap id="BaseResultMap" type="com.pojo.Teacher" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="VARCHAR" />
</resultMap>
<sql id="Base_Column_List" >
id, name
</sql>
<select id="selectTeacherById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from teacher where id=#{id}
</select>
</mapper>
TeacherMapper.xml
package com.mapper;
import com.pojo.Classes;
public interface ClassesMapper {
//方法一
Classes selectByClassId1(Integer classId);
//方法二
Classes selectByClassId2(Integer classId);
}
ClassesMapper.java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mapper.ClassesMapper" > <sql id="Base_Column_List">
class_id,class_name,teacher_id
</sql>
<sql id="classesAndTeacher">
classes.class_id,classes.class_name,teacher.id,teacher.name
</sql>
<!--
方法一:直接嵌套查询
-->
<resultMap id="ClassesMap1" type="com.pojo.Classes" >
<id column="class_id" property="classId" jdbcType="INTEGER" />
<result column="class_name" property="className" jdbcType="VARCHAR" />
<association property="teacher" javaType="com.pojo.Teacher">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
</association>
</resultMap>
<select id="selectByClassId1" resultMap="ClassesMap1" parameterType="java.lang.Integer" >
select
<include refid="classesAndTeacher"/>
from classes LEFT JOIN teacher ON classes.teacher_id=teacher.id where classes.class_id=#{classId}
</select> <!--
方法二:进行2次查询(可使用懒加载)
-->
<resultMap id="ClassesMap2" type="com.pojo.Classes" >
<id column="class_id" property="classId" jdbcType="INTEGER" />
<result column="class_name" property="className" jdbcType="VARCHAR" />
<association property="teacher" javaType="com.pojo.Teacher" column="teacher_id" select="com.mapper.TeacherMapper.selectTeacherById"/>
<!--
若需设置懒加载,需在mybatis-config.xml中添加下列节点(开启懒加载,关闭急加载)
<settings>
开启懒加载
<setting name="lazyLoadingEnabled" value="true"/>
关闭急加载
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
并在association节点中添加fetchType属性并设置为lazy,如下
-->
<!-- <association property="teacher" javaType="com.pojo.Teacher" column="teacher_id" select="com.mapper.TeacherMapper.selectTeacherById" fetchType="lazy"/> -->
</resultMap>
<select id="selectByClassId2" resultMap="ClassesMap2" parameterType="java.lang.Integer">
select
<include refid="Base_Column_List"/>
from classes where class_id=#{id}
</select>
</mapper>
ClassesMapper.xml
编写测试类
package com.test; import java.io.InputStream; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import com.mapper.ClassesMapper;
import com.pojo.Classes; public class TestHasOne { public static void main(String[] args) throws Exception {
//mybatis的核心配置文件
String resource = "mybatis-config.xml";
//使用MyBatis提供的Resources类加载mybatis的配置文件
InputStream is = Resources.getResourceAsStream(resource);
//构建SqlSession的工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//开启SqlSession
SqlSession session = factory.openSession();
//通过映射接口执行操作
ClassesMapper mapper = session.getMapper(ClassesMapper.class);
Classes clazz1 = mapper.selectByClassId1(1);
System.out.println("方法一:" + clazz1);
Classes clazz2 = mapper.selectByClassId2(1);
System.out.println("方法二:" + clazz2);
session.close();
} }
TestHasOne
输出结果如下:

可从日志输出中看出,方法一仅执行了1条查询语句,方法二执行了2条查询语句
三、一对多联表查询
一个班级(classes)中有许多学生(student),即一对多的关系
修改反向生成的文件
删除Student类中多余的cId属性
package com.pojo;
public class Student {
private Integer id;
private String name;
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 == null ? null : name.trim();
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}
Student
在Classes类中添加一个List<Student>类型的students集合
package com.pojo;
import java.util.List;
public class Classes {
private Integer classId;
private String className;
private Teacher teacher; //一对一对应的teacher
private List<Student> students; //一对多对应的students
public Integer getClassId() {
return classId;
}
public void setClassId(Integer classId) {
this.classId = classId;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
@Override
public String toString() {
return "Classes [classId=" + classId + ", className=" + className
+ ", teacher=" + teacher + ", students=" + students + "]";
}
}
Classes
修改接口及mapper映射文件:
在resultMap节点下添加一个association节点,其配置与resultMap类似,该节点可以用于处理“一对多“的类型关系
package com.mapper;
import com.pojo.Student;
public interface StudentMapper {
Student selectStudentById(Integer cId);
}
StudentMapper.java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mapper.StudentMapper" >
<resultMap id="BaseResultMap" type="com.pojo.Student" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="VARCHAR" />
</resultMap>
<sql id="Base_Column_List" >
id, name
</sql>
<select id="selectStudentById" resultMap="BaseResultMap" parameterType="java.lang.Integer">
select
<include refid="Base_Column_List"/>
from student where c_id=#{cId}
</select>
</mapper>
StudentMapper.xml
package com.mapper;
import com.pojo.Classes;
public interface ClassesMapper {
//方法一
Classes selectByClassId1(Integer classId);
//方法二
Classes selectByClassId2(Integer classId);
//一对多查询
Classes selectByClassId3(Integer classId);
}
ClassesMapper.java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mapper.ClassesMapper" > <sql id="Base_Column_List">
class_id,class_name,teacher_id
</sql>
<sql id="classesAndTeacher">
classes.class_id,classes.class_name,teacher.id,teacher.name
</sql>
<sql id="classesAndStudent">
classes.class_id,classes.class_name,student.id,student.name
</sql>
<!--
方法一:直接嵌套查询
-->
<resultMap id="ClassesMap1" type="com.pojo.Classes" >
<id column="class_id" property="classId" jdbcType="INTEGER" />
<result column="class_name" property="className" jdbcType="VARCHAR" />
<association property="teacher" javaType="com.pojo.Teacher">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
</association>
</resultMap>
<select id="selectByClassId1" resultMap="ClassesMap1" parameterType="java.lang.Integer" >
select
<include refid="classesAndTeacher"/>
from classes LEFT JOIN teacher ON classes.teacher_id=teacher.id where classes.class_id=#{classId}
</select> <!--
方法二:进行2次查询(可使用懒加载)
-->
<resultMap id="ClassesMap2" type="com.pojo.Classes" >
<id column="class_id" property="classId" jdbcType="INTEGER" />
<result column="class_name" property="className" jdbcType="VARCHAR" />
<association property="teacher" javaType="com.pojo.Teacher" column="teacher_id" select="com.mapper.TeacherMapper.selectTeacherById"/>
<!--
若需设置懒加载,需在mybatis-config.xml中添加下列节点(开启懒加载,关闭急加载)
<settings>
开启懒加载
<setting name="lazyLoadingEnabled" value="true"/>
关闭急加载
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
并在association节点中添加fetchType属性并设置为lazy,如下
-->
<!-- <association property="teacher" javaType="com.pojo.Teacher" column="teacher_id" select="com.mapper.TeacherMapper.selectTeacherById" fetchType="lazy"/> -->
</resultMap>
<select id="selectByClassId2" resultMap="ClassesMap2" parameterType="java.lang.Integer">
select
<include refid="Base_Column_List"/>
from classes where class_id=#{id}
</select> <!-- 一对多查询 -->
<resultMap id="ClassesMap3" type="com.pojo.Classes" >
<id column="class_id" property="classId" jdbcType="INTEGER" />
<result column="class_name" property="className" jdbcType="VARCHAR" />
<association property="teacher" javaType="com.pojo.Teacher" column="teacher_id" select="com.mapper.TeacherMapper.selectTeacherById"/>
<collection property="students" column="class_id" ofType="com.pojo.Student" select="com.mapper.StudentMapper.selectStudentById"/>
</resultMap>
<select id="selectByClassId3" resultMap="ClassesMap3" parameterType="java.lang.Integer">
select
<include refid="Base_Column_List"/>
from classes where class_id=#{id}
</select>
</mapper>
ClassesMapper.xml
编写测试类
package com.test; import java.io.InputStream; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import com.mapper.ClassesMapper;
import com.pojo.Classes; public class TestHasMany { public static void main(String[] args) throws Exception{
//mybatis的核心配置文件
String resource = "mybatis-config.xml";
//使用MyBatis提供的Resources类加载mybatis的配置文件
InputStream is = Resources.getResourceAsStream(resource);
//构建SqlSession的工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//开启SqlSession
SqlSession session = factory.openSession();
//通过映射接口执行操作
ClassesMapper mapper = session.getMapper(ClassesMapper.class);
Classes clazz = mapper.selectByClassId3(1);
System.out.println(clazz);
} }
TestHasMany
输出结果如下

Classes [classId=1, className=一年1班, teacher=Teacher [id=2, name=教师B], students=[Student [id=1, name=张三], Student [id=2, name=李四], Student [id=3, name=王五]]]
MyBatis学习存档(5)——联表查询的更多相关文章
- MyBatis学习总结——实现关联表查询(转)
原文链接:孤傲苍狼 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关 ...
- MyBatis学习总结(五)——关联表查询的实现
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- mybatis学习 十二 多表查询
Mybatis 实现多表查询方式: (1)业务装配.对两个表编写单表查询语句,在业务(Service)把查询的两个结果进行关联. (2)使用Auto Mapping特性,在实现两表联合查询时通过别名完 ...
- Mybatis学习笔记之---多表查询(1)
Mybatis多表查询(1) (一)举例(用户和账户) 一个用户可以有多个账户 一个账户只能属于一个用户(多个账户也可以属于同一个用户) (二)步骤 1.建立两张表:用户表,账户表,让用户表和账户表之 ...
- Mybatis学习笔记之---多表查询(2)
Mybatis多表查询(2) (一)举例 用户和角色 一个用户可以有多个角色,一个角色可以赋予多个用户 (二)步骤 1.建立两张表:用户表,角色表,让用户表和角色表具有多对多的关系.需要使用中间表,中 ...
- Mybatis学习——一对多关联表查询
1.实体类 public class Student { private int id; private String name; } public class Classes { private i ...
- MyBatis入门学习教程-实现关联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- MyBatis联表查询
MyBatis逆向工程主要用于单表操作,那么需要进行联表操作时,往往需要我们自己去写sql语句. 写sql语句之前,我们先修改一下实体类 Course.java: public class Cours ...
- mybatis 联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
随机推荐
- Echarts——关系图(人民的名义为例,简化)源码
参考博文:https://www.cnblogs.com/emrys5/p/echart-relationship-map.html <!DOCTYPE html> <html> ...
- nginx 配置 nodejs 反向代理
upstream my_nodejs_upstream { server ; keepalive ; } server { listen ; server_name www.my-website.co ...
- Embedded based learning
简单整理了一些嵌入式底层需要接触的相关概念. # CPU CU. Control Unit. send need-clac-data -> ALU clac -> get resul ...
- HTTP之基本认证机制
1. 认证 1.1 HTTP 的质询/响应认证框架 HTTP 提供了一个原生的质询/响应(challenge/response)框架,简化了对用户的认证过程. HTTP 的认证模型如下图所示: Web ...
- ios TCP抓包
1.工具安装 Mac15.1 ,Xcode11.2.1 这一步有个小坑,我第一次执行rvictls -s 提示 rvictl: command not found.Stack Overflow上提供了 ...
- mysql数据库每个表的备份脚本
对mysql数据库中的每张表进行按日期备份,思想是:先把每张表的表名取出取出,然后通过for循环去对每个表进行按日期备份 [root@ZFVM-APP-- backup]# vim dataname. ...
- 记录Redis连接未正确释放,TCP连接过多,造成服务器上部分功能不可用和linux服务器内存一直增加问题
问题1 多人共享开发服务器(windows系统),我们小组有个程序,定时检测mongodb,redis,mysql连接是否正常,程序启动一段时间后,服务器管理人员找到我们说,我们的某个pid的程序把T ...
- P2308 添加括号
P2308 添加括号 题解 一看这题---我能AC 看完这题---我要换题 这题第二问其实就是一个链的石子合并,也就是不用处理环 所以一三问怎么处理??? 数组 mid[ i ][ j ] 记录区间 ...
- vue常用的修饰符
v-model修饰符 <template> <div id="demo14"> <p>-----------------模板语法之修饰符---- ...
- 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_09-webpack研究-webpack介绍
使用vue.js开发大型应用需要使用webpack打包工具,本节研究webpack的使用方法. 1.3.1 webpack介绍 Webpack 是一个前端资源的打包工具,它可以将js.image.cs ...