一、第一种方式(一条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"