多表关联查询1+N查询(一对多)
查询目标:查询某个班级中所有的学生信息
数据库准备:


pojo类
public class Clazz implements Serializable {
private long cid;
private String cname;
private String room;
//在一(1)的对象中持有多(N)的对象
private List<Student> student;
getter()/setter()
toString()
}
public class Student implements Serializable {
private long sid;
private String sname;
private long age;
private long cid;
getter()/setter()
toString()
}
一、分别查询,service层手动装配
1.1 接口
public interface ClazzMapper {
//查询班级信息
public Clazz getClazzByCid(int cid);
}
public interface StudentMapper {
//根据cid查班级中所有的学生信息
public List<Student> getStuByCid(int cid);
}
1.2 mapper映射文件
<mapper namespace="com.yd.mapper.ClazzMapper">
<cache></cache>
<select id="getClazzByCid" resultType="Clazz">
select * from clazz where cid = #{param1}
</select>
</mapper>
<mapper namespace="com.yd.mapper.StudentMapper">
<cache></cache>
<select id="getStuByCid" resultType="Student">
select * from student where cid = #{param1}
</select>
</mapper>
1.3 运行代码:
//1.service层手动装配
@Test
public void getClazz(){
//查询班级1的信息
Clazz clazz = clazzMapper.getClazzByCid(1);
//查询班级1的学生
List<Student> studentList = studentMapper.getStuByCid(1);
//装配
clazz.setStudent(studentList);
System.out.println(clazz);
sqlSession.close();
}
运行结果:

二、resultMap 的 N+1 方式实现多表查询(一对多)
2.1 接口
public interface ClazzMapper {
//根据主键cid查询某班级及学生信息
public Clazz getClazz(int cid);
}
public interface StudentMapper {
//根据外键cid查询学生信息
public List<Student> getStuByCid(int cid);
}
2.2 xml映射文件
提供 ClazzMapper 和 StudentMapper, ClazzMapper 查询所有班级信息, StudentMapper 根据班级编号查询学生信息 . 在 ClazzMapper 中使用
<collection>用于关联一个集合
-
property: 属性名
-
select: 设定要继续引用的查询, namespace+id
-
column: 查询时需要传递的列
<mapper namespace="com.yd.mapper.ClazzMapper">
<cache></cache>
<resultMap id="rm" type="Clazz">
<!--两张表相关联的列不可以省略(主键不可省略),其他同名列都可以省略-->
<id property="cid" column="cid"></id>
<collection property="student" select="com.yd.mapper.StudentMapper.getStuByCid" column="cid">
<!--同名列可以省略-->
</collection>
</resultMap>
<select id="getClazz" resultMap="rm">
select * from clazz where cid = #{param1}
</select>
</mapper>
<mapper namespace="com.yd.mapper.StudentMapper">
<cache></cache>
<select id="getStuByCid" resultType="Student">
select * from student where cid = #{param1}
</select>
</mapper>
2.3 运行文件:
@Test
public void getClazz2(){
//查询班级1的信息
Clazz clazz = clazzMapper.getClazz(1);
System.out.println(clazz);
}
运行结果:

三、resultMap 的sql关联查询方式实现1+N(一对多)
3.1 接口
public interface ClazzMapper {
//查询某班级及学生信息
public Clazz getClazz2(int cid);
}
3.2 xml映射文件
a) 在 ClazzMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应学生的信息.
b) 通过<resultMap>定义映射关系, 并通过<collection>指定集合属性泛型的映射关系. 可以把<collection>看成一个<resultMap>使用.
-
property:属性名
-
javaType:表示返回类型List类型别名(参考mybatis官方文档:https://mybatis.org/mybatis-3/zh/configuration.html)
-
ofType: 表示返回集合的泛型, 可以写全限定路径或别名.
<mapper namespace="com.yd.mapper.ClazzMapper">
<cache></cache>
<resultMap id="rm2" type="Clazz">
<!-- 属性名与数据库列名的映射关系不能省略-->
<id property="cid" column="cid"></id>
<result property="cname" column="cname"></result>
<result property="room" column="room"></result>
<!--关联Student类 -->
<collection property="student" javaType="list" ofType="Student">
<!-- 属性名与数据库列名的映射关系不能省略-->
<id property="sid" column="sid"></id>
<result property="sname" column="sname"></result>
<result property="age" column="age"></result>
<result property="cid" column="cid"></result>
</collection>
</resultMap>
<select id="getClazz2" resultMap="rm2">
<!-- select c.cid,cname,room,sid,sname,age from clazz c join student s on c.cid = s.cid where c.cid = #{param1}-->
select * from clazz c join student s on c.cid = s.cid where c.cid = #{param1}
</select>
</mapper>
3.3 运行代码:
@Test
public void getClazz2(){
//查询班级1的信息
Clazz clazz = clazzMapper.getClazz2(1);
System.out.println(clazz);
}
运行结果:

四、总结
- 前两种装配方式中,外键装配的信息需要进行多次查询;
- 第三种关联查询只要查一次;
- 前两中装配方式中,xml映射文件中属性和列名相同的可以省略不写;关联查询中,所有列名都必须写上
- 若属性(列)过多,推荐使用前两种装配方式。
浙公网安备 33010602011771号