一.一对一的表查询

查询班级表中班级号为1的对应的记录(包括教师的具体信息)

1.首先建立数据表

数据表class和techear,class表中只有一个外键techear_id,sql脚本如下:

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

建立好的数据表如下:

class表

techear表

2.实体类

Classes类对应class表,Teacher类对应teacher表

 package me.gacl.domain;

 import me.gacl.domain.Teacher;
/**
* 班级实体类
*/
public class Classes {
private int id;//id对应c_id
private String name;//name对应c_name
private Teacher teacher;//因为class表中只有一个teacher_id外键,所以Class类中持有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 +
'}';
}
}
 package me.gacl.domain;

 /**
* 教师实体类
*/
public class 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 + '\'' +
'}';
}
}

3.编写sql映射文件

teacher_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">
<!--namespace一般命名成报名+映射名-->
<mapper namespace="me.gacl.mapping.teacher_classMapper">
<!--查询班级为1的班级和教师信息-->
<!--方法一:联表查询-->
<select id="getClass_Teacher" parameterType="int" resultMap="classResultMap">
select * from class,teacher where class.teacher_id=teacher.t_id and c_id=#{id}
</select>
<!--使用resultMap指定实体类字段与数据表属性之间的一一对应关系-->
<resultMap id="classResultMap" type="Classes">
<id column="c_id" property="id"></id>
<result column="c_name" property="name"></result>
<!--使用association中的javaType指定关联表中对应的实体类的类型,
及实体类字段与数据表属性之间的一一对应关系-->
<association property="teacher" javaType="Teacher">
<id column="t_id" property="id"></id>
<result column="t_name" property="name"></result>
</association>
</resultMap>
<!--方法二,执行两步查询,引用另一步查询的查询结果-->
<!--首先查询出班级为1对应的教师信息-->
<select id="getClass_Teacher2" parameterType="int" resultMap="classResultMap2">
select * from class where c_id=#{id}
</select>
<resultMap id="classResultMap2" type="Classes">
<id column="c_id" property="id"></id>
<result column="c_name" property="name"></result>
<!--这里的column="teacher_id"一定不能少,因为teacher_id的值是作为参数传递给要引用的Select语句的
相当于mybatis执行resultSet.getInt("teacher_id"),where后面的id入参就是得到的teacher_id的值-->
<association property="teacher" column="teacher_id" select="getTeacher"></association>
</resultMap>
<!--然后根据上一步查询出的教师id到教师表中查询教师信息-->
<select id="getTeacher" parameterType="int" resultType="me.gacl.domain.Teacher">
select t_id id,t_name name from teacher where t_id=#{id}
</select>
</mapper>

注意:引用类都是用的别名,即类名

4.注册sql映射文件

在mybatis_config.xml中注册teacher_classMapper.xml映射文件

    <mappers>
<mapper resource="mapping/teacher_classMapper.xml"></mapper>
</mappers>

5.编写测试类

 package me.gacl.domain;

 import me.gacl.Util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* 联表查询的测试类
*/
public class Class_TeacherTest {
public void testgetClass_teacher(){
SqlSession sqlSession = MyBatisUtil.getSqlSession(true);
String statement = "me.gacl.mapping.teacher_classMapper.getClass_Teacher";
Classes classes = sqlSession.selectOne(statement,1);
sqlSession.close();
System.out.println(classes);
}
public void testgetClass_teacher2(){
SqlSession sqlSession = MyBatisUtil.getSqlSession(true);
String statement = "me.gacl.mapping.teacher_classMapper.getClass_Teacher2";
List <Classes> list = sqlSession.selectList(statement,1);
sqlSession.close();
System.out.println(list);
} public static void main(String[] args) {
Class_TeacherTest class_teacherTest = new Class_TeacherTest();
//class_teacherTest.testgetClass_teacher();
class_teacherTest.testgetClass_teacher2();
}
}

测试结果:两个方法输出结果一样

6.总结

mybatis中实现一对一的多表查询,使用association标签实现,association标签的属性介绍如下:

properties:属性的名称

javaType:属性的类型

column:表中的外键字段名

select:使用另一个查询

二.实现一对多的联表查询

1.建立一个学生表,班级表与学生表示1:n的关系

sql脚本:

 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.建立student实体类

package me.gacl.domain;

/**
* 学生实体类
*/
public class Student {
private int id;//id对应student表中的s_id
private String name;//name对应student表中的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 + '\'' +
'}';
}
}

3.修改Classes类

类中添加学生对象

 package me.gacl.domain;

 import me.gacl.domain.Teacher;
import java.util.List;
/**
* 班级实体类
*/
public class Classes {
private int id;//id对应c_id
private String name;//name对应c_name
private Teacher teacher;//因为class表中只有一个teacher_id外键,所以Class类中持有Teacher类的一个对象
private List<Student> students;//因为班级与学生是1:n的关系,因此使用List存储一个班的n个学生 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 +
'}';
}
}

4.编写映射文件

 <?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">
<!--namespace一般命名成报名+映射名-->
<mapper namespace="me.gacl.mapping.student_classMapper">
<!--查询班级为1的班级对应的学生和教师信息-->
<!--方法一:联表查询-->
<select id="getClassTeacherStudent" parameterType="int" resultMap="classResultMap">
select * from class,teacher,student where class.teacher_id=teacher.t_id and class.c_id=student.class_id and c_id=#{id}
</select>
<!--使用resultMap指定实体类字段与数据表属性之间的一一对应关系-->
<resultMap id="classResultMap" type="Classes">
<id column="c_id" property="id"></id>
<result column="c_name" property="name"></result>
<!--使用association中的javaType指定关联表中对应的实体类的类型,
及实体类字段与数据表属性之间的一一对应关系-->
<association property="teacher" column="teacher_id" javaType="Teacher">
<id column="t_id" property="id"></id>
<result column="t_name" property="name"></result>
</association>
<collection property="students" ofType="Student">
<id column="s_id" property="id"></id>
<result column="s_name" property="name"></result>
<!--若没有指定属性class_id的对应column名称,则输出class_id为0
也可以学生实体类中不包含属性class_id,那么打印输出中就没有class_id信息-->
<result column="class_id" property="class_id"></result>
</collection>
</resultMap>
<!--方法二,执行两步查询,引用另一步查询的查询结果-->
<!--首先查询出班级为1对应的教师信息-->
<select id="getClassTeacherStudent2" parameterType="int" resultMap="classResultMap2">
select * from class where c_id=#{id}
</select>
<resultMap id="classResultMap2" type="Classes">
<id column="c_id" property="id"></id>
<result column="c_name" property="name"></result>
<!--这里的column="teacher_id"一定不能少,因为teacher_id的值是作为参数传递给要引用的Select语句的
相当于mybatis执行resultSet.getInt("teacher_id"),where后面的id入参就是得到的teacher_id的值-->
<association property="teacher" column="teacher_id" select="getTeacher"></association>
<!--这里的column="c_id"一定不能少,因为c_id的值是作为参数传递给要引用的Select语句的
相当于mybatis执行resultSet.getInt("c_id"),where后面的id入参就是得到的c_id的值-->
<collection property="students" column="c_id" select="getStudent"></collection>
</resultMap>
<!--然后根据上一步查询出的教师id到教师表中查询教师信息-->
<select id="getTeacher" parameterType="int" resultType="Teacher">
select t_id id,t_name name from teacher where t_id=#{id}
</select>
<!--然后根据第一步查询出的班级id到学生表中查询班级中的学生信息-->
<select id="getStudent" parameterType="int" resultType="Student">
select s_id id,s_name name from student where class_id=#{id}
</select>
</mapper>

5.mybatis_config.xml中注册student_classMapper映射文件

  <mappers>
<mapper resource="mapping/student_classMapper.xml"></mapper>
</mappers>

6.编写测试类

 package me.gacl.domain;

 import me.gacl.Util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession; /**
* 测试一对多联表查询
*/
public class Class_TeacherStudentTest {
public void getClassTeacherStudent(){
SqlSession sqlSession = MyBatisUtil.getSqlSession(true);
String statement = "me.gacl.mapping.student_classMapper.getClassTeacherStudent";
Classes classes = sqlSession.selectOne(statement,1);
sqlSession.close();
System.out.println(classes);
}
public void getClassTeacherStudent2(){
SqlSession sqlSession = MyBatisUtil.getSqlSession(true);
String statement = "me.gacl.mapping.student_classMapper.getClassTeacherStudent2";
Classes classes = sqlSession.selectOne(statement,2);
sqlSession.close();
System.out.println(classes);
} public static void main(String[] args) {
Class_TeacherStudentTest class_teacherStudentTest = new Class_TeacherStudentTest();
class_teacherStudentTest.getClassTeacherStudent();
//class_teacherStudentTest.getClassTeacherStudent2();
}
}

测试结果:两个方法的输出结果一样

7.一对多关联查询总结

mybatis中解决一对多查询问题使用的是collection标签,属性ofType表示指定集合中元素的对象类型

注意: toString()是Java中的一个内置方法,如果你在类里编写了toString,相当于覆盖了类中原有的toString,在System.out.print中会自动调用,因此每个实体类的toString()方法都要正确,最好使用自动生成的,不然System.out.print打印结果不对

mybatis学习(五)----实现关联表查询的更多相关文章

  1. MyBatis学习总结——实现关联表查询(转)

    原文链接:孤傲苍狼 一.一对一关联 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学习总结(五)——实现关联表查询(转载)

    本文转载自:http://www.cnblogs.com/jpf-java/p/6013516.html 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数 ...

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

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

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

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

  7. MyBatis学习笔记(五)——实现关联表查询

    转自孤傲苍狼的博客:http://www.cnblogs.com/xdp-gacl/p/4264440.html 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创 ...

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

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

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

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

  10. mybatis学习 十二 多表查询

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

随机推荐

  1. [转载]mapreduce合并小文件成sequencefile

    mapreduce合并小文件成sequencefile http://blog.csdn.net/xiao_jun_0820/article/details/42747537

  2. Vue音乐项目笔记(二)

    1. Vuex https://blog.csdn.net/weixin_40814356/article/details/80347366 编写: 然后,在main.js中引入 在组件中改变stat ...

  3. Html Email 邮件html页编写指南

    前言 写过邮件的html的童学应该都知道,邮件的html一般都用table来布局,为什么呢?原因是大多数的邮件客户端(比如Outlook和Gmail),会过滤HTML设置,让邮件面目全非. 经过多次的 ...

  4. node模块之net模块——socket

    当我们去面试的时候,常常会遇到这样一个问题:当用户在浏览器地址栏输入一段url发出资源请求后,到服务端返回数据呈现给用户的这个过程都发生了什么? 我们把进行通信的这两个端(这里指的是,浏览器和资源获取 ...

  5. Git将本地项目上传到GitHub

    本文转载于:https://segmentfault.com/a/1190000011909294 https://www.cnblogs.com/cxk1995/p/5800196.html 我们使 ...

  6. hdu-6333-莫队

    Problem B. Harvest of Apples Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K ...

  7. github上fork了别人的项目后,再同步更新别人的提交(转)

    原文地址:github上fork了别人的项目后,再同步更新别人的提交 我从github网站和用git命令两种方式说一下. github网站上操作 打开自己的仓库,进入code下面. 点击new pul ...

  8. Async:简洁优雅的异步之道

    前言 在异步处理方案中,目前最为简洁优雅的便是 async函数(以下简称A函数).经过必要的分块包装后,A函数能使多个相关的异步操作如同同步操作一样聚合起来,使其相互间的关系更为清晰.过程更为简洁.调 ...

  9. MapReduce分布式算法

    一.MapReduce 有一种特殊的并行算法,就是分布式算法.在并行算法只需要两个到四个内核时,完全可以在笔记本电脑上运行,但是如果需要数百个内核,这种情况下,可让算法在多台计算机上运行. 假设你有一 ...

  10. Bellman-Ford算法——为什么要循环n-1次?图有n个点,又不能有回路,所以最短路径最多n-1边。又因为每次循环,至少relax一边所以最多n-1次就行了!

    单源最短路径 给定一个图,和一个源顶点src,找到从src到其它所有所有顶点的最短路径,图中可能含有负权值的边. Dijksra的算法是一个贪婪算法,时间复杂度是O(VLogV)(使用最小堆).但是迪 ...