十三、多表关联查询

1. 业务装配实现

业务装配实现多表查询(多对一)

mapper 层只做单表查询操作, 在 service 层进行手动装配,实现关联查询的结果.

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

(1) 实体类

创建班级类(Clazz) 和学生类(Student), 并在 Student 中添加一个 Clazz 类型的属性, 用于表示学生的班级信息.

 

(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>

 

(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;

}

}

 

(4) 测试代码

public static void main(String[] args) {

StudentService ss = new StudentServiceImpl();

List<Student> list = ss.selAll();

for (Student student : list) {

System. out.println(student);

}

}

 

2. 单个对象(N+1)

resultMap 的N+1方式实现多表查询(多对一)

(1) 实体类

创建班级类(Clazz) 和学生类(Student), 并在 Student 中添加一个 Clazz 类型的属性, 用于表示学生的班级信息.

 

(2) mapper 层

提供 StudentMapper 和 ClazzMapper, StudentMapper 查询所有学生信息 , ClazzMapper 根据编号查询班级信息 . 再StudentMapper 中使用<association>设置装配.

<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>

 

(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 的关联方式实现多表查询 (多对一)

(1) mapper 层

1) 在 StudentMapper. xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应班级的信息.

2) 通过<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>

 

4. 集合对象(N+1)

resultMap 的 N+1 方式实现多表查询(一对多)

(1) 实体类

在班级类中定义一个学生集合, 用于存放该班级的所有学生信息.

 

(2) mapper 层

提供 ClazzMapper 和 StudentMapper, ClazzMapper 查询所有班级信息 , StudentMapper 根据班级编号查询学生信息 .

ClazzMapper 中使用<collection>设置装配.

<collection>用于关联一个集合

property: 指定要关联的属性名

select: 设定要继续引用的查询, namespace+id

column: 查询时需要传递的列

<mapper namespace="com.bjsxt.mapper.ClazzMapper">

<resultMap type="clazz" id="cmap">

<id property="id" column="id" />

<collection property="stus"

select="com.bjsxt.mapper.StudentMapper.selByCid"

column="id"></collection>

</resultMap>

<select id="selAll" resultMap="cmap">

select * from t_class

</select>

</mapper>

<mapper namespace="com.bjsxt.mapper.StudentMapper">

<select id="selByCid" resultType="student" parameterType="int">

select * from t_student where cid=#{0}

</select>

</mapper>

 

(3) service 层

public class ClazzServiceImpl implements ClazzService {

@Override

public List<Clazz> selAll() {

SqlSession session = MyBatisUtil. getSession();

ClazzMapper mapper = session.getMapper(ClazzMapper. class);

List<Clazz> list = mapper.selAll();

session.close();

return list;

}

}

 

5. 集合对象(关联)

resultMap 的关联方式实现多表查询(一对多)

(1) 在 ClazzMapper. xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应学生的信息.

(2) 通过<resultMap>定义映射关系, 并通过<collection>指定集合属性泛型的映射关系. 可以把<collection>看成一个<resultMap>使用 . ofType 属性表示集合的泛型, 可以写全限定路径或别名 .

<mapper namespace="com.bjsxt.mapper.ClazzMapper">

<resultMap type="clazz" id="cmap">

<id property="id" column="cid" />

<result property="name" column="cname" />

<result property="room" column="room" />

<collection property="stus" javaType="list" ofType="student">

<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" />

</collection>

</resultMap>

<select id="selAll" resultMap="cmap">

select c.id cid, c.name cname, c.room, s.id sid, s.name sname, s.age, s.gender

from t_student s

right join t_class c

on s.cid=c.id

</select>

</mapper>

 

6. Auto-Mapping多表查询

通过 Auto-Mapping 实现多表查询

(1) 通过 MyBatis 的 Auto-Mapping 机制及数据库查询时的别名结合, 可以方便的实现多表查询.

(2) SQL 语句中, 别名出现特殊符号时, 必须进行处理. MySQL可以使用(``) 符号, Oracle 可以使用("") 符号.

<mapper namespace="com.bjsxt.mapper.StudentMapper">

<select id="selAll" resultType="student">

select s.id, s.name, s.age, s.gender, s.cid, c.id `clazz.id`, c.name `clazz.name`, c.room `clazz.room`

from t_student s

left join t_class c

on s.cid=c.id

</select>

</mapper>

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄