MyBatis延遲加載策略詳解

延遲加載就是在需要用到數據的時候才進行加載,不需要用到數據的時候就不加載數據。延遲加載也稱爲懶加載。

優點:在使用關聯對象時,才從數據庫中查詢關聯數據,大大降低數據庫不必要開銷。

缺點:因爲只有當需要用到數據時,纔會進行數據庫查詢,這樣在大批量數據查詢時,因爲查詢工作也需要耗費時間,所以可能造成用戶等待時間變長,造成用戶體驗下降。

數據庫模型準備

下面我們給出的就是一個數據庫關係模型,在後面的例子中一這兩個表爲基礎講解MyBatis延遲加載。我們假定Article(文章)與Tag(標籤)是一對多的關係。

在這裏插入圖片描述

注意面這段話的表述:表的關聯關係大致可以分爲四種:一對一、多對一、一對多、多對多,但是實質上從單獨一個表的角度上來看只存在一對一和一對多關係;而一對一和一對多的關係都能通過下列兩個表來表示,以Article表的角度上來看,一個Article數據可以由多個Tag數據行對應,這就是一對多的關係;而一個Tag數據只能與一個Article關聯,這就是一對一的關係。所以瞭解了MyBatis一對多的延遲加載的配置(雙向)也就學會了四種關聯模式的配置。

第一步:配置MyBatis核心配置文件

如果想使用延遲加載策略,就需要在MyBatis全局配置文件中開啓延遲加載策略:

{% asset_img 34.png %}
參數詳情參考官方文檔:settings配置

我們在MyBatis全局配置文件(SqlMapConfig.xml)中添加下列代碼:

<settings>
		<setting name="lazyLoadingEnabled"  value="true"/>
		<setting name="aggressiveLazyLoading" value="true"/>
</settings>

第二步:配置映射文件

預先定義ArticleMapper和TagMapper接口

ArticleMapper接口

public interface ArticleMapper {
    Article getArticleById(Long id);
}

TagMapper接口

public interface TagMapper {
    Tag getTagById(Long id);
    
     Tag getTagsByArticleId(Long id);
}

配置ArticleMapper.xml映射文件(一對多配置)

在不使用延遲加載的情況下,我們通常使用的是關聯查詢,直接查出關聯對象的數據:

<mapper namespace="com.tjd.spring_mybatis_plus.mapper.ArticleMapper">
   
    <resultMap id="articleMap" type="Article">
        <id column="id" property="id"></id>
        <result column="title" property="title"></result>
        <result column="content" property="content"></result>
        <collection property="tags" ofType="Tag">
            <id column="tid" property="id"></id>
            <result column="tcontent" property="content"></result>
        </collection>
    </resultMap>

    <select id="getArticleById" resultMap="articleMap" parameterType="long">
      SELECT
	    a.id id,
	    a.title title,
	    a.content content,
	    t.id tid,
	    t.content tcontent
      FROM
	    article a
	    LEFT JOIN tag t ON a.id = t.article_id
      WHERE
	    a.id = #{id}
    </select>

</mapper>

如果要想使用延遲加載策略,那麼映射文件配置就不能採用連接查詢了,因爲這樣一旦SQL語句執行了,關聯數據也就查詢出來了,所以我們要將原來的關聯查詢,轉換成單表查詢:

<mapper namespace="com.tjd.spring_mybatis_plus.mapper.ArticleMapper">
    <resultMap id="articleMap" type="Article">
        <id column="id" property="id"></id>
        <result column="title" property="title"></result>
        <result column="content" property="content"></result>
        <collection  property="tags" ofType="Tag" column="id"  select="com.tjd.spring_mybatis_plus.mapper.TagMapper.getTagsByArticleId" ></collection>
    </resultMap>

    <select id="getArticleById" resultMap="articleMap" parameterType="long">
      select * from article where id=#{id}
    </select>

</mapper>

collection標籤屬性:

  • ofType:用於指定集合元素的數據類型。
  • select:指定用於查詢關聯表數據SQL語句的ID。
  • column:是用於指定使用哪個字段的值作爲條件查詢。

在TagMapper.xml映射文件中定義如下語句

<!--在前面定義的ArticleMapper.xml映射文件中collection標籤中select屬性就是指向的這個SQL語句-->
<select id="getTagsByArticleId" parameterType="long" resultType="Article">
        select * from tag where article_id=#{article_id}
</select>

做到這裏,一對多的延遲加載配置就完成了,在執行ArticleMapper中ID爲getArticleById的SQL語句時,並不會立即執行TagMapper中的getTagsByArticleId,而是在需要時再執行getTagsByArticleId,從而達到了延遲加載的目的。

配置TagMapper.xml映射文件(一對一 或 多對一 配置)

<mapper namespace="com.tjd.spring_mybatis_plus.mapper.TagMapper">

    <resultMap id="tagMap" type="Tag">
        <id column="id" property="id"></id>
        <result column="content" property="content"></result>
        <association property="article" column="article_id" javaType="Article" select="com.tjd.spring_mybatis_plus.mapper.ArticleMapper.getArticleById"></association>
    </resultMap>
    
    <!--並沒有採用關聯查詢-->
    <select id="getTagById" parameterType="long" resultMap="tagMap">
        select * from tag where id=#{id}
    </select>

    <select id="getTagsByArticleId" parameterType="long" resultMap="Article">
        select * from tag where article_id=#{article_id}
    </select>
</mapper>

association標籤屬性:

  • ofType:用於指定集合元素的數據類型。
  • select:指定用於查詢關聯表數據SQL語句的ID。

第三步:測試

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class LazyLoadTest {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private TagMapper tagMapper;

    @Test
    public void test(){
        Tag tag = tagMapper.getTagById(1L);
    	Article article = tag.getArticle();
    	List<Tag> tags = article.getTags();
    }
}

如果想要驗證延遲加載策略,我們推薦採用Debug,開啓MyBatis SQL日誌功能,然後每執行一條語句就會發現控制檯輸出一條SQL語句,這就表明它的關聯數據是延遲查詢的。
在這裏插入圖片描述

博主的個人首頁,有興趣的小夥伴可以關注一下:www.bigcoder.cn(部分地區網速比較慢,各位看官稍等哈)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章