实现关联表查询
一、一对一关联
需求
根据班级id查询班级信息(带老师的信息)
- 创建表和数据(一张老师表一直班级表,假设一个老师只负责一个班)
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);
班级表里的teacher_id关联老师表里的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);
2
定义班级表和老师表所对应的实体类
public class classes {
private int id;
private String name;
private Teacher teacher;
private List<student> students;
public List<student> getStudents() {
return students;
}
public void setStudents(List<student> students) {
this.students = 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;
}
@Override
public String toString() {
return "classes{" + "id=" + id + ", name='" + name + '\'' + ", teacher=" + teacher + ", students=" + students + '}';
}
}
public class Teacher {
private int id;
private String 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.定义sql映射文件classMapper.xml并在主配置文件config.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="mapping.classMapper">
<!--根据班级id查询班级信息(带老师的信息)-->
<!--
方式一:嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
封装联表查询的数据(去除重复的数据)
select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=1
-->
<select id="getClass" parameterType="int"
resultMap="ClassResultMap">
SELECT *FROM class C ,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=#{id}
</select>
<!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
<resultMap id="getClass" type="entity.classes">
<id property="id" column="c_id"></id>
<result property="name" column="c_name"></result>
<association property="teacher" javaType="entity.Teacher">
<id property="id" column="t_id"></id>
<result property="name" column="t_name"></result>
</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="CalssResultMap2">
SELECT * FROM class WHERE c_id=#{id}
</select>
<!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
<resultMap id="CalssResultMap2" type="entity.classes">
<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="entity.Teacher">
SELECT t_id id,t_name name FROM teacher WHERE t_id=#{id}
</select>
</mapper>
<mapper resource="mapping/classMapper.xml"/> //此代码在config中注册classMapper.xml
3.编写测试类
方法一:
@Test
public void testGetClass1(){
SqlSession session = UserMapperUtil.getSqlSession();
String statement="mapping.classMapper.getClass1";
classes classes =session.selectOne(statement,1);
session.close();
System.out.println(classes);
}
方法二:
@Test
public void testGetClass2(){
SqlSession session = UserMapperUtil.getSqlSession();
String statement="mapping.classMapper.getClass2";
classes classes =session.selectOne(statement,1);
session.close();
System.out.println(classes);
}
一对一关联查询总结
*MyBatis中使用association标签来解决一对一的关联查询,association标签可用的属性如下:
property:对象属性的名称
javaType:对象属性的类型
column:所对应的外键字段名称
select:使用另一个查询封装的结果*
二、一对多关联
需求
根据classId查询对应的班级信息,包括学生,老师
- 创建学生表并添加数据
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);
- 定义实体类students并为classes类添加一个Lis students属性
public class student {
private int id;
private String 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 + '\'' + '}';
}
}
private List<student> students; //classes添加的属性
3.修改classMapper.xml映射文件
<!--
根据classId查询对应的班级信息,包括学生,老师
-->
<!--
方式一: 嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集
SELECT * FROM class c, teacher t,student s WHERE c.teacher_id=t.t_id AND c.C_id=s.class_id AND c.c_id=1 -->
<select id="getClass3" parameterType="int" resultMap="ClassRusultMap3">
SELECT * FROM class c,student s,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=s.class_id AND c.c_id=#{id}
</select>
<resultMap id="ClassRusultMap3" type="classes">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" column="teacher_id" javaType="Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
<!-- ofType指定students集合中的对象类型 -->
<collection property="students" ofType="student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
</resultMap>
4.编写测试类
public static void main(String[] args) {
SqlSession session = UserMapperUtil.getSqlSession();
String statement="mapping.classMapper.getClass3";
classes classes =session.selectOne(statement,1);
session.close();
System.out.println(classes);
}
三、调用存储过程
查询得到男性或女性的数量, 如果传入的是0就女性否则是男性
- 创建表和存储过程
CREATE TABLE p_user(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
sex CHAR(2)
);
INSERT INTO p_user(NAME,sex) VALUES('A',"男");
INSERT INTO p_user(NAME,sex) VALUES('B',"女");
INSERT INTO p_user(NAME,sex) VALUES('C',"男");
-- 创建存储过程(查询得到男性或女性的数量, 如果传入的是0就女性否则是男性)
DELIMITER $
CREATE PROCEDURE mybatis.ges_user_count(IN sex_id INT, OUT user_count INT)
BEGIN
IF sex_id=0 THEN
SELECT COUNT(*) FROM mybatis.p_user WHERE p_user.sex='女' INTO user_count;
ELSE
SELECT COUNT(*) FROM mybatis.p_user WHERE p_user.sex='男' INTO user_count;
END IF;
END
$
-- 调用存储过程
DELIMITER ;
SET @user_count = 0;
CALL mybatis.ges_user_count(1, @user_count);
SELECT @user_count;
2.为userMapper.xml添加配置
<!--
查询得到男性或女性的数量, 如果传入的是0就女性否则是男性
-->
<select id="getUserCount" parameterMap="getUserCountMap" statementType="CALLABLE">
CALL mybatis.ges_user_count(?,?)
</select>
<!--
parameterMap.put("sexid", 0);
parameterMap.put("usercount", -1);
-->
<parameterMap type="java.util.Map" id="getUserCountMap">
<parameter property="sexid" mode="IN" jdbcType="INTEGER"/>
<parameter property="usercount" mode="OUT" jdbcType="INTEGER"/>
</parameterMap>
3.编写测试类
public static void main(String[] args) {
SqlSession session = UserMapperUtil.getSqlSession();
String statement="mapping.userMapper.getUserCount";
Map<String,Integer> paramentMap = new HashMap<String,Integer>();
paramentMap.put("sexid",1);
paramentMap.put("usercount",-1);
session.selectOne(statement,paramentMap);
int result = paramentMap.get("usercount");
System.out.println(result);
session.close();
}