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 mapper PUBLIC "-//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"> select d.*, a.id Aid, a.user_id, a.summary, a.title, a.read_count, a.create_time, a.update_time from article_detail d left join article a on d.article_id = a.id where d.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 mapper PUBLIC "-//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 mapper PUBLIC "-//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 mapper PUBLIC "-//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"> select a.*, d.id Did, d.content from article a left join article_detail d on a.id = d.article_id where 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 mapper PUBLIC "-//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”。