MyBatis 多表关联查询
目录
- 单表查询
- 多表查询
- 多对一
- 一对多
sql样例
表结构
表样例
sql语句
create table student
(
id int not null primary key,
name varchar(20) null,
tid int not null
);
create table teacher
(
id int not null primary key,
name varchar(20) not null
);
insert into student(id,name,tid) values(1,'student1',1),(2,'student2',1),(3,'student3',1),(4,'student4',2),(5,'student5',2),(6,'student6',3);
insert into teacher(id,name) values(1,'teacherA'),(2,'teacherB'),(3,'teacherC');
单表查询
单表查询非常简单,这里仅简述
例如我们要查询所有student的信息
Student
package com.szx.pojo;
import lombok.Data;
@Data
public class Student {
private int id;
private String name;
private int tid;
}
这里使用了lombok插件,省略了构造、set、get等方法
StudentMapper
package com.szx.dao;
import com.szx.pojo.Student;
import java.util.List;
public interface StudentMapper {
List<Student> getAllStudent();
}
其中getAllStudent();为方法,返回一个List
StudentMapper.xml
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szx.dao.StudentMapper">
<select id="getAllStudent" resultType="Student">
select * from test.student;
</select>
</mapper>
- 绑定接口StudentMapper
- 制定select中的id(即方法名),和resultType(返回结果)
- 写sql查询语句
写测试类
package com.szx;
import com.szx.dao.StudentMapper;
import com.szx.pojo.Student;
import com.szx.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class ForTest {
@Test
public void getAllStudents() {
SqlSession session = MybatisUtils.getSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
List<Student> Students = mapper.getAllStudent();
for (Student student : Students) {
System.out.println(student);
}
session.close();
}
}
测试结果
多表查询-(多对一)
现在我们修改需求,我们不仅要查询所有的学生信息,我们还要查询学生对应的老师是谁以及该老师的id
对应的问题
我们可以有sql语句:
select * from student as s, teacher as t where s.tid = t.id;
在我们的sql中是可以查询到的没问题
但是如果把StudentMapper.xml中select标签中的sql改成如上,我们也仅仅只能得到学生的信息
原来的方法不可行了,因为我们的Student类中仅仅只包含学生的信息,与Teacher类毫不相关
解决问题
于是我们在Student类中定义一个Teacher, 代表该学生所对应的老师的信息
Teacher类
package com.szx.pojo;
import lombok.Data;
@Data
public class Teacher {
private int id;
private String name;
}
Student类
package com.szx.pojo;
import lombok.Data;
@Data
public class Student {
private int id;
private String name;
private int tid;
private Teacher teacher;
}
由于student中含有的teacher并非基本类型,所以我们要用结果映射
StudentMapper接口
package com.szx.dao;
import com.szx.pojo.Student;
import java.util.List;
public interface StudentMapper {
List<Student> getAllStudent();
}
StudentMapper.xml
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szx.dao.StudentMapper">
<select id="getAllStudent" resultMap="AllStudent">
select s.id as sid,t.id as tid,s.name as sname,t.name as tname,s.tid
from student as s, teacher as t
where s.tid = t.id;
</select>
<resultMap id="AllStudent" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
<association property="teacher" javaType="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
</association>
</resultMap>
</mapper>
其中resultMap即是结果映射,select中的AllStudent对应id为AllStudent的resultMap
property 为 pojo中定义的变量名, column为sql语句中起的别名
例如 在student类中定义的 id 在sql 起了别名 sid,而定义的teacher是一个实体类,所以用javaType。
而teacher这个类中也会有teacher自己的变量,所以进行嵌套。
注意这里的association:这是表示关联关系,即student这个类中只有一个teacher(一个学生只有一个老师,学生和老师是一对多的关系,所以一个学生关联一个老师)
查询结果如下
另一种查询方法
上面这种方法是一次性查出, 根据查询的结果进行映射,此外还可以查询两次
相当于
select * from teacher where id=(select tid from student);
StudentMapper.xml
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szx.dao.StudentMapper">
<select id="getAllStudent" resultMap="AllStudent">
select * from student;
</select>
<resultMap id="AllStudent" type="Student">
<result property="name" column="name"/>
<result property="id" column="id"/>
<result property="tid" column="tid"/>
<association property="teacher" column="tid" javaType="Teacher" select="getTeacherByID">
<result property="id" column="id"/>
<result property="name" column="name"/>
</association>
</resultMap>
<select id="getTeacherByID" resultType="teacher" >
select * from teacher where id=#{tid}
</select>
</mapper>
先选择所有的学生,然后根据学生的tid查询老师,仍然可以得到相同的结果.
多表查询-(一对多)
现在我们要查询老师和其学生的信息。这可和刚才有点不一样,刚才我们要查学生和他的老师,现在我们要查询老师和他对应的所有学生
改变实体类
一个老师对应多个学生,我们在teacher中定义一个student的List即可
Teacher类
package com.szx.pojo;
import lombok.Data;
import java.util.List;
@Data
public class Teacher {
private int id;
private String name;
private List<Student> students;
}
Student类
package com.szx.pojo;
import lombok.Data;
@Data
public class Student {
private int id;
private String name;
private int tid;
}
TeacherMapper接口
package com.szx.dao;
import com.szx.pojo.Teacher;
import java.util.List;
public interface TeacherMapper {
List<Teacher> getAllTeacher();
}
TeacherMapper.xml
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szx.dao.TeacherMapper">
<select id="getAllTeacher" resultMap="AllTeacher">
select t.id as tid,s.id as sid,t.name as tname,s.name as sname,s.tid
from teacher as t,student as s
where t.id = s.tid;
</select>
<resultMap id="AllTeacher" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
</mapper>
因为teacher中的students是一个List,即teacher中有多个student,这是集合关系,所以用collection
而List中的类型为Student,所以ofType为Student
至此我们能得到查询结果
查询结果
总结
MyBatis的多表查询,只要注意是一对多还是多对一的关系。
确定之后,一个个对应pojo中的变量名和sql中的变量名即可
至于两种方式,写一次查询更为简洁,方便调试,结果映射也容易理解。
-
[x] 一次查询
-
[ ] 两次查询