多表查询非常重要,是MyBatis多对一查询的利器。
一 . 业务装配实现多表查询( 多对一)
mapper 层只做单表查询操作, 在 service 层进行手动装配,实现关联查询的结果.
1.1 实体类
创建班级类(Clazz)和学生类(Student), 并在 Student 中添加一个 Clazz 类型的属性, 用于表示学生的班级信息.
1.2 mapper 层
提供StudentMapper和ClazzMapper, StudentMapper查询所有学生信息, ClazzMapper 根
据编号查询班级信息.
<mapper namespace="com.bjsxt.mapper.StudentMapper">
<select id="selAll" resultType="student">
select * from t_student
</select>
</mapper>
<mapper namespace="com.bjsxt.mapper.ClazzMapper">
<select id="selById" resultType="clazz" parameterType="int">
select * from t_class where id=#{0}
</select>
</mapper>
1.3 service 层
调用 mapper 层, 先查询所有学生, 再根据每个学生的班级编号查询班级信息, 手动进行组装,
称之为业务装配.
public class StudentServiceImpl implements StudentService {
@Override
public List<Student> selAll() {
SqlSession session = MyBatisUtil.getSession();
// 学生mapper
StudentMapper stuMapper = session.getMapper(StudentMapper.class);
// 班级mapper
ClazzMapper clsMapper = session.getMapper(ClazzMapper.class);
// 查询所有学生信息
List<Student> list = stuMapper.selAll();
// 为每一个student组装班级信息
for (Student student : list) {
student.setClazz(clsMapper.selById(student.getCid()));
}
session.close();
return list;
}
}
1.4 测试代码。
public static void main(String[] args) {
StudentService ss = new StudentServiceImpl();
List<Student> list = ss.selAll();
for (Student student : list) {
System.out.println(student);
}
}
二 . resultMap 的N+1 方式实现多表查询( 多对一)
2.1 实体类
创建班级类(Clazz)和学生类(Student), 并在 Student 中添加一个 Clazz 类型
的属性, 用于表示学生的班级信息.
2.2 mapper 层
提供StudentMapper和ClazzMapper, StudentMapper查询所
有学生信息, ClazzMapper 根据编号查询班级信息. 再
StudentMapper 中使用<association>设置装配.
(a) <association>用于关联一个对象
property: 指定要关联的属性名
select: 设定要继续引用的查询, namespace+id
column: 查询时需要传递的列.
<mapper namespace="com.bjsxt.mapper.StudentMapper">
<resultMap type="student" id="smap">
<!-- N+1查询时, 同名映射可以省略, 但是只能使用一次 -->
<result property="cid" column="cid" />
<!-- 用于关联一个对象 -->
<association property="clazz"
select="com.bjsxt.mapper.ClazzMapper.selById"
column="cid"></association>
</resultMap>
<select id="selAll" resultMap="smap">
select * from t_student
</select>
</mapper>
<mapper namespace="com.bjsxt.mapper.ClazzMapper">
<select id="selById" resultType="clazz" parameterType="int">
select * from t_class where id=#{0}
</select>
</mapper>
2.3 service 层
由于装配已经完成, service 层只需要调用 mapper 即可, 不需要再进行装配了.
public class StudentServiceImpl implements StudentService {
@Override
public List<Student> selAll() {
SqlSession session = MyBatisUtil.getSession();
// 学生mapper
StudentMapper stuMapper = session.getMapper(StudentMapper.class);
List<Student> list = stuMapper.selAll();
session.close();
return list;
}
}
3. resultMap 的关联方式实现多表查询( 多对一)
3.1 mapper 层
(a) 在 StudentMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括
对应班级的信息.
(b) 通过<resultMap>定义映射关系, 并通过<association>指定对象属性的映射关系. 可以把
<association>看成一个<resultMap>使用. javaType 属性表示当前对象, 可以写全限定路径
或别名.
<resultMap type="student" id="smap">
<id property="id" column="sid" />
<result property="name" column="sname" />
<result property="age" column="age" />
<result property="gender" column="gender" />
<result property="cid" column="cid" />
<association property="clazz" javaType="clazz">
<id property="id" column="cid" />
<result property="name" column="cname" />
<result property="room" column="room" />
</association>
</resultMap>
<select id="selAll" resultMap="smap">
select s.id sid, s.name sname, s.age, s.gender, c.id cid,
c.name cname, c.room
from t_student s
left join t_class c
on s.cid=c.id
</select>