数据库准备:
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(); }