mybatis学习(五)----实现关联表查询
一.一对一的表查询
查询班级表中班级号为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学习(五)----实现关联表查询的更多相关文章
- 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学习总结(五)——实现关联表查询(转载)
本文转载自:http://www.cnblogs.com/jpf-java/p/6013516.html 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数 ...
- MyBatis学习总结(五)——实现关联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- MyBatis学习总结(五)——实现关联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- MyBatis学习笔记(五)——实现关联表查询
转自孤傲苍狼的博客:http://www.cnblogs.com/xdp-gacl/p/4264440.html 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创 ...
- 五:MyBatis学习总结(五)——实现关联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- MyBatis入门学习教程-实现关联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- mybatis学习 十二 多表查询
Mybatis 实现多表查询方式: (1)业务装配.对两个表编写单表查询语句,在业务(Service)把查询的两个结果进行关联. (2)使用Auto Mapping特性,在实现两表联合查询时通过别名完 ...
随机推荐
- javascript之封装(引用网络)
一. 例:事件监听封装 jQuery 中的事件监听,完全可以用 addEventListener/attachEvent 模拟,分别对应于现代浏览器和 IE ,可以把两个方法封装一下,但是为了方便,这 ...
- MySql常用函数 --MySql
1.目标 MySQL数据库中提供了很丰富的函数.MySQL函数包括数学函数.字符串函数.日期和时间函数.条件判断函数.系统信息函数.加密函数.格式化函数等.通过这些函数,可以简化用户的操作.例如,字符 ...
- Spring Boot之Swagger2集成
一.Swagger2简单介绍 Swagger2,它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档.它既可以减少我们创建文档的工作量,同时 ...
- 20181013xlVba成绩报表优化
Public Sub 成绩报表优化() Application.ScreenUpdating = False Application.DisplayAlerts = False Application ...
- (未完成👃)You Don't Know JS: Scope & Closures (第5章: Scope & Closures)
Chapter 5: Scope Closure 我们到达这里时,已经对作用域如何工作有了非常健康稳固的理解. 下面,我们转移注意力到一个及其重要,但长期难以理解,几乎是神话中的部分语言:Closur ...
- 他将Yahoo!Hadoop从20个节点扩展为42000个节点
他将Yahoo!Hadoop从20个节点扩展为42000个节点 http://www.csdn.net/article/2012-11-08/2811629-Interview-Hortonworks ...
- android -------- 安装APK报错:Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE解决方法
记录一个 DELETE_FAILED_INTERNAL_ERROR Error while Installing APK问题 之前遇到这个问题 方案1 将data/data/目录下该应用的包名的目录删 ...
- Permutations CodeForces - 736D (矩阵逆)
对于删除每个对(x,y), 可以发现他对答案的贡献为代数余子式$A_{xy}$ 复习了一下线代后发现代数余子式可以通过伴随矩阵求出, 即$A_{xy}=A^*[y][x]$, 伴随矩阵$A^*=|A| ...
- Integer to English words leetcode java
问题描述: Convert a non-negative integer to its english words representation. Given input is guaranteed ...
- idea中查看java类继承图
复习java io,看了书里的这张图,太模糊了,想弄个出来放大看,一开始试了idea发现只能看父类,后来折腾了一会试了其他工具才发现还是idea好用. :) 一.打开type hierachy 光标放 ...