MyBatis的⾼级映射及延迟加载
- 一、多对一
- 1.方式一:级联属性映射
- 2.方式二:association
- 3.方式三:分步查询
- 二、一对多
- 1.方式一:collection
- 2.方式二:分步查询
- 三、延迟加载(懒加载)
- 1.分步查询的优点
- 2.延迟加载(懒加载)
- 开始写代码前先了解数据库表的结构。
一、多对一
- 以ArticleDetail表(主键)为多,Article表为一。
1.方式一:级联属性映射
-
编写pojo实体类
package com.gdb.mybatis.advancedMapping.pojo;public class ArticleDetail {private Integer id;private String content;private Article article; //多对一,多的为主表时,在主表中添加⼀个属性:Article article; //有参构造、无参构造、toString、set和get方法... }
-
编写映射文件Article
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.gdb.mybatis.advancedMapping.mapper.ArticleDetailMapper"><resultMap id="ArticleDetailResultMap" type="ArticleDetail" ><id property="id" column="id"/><result property="content" column="content"/><result property="article.id" column="Aid"/><result property="article.userId" column="user_id"/><result property="article.title" column="title"/><result property="article.summary" column="summary"/><result property="article.readCount" column="read_count"/><result property="article.createTime" column="create_time"/><result property="article.updateTime" column="update_time"/></resultMap><select id="selectArticleDetailForId" resultMap="ArticleDetailResultMap">selectd.*, a.id Aid, a.user_id, a.summary, a.title, a.read_count, a.create_time, a.update_timefromarticle_detail d left join article a on d.article_id = a.idwhered.id = #{id}</select> </mapper>
-
测试程序
@org.junit.Test public void TestSelectArticleDetailForId(){SqlSession sqlSession = SqlSessionUtil.openSqlsession();ArticleDetailMapper mapper = sqlSession.getMapper(ArticleDetailMapper.class);ArticleDetail articleDetail = mapper.selectArticleDetailForId(1);System.out.println(articleDetail);System.out.println(articleDetail.getArticle());sqlSession.close(); }
-
结果展示
2.方式二:association
- 其他位置都不需要修改,只需要修改resultMap中的配置:association即可。
<resultMap id="ArticleDetailResultMap" type="ArticleDetail" ><id property="id" column="id"/><result property="content" column="content"/><association property="article" javaType="Article"><id property="id" column="id"/><result property="id" column="Aid"/><result property="userId" column="user_id"/><result property="title" column="title"/><result property="summary" column="summary"/><result property="readCount" column="read_count"/><result property="createTime" column="create_time"/><result property="updateTime" column="update_time"/></association>
</resultMap>
3.方式三:分步查询
-
其他位置不需要修改,只需要修改以及添加以下三处:
- 第一处:在ArticleMapper接⼝中添加⽅法。
package com.gdb.mybatis.advancedMapping.mapper;import com.gdb.mybatis.advancedMapping.pojo.Article;public interface ArticleMapper {Article selectArticleForId(Integer id); }
- 第二处:在ArticleMapper.xml⽂件中进⾏配置
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.gdb.mybatis.advancedMapping.mapper.ArticleMapper"><select id="selectArticleForId" resultType="Article">select * from article where id = #{id};</select> </mapper>
- 第三处:在ArticleDetailMapper.xml文件中的association标签中select位置填写sqlId。sqlId=namespace+id。其中column属性作为这条⼦sql语句的条件。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.gdb.mybatis.advancedMapping.mapper.ArticleDetailMapper"><resultMap id="ArticleDetailResultMap" type="ArticleDetail" ><id property="id" column="id"/><result property="content" column="content"/><association property="article" select="com.gdb.mybatis.advancedMapping.mapper.ArticleMapper.selectArticleForId" column="article_id"/></resultMap><select id="selectArticleDetailForId" resultMap="ArticleDetailResultMap">select * from article_detail where id = #{id};</select> </mapper>
二、一对多
-
⼀对多的实现,通常是在⼀的⼀⽅中有List集合属性。
package com.gdb.mybatis.advancedMapping.pojo;import java.util.Date; import java.util.List;public class Article {private Integer id;private Integer userId;private String title;private String summary;private Integer readCount;private Date createTime;private Date updateTime;private List<ArticleDetail> articleDetailList;//有参构造、无参构造、toString、set和get方法... }
1.方式一:collection
-
ArticleMapper中添加方法
public interface ArticleMapper {Article selectArticleForId(Integer id); }
-
编写ArticleMapper.xml映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.gdb.mybatis.advancedMapping.mapper.ArticleMapper"><resultMap id="ArticleResultMap" type="Article"><id property="id" column="id"/><result property="userId" column="user_id"/><result property="title" column="title"/><result property="summary" column="summary"/><result property="readCount" column="read_count"/><result property="createTime" column="create_time"/><result property="updateTime" column="update_time"/><collection property="articleDetailList" ofType="ArticleDetail"><id property="id" column="Did"/><result property="content" column="content"/></collection></resultMap><select id="selectArticleForId" resultMap="ArticleResultMap">selecta.*, d.id Did, d.contentfromarticle a left join article_detail d on a.id = d.article_idwhere a.id = #{id}</select> </mapper>
- 注意是ofType,表示“集合中的类型”。
-
编写测试程序
@org.junit.Test public void TestSelectArticleForId(){SqlSession sqlSession = SqlSessionUtil.openSqlsession();ArticleMapper mapper = sqlSession.getMapper(ArticleMapper.class);Article article = mapper.selectArticleForId(1);System.out.println(article);System.out.println(article.getArticleDetailList());sqlSession.close(); }
-
查询结果
2.方式二:分步查询
-
和多对一的分布查询方式一样,只需要修改三处的代码即可。
-
第一处:修改映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.gdb.mybatis.advancedMapping.mapper.ArticleMapper"><resultMap id="ArticleResultMap" type="Article"><id property="id" column="id"/><result property="userId" column="user_id"/><result property="title" column="title"/><result property="summary" column="summary"/><result property="readCount" column="read_count"/><result property="createTime" column="create_time"/><result property="updateTime" column="update_time"/><collection property="articleDetailList" select="com.gdb.mybatis.advancedMapping.mapper.ArticleDetailMapper.selectArticleDetailByArticleId" column="id"/></resultMap><select id="selectArticleForId" resultMap="ArticleResultMap">select * from article where id = #{id};</select> </mapper>
-
第二处:在ArticeDetailMapper中添加方法
/*** 通过文章的编号 id,查询文章下所有的评论* @param ArticleId 文章id* @return 返回对应文章下的所有评论*/ List<ArticleDetail> selectArticleDetailByArticleId(Integer ArticleId);
-
第三处:编写ArticleDetailMapper.xml文件中的sql语句。
<select id="selectArticleDetailByArticleId" resultType="ArticleDetail">select * from article_detail where article_id = #{articleId}; </select>
三、延迟加载(懒加载)
1.分步查询的优点
- 第一:复用性增强,可以重复利用。(大步拆成 N 个小碎步。每一步更加可以复用)。
- 第二:采用这种分步查询,可以充分利用他们的延迟加载/懒加载机制。
2.延迟加载(懒加载)
- 延迟加载的核心原理是:用的时候再执行查询语句。不用的时候不查询。
- 作用:提高性能。尽可能的不查,或者说尽可能的少查。来提高效率。
- 在mybatis当中怎么开启延迟加载:
- association 标签中添加fetchType = “lazy”
- 注意:默认情况下是没有开启延迟加载的。需要设置:fetchType = “lazy”
- 这种在association标签中配置fetchType=“lazy”,是局部设置,只对当前的association关联的sql语句起作用。
- 在实际的开发中,大部分都是需要使用延迟加载的,所以建议开启全部的延迟加载机制。
- 在 mybatis 核心配置文件中添加全局配置:lazyLoadingEnabled=true
- 实际开发中的模式:
- 把全局的延迟加载开启。
- 如果某一步不需要使用延迟加载,设置:fetchType=“eager”。