Mybatis 实现多表查询方式
- 业务装配.对两个表编写单表查询语句,在业务(Service)把查询 的两个结果进行关联
- 使用 Auto Mapping 特性,在实现两表联合查询时通过别名完成 映射.
- 使用 MyBatis 的
<resultMap>
标签进行实现.
- 多表查询时,类中包含另一个类的对象的分类
resultMap 标签
<resultMap>
标签写在mapper.xml中,由程序员控制SQL查询结果与 实体类的映射关系.
- 默认
MyBatis
使用Auto Mapping
特性. - 使用
resultMap
标签时,select
标签不写resultType
属性,而是使 用resultMap
属性引用resultMap
标签. - 使用
resultMap
实现单表映射关系
TIP
使用<
resultMap>
标签时,<
select>
标签不写 resultType
属性,而是使 用 resultMap 属性引用<
resultMap>
标签.
<demo>
<resultMap type="teacher" id="mymap">
<!-- 主键使用 id 标签配置映射关系 -->
<id column="id" property="id1" />
<!-- 其他列使用 result 标签配置映射关系 -->
<result column="name" property="name1"/>
</resultMap>
<select id="selAll" resultMap="mymap">
select * from teacher
</select>
</demo>
使用 resultMap 实现关联单个对象(N+1 方式)
- N+1 查询方式,先查询出某个表的全部信息,根据这个表的信息 查询另一个表的信息
一对一
在 Student 实现类中包含了一个 Teacher 对象
- 在 TeacherMapper 中提供一个查询
<select id="selById" resultType="teacher"
parameterType="int">
select * from teacher where id=#{0}
</select>
- 在 StudentMapper 中
- association 装配一个对象时使用
- property: 对象在类中的属性名
- select:通过哪个查询查询出这个对象的信息
- column: 把当前表的哪个列的值做为参数传递给另 一个查询
- 大前提使用 N+1 方式.时如果列名和属性名相同可以不配置,使用 Auto mapping 特性.但是 mybatis 默认只会给列专配一次
<demo>
<!--
方式一:嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
封装联表查询的数据(去除重复的数据)
select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=1
-->
<!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
<resultMap type="student" id="stuMap">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="tid" column="tid"/>
<!-- 如果关联一个对象 -->
<!-- 使用resultMap下面association 属性来完成1对1的映射-->
<association property="teacher" javaType="com.qiu.entity.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
</resultMap>
<select id="selAll" resultMap="stuMap">
select * from student
</select>
</demo>
简化一下
<demo>
<!--
方式二:嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
SELECT * FROM class WHERE c_id=1;
SELECT * FROM teacher WHERE t_id=1 //1 是上一个查询得到的teacher_id的值
-->
<resultMap type="student" id="stuMap">
<result column="tid" property="tid"/>
<!-- 如果关联一个对象 -->
<association property="teacher"
select="com.b.mapper.TeacherMapper.selById"
column="tid"></association>
</resultMap>
<select id="selAll" resultMap="stuMap">
select * from student
</select>
</demo>
在mybatis中使用resultMap节点下的association标签来解决一对一的关联查询,association可用属性有:
- property:对象属性的名称
- javaType:对象属性的类型
- column:所对应的外键字段名称
- select:使用另一个查询封装的结果
<
resultMap>
查询关联集合对象(N+1)
一对多public class Teacher {
private int id;
private String name;
private List<Student> list;
StudentMapper.xml
<select id="selByTid" parameterType="int" resultType="student"> select * from student where tid=#{0} </select>
在 TeacherMapper.xml 中添加查询全部
<collection/>
当属性是集合类型时使用的标签
MyBatis中使用collection标签来解决一对多的关联查询,ofType属性指定集合中元素的对象类型。
<de>
<resultMap type="teacher" id="mymap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="list"
select="com.b.mapper.StudentMapper.selByTid"
column="id"></collection>
</resultMap>
<select id="selAll" resultMap="mymap">
select * from teacher
</select>
</de>
使用关联查询
<!--
嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集
SELECT * FROM class c,student s WHERE c.C_id=s.class_id AND c.c_id=1
-->
<select id="getClass3" parameterType="int" resultMap="ClassResultMap3">
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=#{id}
</select>
<resultMap type="com.qiu.entity.Classes" id="ClassResultMap3">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<!-- ofType指定students集合中的对象类型 -->
<collection property="students" ofType="com.qiu.entity.Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
</resultMap>
Auto Mapping 结合别名实现多表查询.
- 只能使用多表联合查询方式
- 在 SQL 是关键字符,两侧添加反单引号
<select id="selAll" resultType="student">
select t.id `teacher.id` , t.name`teacher.name`
, s.id id , s.name name , age , tid
from student s LEFT JOIN teacher t on t.id=s.tid
</select>