MyBatis学习总结(五)——关联表查询的实现
一、一对一关联
1.1、提出需求
根据班级id查询班级信息(带老师的信息)
1.2、创建表和数据
创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关系。
- CREATE TABLE teacher(
- t_id INT PRIMARY KEY AUTO_INCREMENT,
- t_name VARCHAR(20)
- );
- CREATE TABLE class(
- c_id INT PRIMARY KEY AUTO_INCREMENT,
- c_name VARCHAR(20),
- teacher_id INT
- );
- ALTER TABLE class ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id) REFERENCES teacher(t_id);
- INSERT INTO teacher(t_name) VALUES('teacher1');
- INSERT INTO teacher(t_name) VALUES('teacher2');
- INSERT INTO class(c_name, teacher_id) VALUES('class_a', 1);
- INSERT INTO class(c_name, teacher_id) VALUES('class_b', 2);
表之间的关系如下:
1.3、创建项目如下Web Project项目(导入jar包)如下:
1.4、定义实体类
1、Teacher类,Teacher类是teacher表对应的实体类。
- package com.myl.entity;
- /**
- * teacher实体类
- * @author myl
- * @date 2018年5月3日 上午7:06:07
- */
- public class Teacher {
- //定义实体类的属性,与teacher表中的字段对应
- private int id; //id===>t_id
- private String name; //name===>t_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;
- }
- @Override
- public String toString() {
- return "Teacher [id=" + id + ", name=" + name + "]";
- }
- }
2、Classes类,Classes类是class表对应的实体类
- package com.myl.entity;
- /**
- * class的实体类
- * @author myl
- * @date 2018年5月3日 上午7:07:14
- */
- public class Classes {
- //定义实体类的属性,与class表中的字段对应
- private int id; //id===>c_id
- private String name; //name===>c_name
- /**
- * class表中有一个teacher_id字段,所以在Classes类中定义一个teacher属性,
- * 用于维护teacher和class之间的一对一关系,通过这个teacher属性就可以知道这个班级是由哪个老师负责的
- */
- private Teacher teacher;
- 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 Teacher getTeacher() {
- return teacher;
- }
- public void setTeacher(Teacher teacher) {
- this.teacher = teacher;
- }
- @Override
- public String toString() {
- return "Classes [id=" + id + ", name=" + name + ", teacher=" + teacher + "]";
- }
- }
1.5、定义sql映射文件classMapper.xml
- <?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,namespace的值习惯上设置成包名+sql映射文件名,这样就能够保证namespace的值是唯一的
- 例如namespace="me.myl.mapping.classMapper"就是me.myl.mapping(包名)+classMapper(classMapper.xml文件去除后缀)
- -->
- <mapper namespace="com.myl.mapping.classMapper">
- <!--
- 根据班级id查询班级信息(带老师的信息)
- ##1. 联表查询
- SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1;
- ##2. 执行两次查询
- SELECT * FROM class WHERE c_id=1; //teacher_id=1
- SELECT * FROM teacher WHERE t_id=1;//使用上面得到的teacher_id
- -->
- <select id="getClass" parameterType="int" resultMap="ClassResultMapper">
- select * from class c,teacher t where c.teacher_id = t.t_id and c_id = #{id}
- </select>
- <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
- <resultMap type="com.myl.entity.Classes" id="ClassResultMapper">
- <id property="id" column="c_id"/>
- <result property="name" column="c_name"/>
- <association property="teacher" javaType="com.myl.entity.Teacher">
- <id property="id" column="t_id"/>
- <result property="name" column="t_name"/>
- </association>
- </resultMap>
- <!--
- 方式二:嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
- SELECT * FROM class WHERE c_id=1;
- SELECT * FROM teacher WHERE t_id=1 //1 是上一个查询得到的teacher_id的值
- -->
- <select id="getClass2" parameterType="int" resultMap="ClassResultMap2">
- select * from class where c_id=#{id}
- </select>
- <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
- <resultMap type="com.myl.entity.Classes" id="ClassResultMap2">
- <id property="id" column="c_id"/>
- <result property="name" column="c_name"/>
- <association property="teacher" column="teacher_id" select="getTeacher"/>
- </resultMap>
- <select id="getTeacher" parameterType="int" resultType="com.myl.entity.Teacher">
- SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id}
- </select>
- </mapper>
数据库连接db.properties配置
- driver=com.mysql.jdbc.Driver
- url=jdbc:mysql://127.0.0.1:3306/mybatis
- username=root
- password=
在mybatisConf.xml文件中注册classMapper.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
- <!-- 引用db.properties配置文件 -->
- <properties resource="db.properties" />
- <environments default="development">
- <environment id="development">
- <transactionManager type="JDBC" />
- <!-- 配置数据库连接信息 -->
- <dataSource type="POOLED">
- <!-- value属性值引用db.properties配置文件中配置的值 -->
- <property name="driver" value="${driver}"/>
- <property name="url" value="${url}"/>
- <property name="username" value="${username}"/>
- <property name="password" value="${password}"/>
- </dataSource>
- </environment>
- </environments>
- <mappers>
- <!--
- 注册userMapper.xml文件,
- userMapper.xml位于me.myl.mapping这个包下,所以resource写成me/myl/mapping/userMapper.xml
- -->
- <mapper resource="com/myl/mapping/classMapper.xml"/>
- </mappers>
- </configuration>
1.6、编写单元测试代码
- package com.myl;
- import org.apache.ibatis.session.SqlSession;
- import org.junit.Test;
- import com.myl.entity.Classes;
- import com.myl.util.MybatisUtil;
- /**
- * 单元测试查询
- * @author myl
- * @date 2018年5月3日 上午6:58:51
- */
- public class Test1 {
- @Test
- public void testGetClass() {
- SqlSession sqlSession = MybatisUtil.getSession();
- //执行查询操作,将查询结果自动封装成Classes对象返回
- Classes clazz = sqlSession.selectOne("getClass",1); //查询class表中id为1的记录
- //使用SqlSession执行完SQL之后需要关闭SqlSession
- sqlSession.close();
- System.out.println(clazz);
- }
- @Test
- public void testGetClass2() {
- SqlSession sqlSession = MybatisUtil.getSession();
- //执行查询操作,将查询结果自动封装成Classes对象返回
- Classes clazz = sqlSession.selectOne("getClass2",1); //查询class表中id为1的记录
- //使用SqlSession执行完SQL之后需要关闭SqlSession
- sqlSession.close();
- System.out.println(clazz);
- }
- }
测试结果
1.7、MyBatis一对一关联查询总结
MyBatis中使用association标签来解决一对一的关联查询,association标签可用的属性如下:
- property:对象属性的名称
- javaType:对象属性的类型
- column:所对应的外键字段名称
- select:使用另一个查询封装的结果
-----------
二、一对多关联
2.1、需求
根据classId查询对应的班级信息,包括学生,老师
2.2、创建表和数据
上面的一对一关联查询演示中,我们已经创建了班级表和教师表,这里再创建一张学生表
- CREATE TABLE student(
- s_id INT PRIMARY KEY AUTO_INCREMENT,
- s_name VARCHAR(20),
- class_id INT
- );
- INSERT INTO student(s_name, class_id) VALUES('student_A', 1);
- INSERT INTO student(s_name, class_id) VALUES('student_B', 1);
- INSERT INTO student(s_name, class_id) VALUES('student_C', 1);
- INSERT INTO student(s_name, class_id) VALUES('student_D', 2);
- INSERT INTO student(s_name, class_id) VALUES('student_E', 2);
- INSERT INTO student(s_name, class_id) VALUES('student_F', 2);
2.3、定义实体类
1、Student类
- package com.myl.entity;
- /**
- * 学生实体类
- * @author myl
- * @date 2018年5月4日 上午7:01:01
- */
- public class Student {
- //定义student属性 和student表中的字段对应
- private int id; //id ==>s_id
- private String name; //name ==>s_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;
- }
- @Override
- public String toString() {
- return "Student [id=" + id + ", name=" + name + "]";
- }
- }
2、修改Classes类,添加一个List<Student> students属性,使用一个List<Student>集合属性表示班级拥有的学生,如下:
- package com.myl.entity;
- import java.util.List;
- /**
- * class的实体类
- * @author myl
- * @date 2018年5月3日 上午7:07:14
- */
- public class Classes {
- //定义实体类的属性,与class表中的字段对应
- private int id; //id===>c_id
- private String name; //name===>c_name
- /**
- * class表中有一个teacher_id字段,所以在Classes类中定义一个teacher属性,
- * 用于维护teacher和class之间的一对一关系,通过这个teacher属性就可以知道这个班级是由哪个老师负责的
- */
- private Teacher teacher;
- //使用一个List<Student>集合属性表示班级拥有的学生
- private List<Student> students;
- 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 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 [id=" + id + ", name=" + name + ", teacher=" + teacher + ", students=" + students + "]";
- }
- }
2.4、修改sql映射文件classMapper.xml
添加如下的SQL映射信息
- <!--
- 根据classId查询对应的班级信息,包括学生,老师
- ##1. 联表查询
- -->
- <select id="getClass3" parameterType="int" resultMap="ClassResultMapper3">
- select * from class c,teacher t, student s where c.teacher_id = t.t_id and s.class_id = c.c_id and c_id = #{id}
- </select>
- <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
- <resultMap type="com.myl.entity.Classes" id="ClassResultMapper3">
- <id property="id" column="c_id"/>
- <result property="name" column="c_name"/>
- <association property="teacher" javaType="com.myl.entity.Teacher">
- <id property="id" column="t_id"/>
- <result property="name" column="t_name"/>
- </association>
- <!-- ofType指定students集合中的对象类型 -->
- <collection property="students" ofType="com.myl.entity.Student">
- <id property="id" column="s_id" />
- <result property="name" column="s_name"/>
- </collection>
- </resultMap>
- <!--
- 方式二:嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
- SELECT * FROM class WHERE c_id=1;
- SELECT * FROM teacher WHERE t_id=1 //1 是上一个查询得到的teacher_id的值
- SELECT * FROM student WHERE class_id=1 //1是第一个查询得到的c_id字段的值
- -->
- <select id="getClass4" parameterType="int" resultMap="ClassResultMapper4">
- select * from class where c_id = #{id}
- </select>
- <resultMap type="com.myl.entity.Classes" id="ClassResultMapper4">
- <id property="id" column="c_id" />
- <result property="name" column="c_name" />
- <association property="teacher" column="teacher_id" javaType="com.myl.entity.Teacher" select="getTeacher2">
- </association>
- <collection property="students" column="c_id" ofType="com.myl.entity.Student" select="getStudent">
- </collection>
- </resultMap>
- <select id="getTeacher2" parameterType="int" resultType="com.myl.entity.Teacher">
- select t_id id, t_name name from teacher where t_id = #{id}
- </select>
- <select id="getStudent" parameterType="int" resultType="com.myl.entity.Student">
- select s_id id, s_name name from student where class_id = #{id}
- </select>
2.5、编写单元测试代码
- package com.myl;
- import org.apache.ibatis.session.SqlSession;
- import org.junit.Test;
- import com.myl.entity.Classes;
- import com.myl.util.MybatisUtil;
- /**
- * 单元测试查询
- * @author myl
- * @date 2018年5月3日 上午6:58:51
- */
- public class Test1 {
- @Test
- public void testGetClass3() {
- SqlSession sqlSession = MybatisUtil.getSession();
- //执行查询操作,将查询结果自动封装成Classes对象返回
- Classes clazz = sqlSession.selectOne("getClass3",1); //查询class表中id为1的记录
- //使用SqlSession执行完SQL之后需要关闭SqlSession
- sqlSession.close();
- System.out.println(clazz);
- }
- @Test
- public void testGetClass4() {
- SqlSession sqlSession = MybatisUtil.getSession();
- //执行查询操作,将查询结果自动封装成Classes对象返回
- Classes clazz = sqlSession.selectOne("getClass4",1); //查询class表中id为1的记录
- //使用SqlSession执行完SQL之后需要关闭SqlSession
- sqlSession.close();
- System.out.println(clazz);
- }
- }
返回结果:
2.6、MyBatis一对多关联查询总结
MyBatis中使用collection标签来解决一对多的关联查询,ofType属性指定集合中元素的对象类型。
MyBatis学习总结(五)——关联表查询的实现的更多相关文章
- MyBatis学习总结——实现关联表查询(转)
原文链接:孤傲苍狼 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关 ...
- Mybatis学习——一对多关联表查询
1.实体类 public class Student { private int id; private String name; } public class Classes { private i ...
- Mybatis源码分析--关联表查询及延迟加载原理(二)
在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...
- MyBatis入门学习教程-实现关联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- mybatis学习 十二 多表查询
Mybatis 实现多表查询方式: (1)业务装配.对两个表编写单表查询语句,在业务(Service)把查询的两个结果进行关联. (2)使用Auto Mapping特性,在实现两表联合查询时通过别名完 ...
- mybatis深入理解(八)-----关联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- Mybatis学习笔记之---多表查询(1)
Mybatis多表查询(1) (一)举例(用户和账户) 一个用户可以有多个账户 一个账户只能属于一个用户(多个账户也可以属于同一个用户) (二)步骤 1.建立两张表:用户表,账户表,让用户表和账户表之 ...
- Mybatis学习笔记之---多表查询(2)
Mybatis多表查询(2) (一)举例 用户和角色 一个用户可以有多个角色,一个角色可以赋予多个用户 (二)步骤 1.建立两张表:用户表,角色表,让用户表和角色表具有多对多的关系.需要使用中间表,中 ...
- Mybatis源码分析--关联表查询及延迟加载(一)
Mybatis提供了关联查询映射的功能. 一.一对一关联
随机推荐
- nginx 的安装、优化、服务器集群
一.安装 下载地址:http://nginx.org 找到 stable 稳定版 安装准备:nginx 依赖于pcre(正则)库,如果没有安装pcre先安装 yum install pcre pcr ...
- oracle(enquences & latches )lock (oracle 锁大全)
资料来自官方文档: https://docs.oracle.com/database/121/CNCPT/consist.htm#CNCPT1333 https://docs.oracle.com/d ...
- python中单例模式的创建
# 单例模式(使用装饰器) def singleton(cls): instance = {} def wrapper(*args,**kwargs): if cls not in instance: ...
- 几个垃圾XSS
遇见帅比厂商就离谱.... 这个厂商就挖了几个反射XSS,幸亏没有浪费太多时间 嗯 有的有waf.有的没有就离谱 可以看见可以解析的,但是他的这个站,遇见关键函数就自己跳转了.然后去寻找下别的标签fu ...
- 从门外汉到腾讯Android高级研发——一个半路出家菜鸟的艰难逆袭之路
我是在去年3月份加入腾讯公司,目前是腾讯公司某技术部门里面的一个小负责人,年薪月薪大税后概30K,谈不上多么厉害,但在回想自己半路出家学习编程,从一个销售到现在终于进入中国互联网顶尖公司,还是有些许感 ...
- netty系列之:文本聊天室
目录 简介 聊天室的工作流程 文本处理器 初始化ChannelHandler 真正的消息处理逻辑 总结 简介 经过之前的系列文章,我们已经知道了netty的运行原理,还介绍了基本的netty服务搭建流 ...
- 1~n数字中1出现的个数
1~n数字中1出现的个数 LeetCode 给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数. 感觉挺有意思 对于一个数,我们先局部分析一下,比如123456,我们考虑百位这个 ...
- 线程休眠_sleep
线程休眠_sleep sleep(时间)指定当前线程阻塞的毫秒数: sleep存在异常InterruptedException: sleep时间到达后线程进入就绪状态: sleep可以模拟网络延时,倒 ...
- 如何不耍流氓的做运维之-SHELL脚本
前言 大家都是文明人,尤其是做运维的,那叫一个斯文啊.怎么能耍流氓呢?赶紧看看,编写SHELL脚本如何能够不耍流氓. 下面的案例,我们以MySQL数据库备份SHELL脚本的案例来进行阐述: 不记录日志 ...
- STM32—SPI读写FLASH
目录 FLASH简介 W25Q64 W25Q64简介 FLASH控制指令 FLASH内部存储结构 代码讲解 读取芯片ID 发送写使能信号 等待FLASH不忙 擦除扇区 写入数据 读取数据 注 FLAS ...