MyBatis学习总结(五)——关联表查询的实现

时间:2022-05-07 20:54:36

一、一对一关联

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);

表之间的关系如下:

MyBatis学习总结(五)——关联表查询的实现

1.3、创建项目如下Web Project项目(导入jar包)如下:

MyBatis学习总结(五)——关联表查询的实现

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);
} }

测试结果

MyBatis学习总结(五)——关联表查询的实现

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);

MyBatis学习总结(五)——关联表查询的实现

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);
} }

返回结果:

MyBatis学习总结(五)——关联表查询的实现

2.6、MyBatis一对多关联查询总结

  MyBatis中使用collection标签来解决一对多的关联查询,ofType属性指定集合中元素的对象类型。

MyBatis学习总结(五)——关联表查询的实现的更多相关文章

  1. MyBatis学习总结——实现关联表查询&lpar;转&rpar;

    原文链接:孤傲苍狼 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关 ...

  2. Mybatis学习——一对多关联表查询

    1.实体类 public class Student { private int id; private String name; } public class Classes { private i ...

  3. Mybatis源码分析--关联表查询及延迟加载原理(二)

    在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...

  4. MyBatis入门学习教程-实现关联表查询

    一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...

  5. mybatis学习 十二 多表查询

    Mybatis 实现多表查询方式: (1)业务装配.对两个表编写单表查询语句,在业务(Service)把查询的两个结果进行关联. (2)使用Auto Mapping特性,在实现两表联合查询时通过别名完 ...

  6. mybatis深入理解&lpar;八&rpar;-----关联表查询

    一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...

  7. Mybatis学习笔记之---多表查询&lpar;1&rpar;

    Mybatis多表查询(1) (一)举例(用户和账户) 一个用户可以有多个账户 一个账户只能属于一个用户(多个账户也可以属于同一个用户) (二)步骤 1.建立两张表:用户表,账户表,让用户表和账户表之 ...

  8. Mybatis学习笔记之---多表查询&lpar;2&rpar;

    Mybatis多表查询(2) (一)举例 用户和角色 一个用户可以有多个角色,一个角色可以赋予多个用户 (二)步骤 1.建立两张表:用户表,角色表,让用户表和角色表具有多对多的关系.需要使用中间表,中 ...

  9. Mybatis源码分析--关联表查询及延迟加载(一)

    Mybatis提供了关联查询映射的功能. 一.一对一关联

随机推荐

  1. PGA

    Server Process PGA   1.PGA作用   2.PGA構成      1)private sql area      2)session memory          3)sql ...

  2. SQL Server如何添加登录名

    1.电脑上如果安装有SQL Server,我们在开始里面打开SQL Server Management Studio,或者以桌面的快捷方式等打开SQL Server. 2.首先以Windows身份验证 ...

  3. Android使用OkHttp实现带进度的上传下载

    先贴上MainActivity.java package cn.edu.zafu.sample; import android.os.Bundle; import android.support.v7 ...

  4. 简明python教程 --C&plus;&plus;程序员的视角(八):标准库

    os模块 这个模块包含普遍的操作系统功能. 如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的.一个例子就是使用os.sep可以取代操作系统特定的路径分割符. os.system() 执行li ...

  5. apache-tomcat-7 设置最大上传&period;war文件大小&lbrack;zhuan&rsqb;

    在利用tomcat自带的主机管理页面进行WAR包部署的时候,提示文件太大,无法上传.   解决方案: 找到 /usr/local/apache-tomcat7/webapps/manager/WEB- ...

  6. &lbrack;BZOJ1543&rsqb; 生成树计数 &lpar;Kruskal&rpar;

    Description 给定一个连通的带边权的图(允许自环和重边),求不同的最小生成树个数.两个生成树不同当它们所用的边的序号不同,换句话说,重边算多次. Input 第一行n,m,表示点数和边数(1 ...

  7. 彻底搞清楚 RxJava 是什么东西

    其实从rxjava14年出现到现在,我是去年从一个朋友那里听到的,特别是随着现在app项目越来越大,分层越来越不明确的情况下,rxjava出现了,以至于出现了rxandroid.其实如果你了解观察者模 ...

  8. &lbrack;MicroPython&rsqb;STM32F407开发板DIY声光控开关

    1.实验目的 1. 学习在PC机系统中扩展简单I/O 接口的方法. 2. 进一步学习编制数据输出程序的设计方法. 3. 学习光敏模块的工作原理. 4. 学习声音的工作原理. 5. 学习F40 7Mic ...

  9. golang配置

    配置使用yaml,使用了github上一个configor的库.理由如下: 1. 支持多种格式 2. ORM,自动给变量赋值,不用写太多的代码 3. 但是他支持shell env配置,我怕与运行的环境 ...

  10. 2018&period;11&period;24 poj3415Common Substrings(后缀数组&plus;单调栈)

    传送门 常数实在压不下来(蒟蒻开O(3)都过不了). 但有正确性233. 首先肯定得把两个字符串接在一起. 相当于heightheightheight数组被height<kheight<k ...