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.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
随机推荐
- Python2.7编码问题:UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position...解决方法
解决方法: 在Python程序最前面加上以下语句: import sys reload(sys) sys.setdefaultencoding('utf-8')
- cs配合msf批量探测内网MS17-010漏洞
第一步 Cobalt strike 派生 shell 给 MSF(前提有个beacon shell) 第二步 选择要派生的beacon,右键-->增加会话,选择刚刚配置的foreign监听器 第 ...
- 【Robot Framework 项目实战 03】使用脚本自动生成统一格式的RF自动化用例
背景 虽然大家都已经使用了统一的关键字,但是在检查了一些测试用例之后,还是发现因为大家对RF的熟悉程度不一导致的测试用例颗粒度差异很大的情况:而且在手动方式转化测试用例过程中,有不少工作是完全重复的且 ...
- 添加sql距离现在多久以前时间条件
UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(add_time)<=25200 其中now()是现在时间 add_time是其他时间点 25200:是秒,现在和ad ...
- SpringBoot保存数据报错:could not execute statement; SQL [n/a]; constraint [PRIMARY];nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
使用SpringBoot做JAVA开发时,用Repository.save();保存数据的时候遇到了报错: could not execute statement; SQL [n/a]; constr ...
- python将py文件转换为pyc
python -m py_compile lib/ylpy.py python -m py_compile lib/ylpy.py python 一个.py文件如何调用另一个.py文件中的类和函数 A ...
- Flask中current_app和g对象
Flask零基础到项目实战(七)请求方法.g对象和钩子函数 一.get方法 二.post方法 post请求在模板中要注意几点: input标签中,要写name来标识这个value的key,方便后台 ...
- 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_11.RabbitMQ研究-工作模式-路由工作模式测试
先常见生产者 复制02的代码 先改一下交换机的名称 还需要制定routingKey.因为是两个消息 所以指定了两个routingKey 这里修改为当前指定的交换机名称 交换机和队列在绑定的时候指定我们 ...
- React Native使用code-push实现热更新
这里就不记录了,下面的传送门介绍的通俗易懂,很详细,一步一步很容易实现成功. http://www.jianshu.com/p/f8689ccf0007
- Vue 2.x指令综合小练习
实现效果如下: 代码实现如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset ...