一、第一种方式(一条SQL语句):级联属性映射
【CarMapper.xml样例】:
<resultMap id="studentResultMap" type="Student"> <!--多对一映射的第一种方式:一条SQL语句,级联属性映射。colum的值赋给property的值--> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <result property="clazz.cid" column="cid"/> <result property="clazz.cname" column="cname"/> </resultMap> <select id="selectById" resultMap="studentResultMap"> select s.sid,s.sname,c.cid,c.cname from t_student s left join t_clazz c on s.cid=c.cid where s.sid=#{sid} </select>
【测试样例】:
@Test public void testSelectById(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectById(1); System.out.println(student.getSname()); System.out.println(student.getClazz().getCid()); System.out.println(student.getClazz().getCname()); sqlSession.close(); }
二、第二种方式(一条SQL语句):association标签
【CarMapper.xml样例】:
<resultMap id="studentResultMapAssociation" type="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <!-- association:翻译为关联。一个Student对象关联一个Clazz对象 property:提供要映射的POJO类属性名 javaType:用来指定要映射的Java类型 --> <association property="clazz" javaType="Clazz"> <id property="cid" column="cid"/> <result property="cname" column="cname"/> </association> </resultMap> <select id="selectByIdAssociation" resultMap="studentResultMapAssociation"> select s.sid,s.sname,c.cid,c.cname from t_student s left join t_clazz c on s.cid=c.cid where s.sid=#{sid} </select>
【测试样例】:
@Test public void testStudentResultMapAssociation(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectByIdAssociation(1); System.out.println(student); sqlSession.close(); }
三、第三种方式(两条SQL语句):分步查询
【注意】这种方式比较常用
【优点】:
- 复用性强。可以重复使用。(把大步拆成N多小碎步。每一个小碎步也可重复利用)
- 可以充分利用他们的延迟加载/懒加载机制
【什么是懒加载/延迟加载】
- 原理是用的时候再执行查询语句。不用的时候不查询。
- 提高性能:尽可能的不查,或者说尽可能少查。来提高效率。
【在mybatis中如何开启】
- association标签中添加fetchType="lazy"
【CarMapper.xml样例】:
第一步:先查出学生信息的所有信息,把信息当中的cid传给第二条查询语句
<!--两条SQL语句,完成多对一的分布查询。--> <!--这里是第一步:根据学生的id查询学生的所有信息。这些信息当中含有班级的id--> <resultMap id="studentResultMapByStep" type="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <association property="clazz" <!--select后面跟的是第二条语句的id(路径)--> select="com.mapper.ClazzMapper.selectByIdStep2" column="cid"/> </resultMap> <select id="selectByIdStep1" resultMap="studentResultMapByStep"> select sid,sname,cid from t_student where sid=#{sid} </select>
第二步:第二条查询语句(根据第一步传过来的cid进行查询对应的课程信息)
<!--分步查询第二步:根据cid获取班级信息。--> <select id="selectByIdStep2" resultType="Clazz"> select cid,cname from t_clazz where cid=#{cid} </select>
【测试样例】:
@Test public void testSelectByIdStep1(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectByIdStep1(5); System.out.println(student); }
【注意】默认情况下是没有开启延迟加载的。需要设置:fetchType="lazy"
<resultMap id="studentResultMapByStep" type="Student"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <association property="clazz" select="com.mapper.ClazzMapper.selectByIdStep2" column="cid" fetchType="lazy"/> </resultMap>
【注】当设置fetchType="lazy"之后,如果只需要看学生的名字,如:
System.out.println(student.getSname());
此时,只会有一条SQL语句执行
select sid,sname,cid from t_student where sid=#{sid}
【注】当要看班级名时,如:
System.out.println("student.getClazz().getCname() = " + student.getClazz().getCname());
此时就会执行两条SQL语句
select sid,sname,cid from t_student where sid=#{sid} + select cid,cname from t_clazz where cid=#{cid}
association标签中的fetchType="lazy",是局部的设置,只对当前的association关联的SQL语句起作用。
在mybatis-config.xml中,作如下配置
<settings> <setting name="lazyLoadingEnabled" value="true"/> </settings>
表示,开启延迟加载的全局开关。默认值false不开启。(所有的分步都采用延迟加载)
1.在实际的开发中,大部分都是需要使用延迟加载的,所以建议开启全部的延迟加载机制。
2.实际开发中的模式中通常都是把全局的开关打开,如果谁不需要延迟加载,就设置
fetchType="eager"