概述
MyBatis 的一对多、多对一,主要就是 resultMapresultMapresultMap 两个属性的使用,而一对多和多对一都是相互的,只是站的角度不同:
- 【一对多】association:一个复杂的类型关联。许多结果将包成这种类型
- 【多对一】collection:复杂类型的集合
准备工作
由于本文是作为解读处理,在这里将不再赘述工程的搭建,只在这里只带大家过一下我们准备的实体类和pojo对象
准备的表有俩张,一个是学生表(t_student),一个是班级表(t_clazz),学生表可以通过cid字段到班级表中查询到对应的班级,java程序控制的外键,俩张表的数据如下:
工程目录如下:
多对一
问题的引出
假设我们要去查询一个学生的信息,这个信息包括班级信息,我们在mysql如何进行查询呢?大家很自然而然的就会想到通过多表联查即可即以下语句:
1. SELECT * FROM t_student 2. LEFT JOIN t_clazz 3. ON t_clazz.`cid`=t_student.`cid` 4. WHERE sid=1
查询的结果如下:
如果我们要将这条记录返回给mybatis进行的数据的封装,就需要提供一个实体类student,那么这个的时候我们需要对这个实体类的属性进行考虑,多个学生对应一个班级也就是多对一,我们把班级作为一个实体类,学生的属性中有班级这一个属性。
班级类(clazz)如下:
1. @Data 2. public class Clazz { 3. private Long cid; 4. private String cname; 5. }
学生类(student)如下:
1. @Data 2. public class Student { 3. private Long sid; 4. private String sname; 5. private Clazz clazz; 6. }
Clazz clazz; 表示学生关联的班级对象。
级联属性映射处理
StudentMapper接口中编写接口
1. /** 2. * 根据id查询学生信息 3. * @param id 4. * @return 5. */ 6. Student selectById(@Param("id") Long id);
StudentMapper.xml中实现
1. <resultMap id="studentResultMap" type="com.study.pojo.Student"> 2. <id property="sid" column="sid"/> 3. <result property="sname" column="sname"/> 4. <result property="clazz.cid" column="cid"/> 5. <result property="clazz.cname" column="cname"/> 6. </resultMap> 7. 8. <select id="selectById" resultMap="studentResultMap"> 9. SELECT * FROM t_student 10. LEFT JOIN t_clazz 11. ON t_clazz.`cid`=t_student.`cid` 12. WHERE sid=#{id} 13. </select>
级联属性映射,就是利用
resultMap
标签对属性和字段进行映射,内部对象的所属属性也进行映射,而SQL
语句就进行表的连接进行查询。例如:clazz.cid
测试代码:
1. @Test 2. public void test01(){ 3. SqlSession session = SqlSessionUtil.openSession(); 4. StudentMapper mapper = session.getMapper(StudentMapper.class); 5. Student student = mapper.selectById(1L); 6. System.out.println(student); 7. }
association处理
association
翻译为关联的意思。它是resultMap
标签中的一个子标签。也是用来处理映射的,当一对象属性中存在另一个对象时,可以利用association
指明其对象中属性及其对应映射。
其他位置都不需要修改,只需要修改resultMap中的配置:association即可。
分步查询
分步查询处理顾名思义将查询的步骤进行分步,在我们进行查询学生信息的时候,可以分为俩步
第一步先到学生表中查到学生的sid和sname,cid
第二步拿第一步中得到的cid去班级表中查询cname
具体实施
第一处:association中select位置填写sqlId。sqlId=namespace+id。其中column属性作为这条子sql语句的条件。
1. <resultMap id="studentResultMap" type="com.study.pojo.Student"> 2. <id property="sid" column="sid"/> 3. <result property="sname" column="sname"/> 4. <association property="clazz" 5. select="com.study.mapper.ClazzMapper.selectById" 6. column="cid"></association> 7. </resultMap> 8. 9. <select id="selectById" resultMap="studentResultMap"> 10. SELECT * FROM t_student 11. LEFT JOIN t_clazz 12. ON t_clazz.`cid`=t_student.`cid` 13. WHERE sid=#{id} 14. </select>
第二处:在ClazzMapper接口中添加方法
1. /** 2. * 根据id查询班级信息 3. * @param id 4. */ 5. Clazz selectById(@Param("id") Long id);
第三处:在ClazzMapper.xml文件中进行配置
1. <select id="selectById" resultType="com.study.pojo.Clazz"> 2. select * from t_clazz where cid=#{id} 3. </select>
逻辑如下:
执行结果,可以很明显看到先后有两条sql语句执行: