数据库准备:
1. 多对一:
多个学生对应一个班级(学生表是主表, 班级表是副表)
多种实现方式, 常见的包括三种
第一种方式: 一条sql语句, 级联属性映射
// StudentMapper.xml
// 一条sql语句, 级联属性映射
<resultMap id="studentResultMap" type="Student">
<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
stu s left join clazz c on s.cid = c.cid
where
s.sid = #{sid}
</select>
// 接口
public interface StudentMapper{
// 根据id获取学生信息, 同时获取学生关联的班级信息
// 返回一个学生对象, 但是学生对象当中含有班级对象
Student selectById(Integer id);
}
// @test
public static void main(String[] args) {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.selectById(6);
System.out.println(student);
sqlSession.close();
}
第二种方式: 一条sql语句, association标签
// StudentMapper.xml
// 一条sql语句, association(关联)
<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
stu s left join clazz c on s.cid = c.cid
where
s.sid = #{sid}
</select>
// 接口
public interface StudentMapper{
// 根据id获取学生信息, 同时获取学生关联的班级信息
// 返回一个学生对象, 但是学生对象当中含有班级对象
// 使用association
Student selectByIdAssociation(Integer id);
}
// @test
public static void main(String[] args) {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.selectByIdAssociation(6);
System.out.println(student);
sqlSession.close();
}
第三种方式: 俩条sql语句, 分布查询(这种方式常用: 优点可复用,支持懒加载)
// StudentMapper.xml
// 一条sql语句, association(关联)
<resultMap id="studentResultMapByStep" type="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
// 会将column传给select这条sql语句
<association property="Clazz"
select="ClazzMapper.selectByIdStep2"
column="cid"/>
</resultMap>
<select id="selectByIdStep1" resultMap="studentResultMapByStep">
select sid,sname,cid from stu where sid = #{sid}
</select>
-------------------------------------------------------------------------------------
// ClazzMapper.xml
<select id="selectByIdStep2" resultType="Clazz">
select cid,cname from clazz where cid = #{cid}
</select>
-------------------------------------------------------------------------------------
// 接口
public interface StudentMapper{
// 分布查询第一步, 先根据id查询出学生信息
Student selectByIdStep1(Integer id);
}
public interface ClazzMapper{
// 分布查询第二步, 根据cid获取班级信息
Clazz selectByIdStep2(Integer cid);
}
// @test
public static void main(String[] args) {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.selectByIdStep1(6);
System.out.println(student);
sqlSession.close();
}
2. 延迟加载:
分布查询的好处:
复用性强, 可以重复使用, 大步拆成多个小碎步, 每一个小碎步更加可以重复利用.
可以充分利用他妈的延迟加载/懒加载机制
什么是延迟加载(懒加载), 有什么用?
延迟加载的核心原理是: 用的时候再执行查询语句, 不用的时候不查询.
作用: 提高性能
在mybatis中怎么开启延迟加载?
默认情况下是没有开启懒加载的
association标签中添加fetchType="lazy"
这种在association标签中配置fetchType="lazy"是局部的设置, 只对当前的association关联的sql语句起作用
<resultMap id="studentResultMapByStep" type="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<association property="Clazz"
// 这条sql语句用到的时候再查询
select="ClazzMapper.selectByIdStep2"
column="cid"
fetchType="lazy"/>
</resultMap>
// 如果只需要查看学生的名字
// 那么就不会使用到ClazzMapper.selectByIdStep2语句
// 如果想看班级的名字
// 那么就会执行ClazzMapper.selectByIdStep2语句了
3. 一对多:
一个班级对应多个学生(班级表是主表, 学生表是副表)
一对多的实现, 通常是在一的一方中有List集合属性
一对多的实现通常包括俩种实现方式:
collection
// ClazzMapper.xml
<resultMap id="clazzResultMap" type="Clazz">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
// 一对多, 这里的collection是集合的意思
// ofType属性用来指定集合当中的元素类型
<collection property="stus //list集合名" ofType="Student">
<id property="sid" column="sid">
<result property="sname" column="sname">
</collection>
</resultMap>
<select id="selectByCollection" resultMap="clazzResultMap">
select c.cid,c.cname,s.sid,s.sname
from clazz c left join stu s on c.cid = s.cid
where c.cid = #{cid}
</select>
// 接口
public interface ClazzMapper{
// 根据班级编号查询班级信息
Clazz selectByCollection(Integer cid);
}
// @test
public static void main(String[] args) {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(StudentMapper.class);
Clazz clazz = mapper.selectByCollection(6);
System.out.println(clazz);
sqlSession.close();
}
分布查询(常用)
// StudentMapper.xml
<select id="selectByIdStep2" resultType="Student">
select * from stu where cid = #{cid}
</select>
-------------------------------------------------------------------------------------
// ClazzMapper.xml
<resultMap id="clazzResultMapStep" type="Clazz">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
// 会将column传给select这条sql语句
<collection property="stus"
select="StudentMapper.selectByCidStep2"
column="cid"/>
</resultMap>
<select id="selectByIdStep1" resultMap="clazzResultMapStep">
select cid,cname from clazz where cid = #{cid}
</select>
-------------------------------------------------------------------------------------
// 接口
public interface StudentMapper{
// 分布查询第二步, 先根据班级编号查询出学生信息
List<Student> selectByCidStep2(Integer id);
}
public interface ClazzMapper{
// 分布查询第一步, 根据班级编号获取班级信息
Clazz selectByIdStep1(Integer cid);
}
// @test
public static void main(String[] args) {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(StudentMapper.class);
Clazz clazz = mapper.selectByIdStep1(6);
System.out.println(clazz);
sqlSession.close();
}