Mybatis延遲加載詳解

一、通過select語句實現延遲加載

在Mybatis中,延遲加載可以使用select語句來實現。假設我們有兩個表,一個是用戶表,一個是訂單表,用戶表中保存了用戶的基本信息,訂單表中保存了用戶的訂單信息。這兩個表之間是一對多關係,即一個用戶可以擁有多個訂單。

在使用Mybatis查詢一條用戶記錄時,如果需要同時查詢該用戶的所有訂單信息,需要在Mapper文件中定義如下的select語句:

<select id="getUserWithOrders" resultMap="userMap">
  select * from user where id = #{userId}
  select * from order where user_id = #{userId}
</select>

這樣的查詢會產生一個問題:在查詢用戶信息時,同時也會查詢該用戶的所有訂單信息,如果該用戶擁有數千條訂單信息,那麼查詢的效率就會非常低。此時,可以通過使用Mybatis的延遲加載來解決這個問題。

二、Mybatis延遲加載是什麼

Mybatis中的延遲加載,指的是當我們查詢一條記錄時,並不會立即查詢該記錄的關聯記錄,而是當我們需要訪問該關聯記錄時,才會進行查詢。這種方式可以有效提高查詢效率。

三、Mybatis延遲加載的原理面試題

Mybatis的延遲加載原理是什麼?

在Mybatis中,延遲加載是通過動態代理實現的。當我們調用一個延遲加載的關聯對象時,Mybatis會首先判斷該對象是否為空,如果為空,則調用Mapper接口中的方法,查詢該關聯對象。在查詢完成後,將查詢結果封裝到代理對象中,並返回該代理對象。

四、Mybatis延遲加載默認

Mybatis的延遲加載默認是關閉的。如果需要啟用延遲加載,則需要在配置文件中開啟相應的延遲加載項。

五、Mybatis延遲加載的實現方式

Mybatis中的延遲加載,有兩種實現方式:

1. 延遲加載關聯對象

延遲加載關聯對象,指的是只有在需要訪問關聯對象時,才會進行查詢。這種方式可以避免一次性查詢大量數據,提高查詢效率。

2. 延遲加載屬性

延遲加載屬性,指的是只有在需要訪問屬性時,才會進行查詢。這種方式可以避免查詢出大量無用的數據,提高查詢效率。

六、Mybatis延遲加載的原理

Mybatis中的延遲加載,通過動態代理的方式實現。在查詢時,如果需要延遲加載某個關聯對象或屬性,Mybatis會將該對象或屬性封裝到一個代理對象中,並返回該代理對象。

當我們訪問代理對象時,Mybatis會先判斷代理對象中是否已經加載了該關聯對象或屬性,如果沒有加載,則調用Mapper接口中的方法,查詢該關聯對象或屬性。在查詢完成後,將查詢結果封裝到代理對象中,並返回該代理對象。下次訪問該關聯對象或屬性時,直接返回代理對象中的值,不再進行查詢。

七、Mybatis延遲加載怎麼配置

Mybatis中的延遲加載需要在配置文件中進行配置。可以通過在Mapper文件中使用select標籤,並指定fetchType屬性的方式,來開啟延遲加載。

例如,在查詢用戶信息時,我們可以通過以下方式開啟延遲加載:

<resultMap id="userMap" type="user">
  <result property="id" column="id"/>
  <result property="name" column="name"/>
  <result property="orders" column="id" select="getOrdersByUserId" fetchType="lazy"/>
</resultMap>

<select id="getUserById" resultMap="userMap">
  select * from user where id = #{id}
</select>

<select id="getOrdersByUserId" resultMap="orderMap">
  select * from order where user_id = #{id}
</select>

在上面的代碼中,我們使用了resultMap來定義查詢結果的映射關係。其中,fetchType屬性指定了關聯對象的延遲加載方式。lazy表示延遲加載,即只有在需要訪問該關聯對象時,才會進行查詢。

八、Mybatis延遲加載沒反應

如果在使用Mybatis的延遲加載時,發現沒有生效,可能是由於以下幾個原因:

1. 配置文件中未開啟延遲加載

在使用延遲加載時,需要在配置文件中開啟相應的延遲加載項。如果未開啟,延遲加載是不會生效的。

2. 關聯對象已經被加載

如果一個關聯對象已經被加載過了,則再次訪問該對象時,不會觸發延遲加載。在這種情況下,可以考慮使用二級緩存。

3. 關聯對象不存在

如果一個關聯對象不存在,則再次訪問該對象時,也不會觸發延遲加載。在這種情況下,需要檢查關聯對象的外鍵值是否正確。

九、Mybatis二級緩存

Mybatis中的二級緩存,是用來緩存Mapper文件中的查詢結果的。在需要查詢相同結果集時,如果已經存在於緩存中,就可以直接從緩存中獲取結果,而不需要再次進行查詢。這樣可以有效提高查詢效率。

在使用Mybatis的延遲加載時,可以使用二級緩存來避免多次查詢同一條記錄的關聯對象。當一個關聯對象已經被加載過了,可以將該對象緩存到二級緩存中。在下次訪問該關聯對象時,就可以直接從緩存中獲取,而不再進行查詢。

在Mybatis中,可以通過在配置文件中開啟二級緩存和指定緩存類型來開啟二級緩存。例如:

<settings>
  <setting name="cacheEnabled" value="true"/>
</settings>

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

在上面的代碼中,我們開啟了二級緩存,並指定了緩存類型為Ehcache。如果需要使用其他類型的緩存,可以在type屬性中指定相應的緩存類型。

十、Mybatis延遲加載附源碼

以下是使用Mybatis實現延遲加載的源碼:

public interface UserMapper {
  User getUserWithOrders(long userId);
}

// Mapper文件中的查詢語句
<select id="getUserWithOrders" resultMap="userMap">
  select * from user where id = #{userId}
  select * from order where user_id = #{userId}
</select>

public class UserMapperImpl implements UserMapper {
  private final SqlSession sqlSession;
  private final OrderMapper orderMapper;

  public UserMapperImpl(SqlSession sqlSession, OrderMapper orderMapper) {
    this.sqlSession = sqlSession;
    this.orderMapper = orderMapper;
  }

  @Override
  public User getUserWithOrders(long userId) {
    User user = sqlSession.selectOne("getUserById", userId);
    user.setOrders(() -> orderMapper.getOrdersByUserId(userId));
    return user;
  }
}

public interface OrderMapper {
  List<Order> getOrdersByUserId(long userId);
}

// Mapper文件中的查詢語句
<select id="getOrdersByUserId" resultMap="orderMap">
  select * from order where user_id = #{userId}
</select>

public class OrderMapperImpl implements OrderMapper {
  private final SqlSession sqlSession;

  public OrderMapperImpl(SqlSession sqlSession) {
    this.sqlSession = sqlSession;
  }

  @Override
  public List<Order> getOrdersByUserId(long userId) {
    return sqlSession.selectList("getOrdersByUserId", userId);
  }
}

public class User {
  private long id;
  private String name;
  private List<Order> orders;

  // getters and setters
}

public class Order {
  private long id;
  private long userId;
  private String content;

  // getters and setters
}

public interface LazyLoader<V> {
  V load();
}

public class LazyObject<T> implements Serializable {
  private static final long serialVersionUID = 1L;

  private final LazyLoader<T> loader;
  private T value;

  public LazyObject(LazyLoader<T> loader) {
    this.loader = loader;
  }

  public T getValue() {
    if (value == null) {
      value = loader.load();
    }
    return value;
  }
}

public class LazyList<T> extends ArrayList<T> implements Serializable {
  private static final long serialVersionUID = 1L;

  private final LazyLoader<List<T>> loader;

  public LazyList(LazyLoader<List<T>> loader) {
    this.loader = loader;
    add(null);
  }

  @Override
  public T get(int index) {
    T value = super.get(index);
    if (value == null) {
      List<T> list = loader.load();
      if (list != null && list.size() > index) {
        value = list.get(index);
        set(index, value);
      }
    }
    return value;
  }
}

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/284509.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-22 15:41
下一篇 2024-12-22 15:41

相關推薦

  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • QML 動態加載實踐

    探討 QML 框架下動態加載實現的方法和技巧。 一、實現動態加載的方法 QML 支持從 JavaScript 中動態指定需要加載的 QML 組件,並放置到運行時指定的位置。這種技術…

    編程 2025-04-29
  • 理解Mybatis中的SQL Limit用法

    Mybatis是一種非常流行的ORM框架,提供了SQL映射配置文件,可以使用類似於傳統SQL語言的方式編寫SQL語句。其中,SQL的Limit語法是一個非常重要的知識點,能夠實現分…

    編程 2025-04-29
  • 類加載的過程中,準備的工作

    類加載是Java中非常重要和複雜的一個過程。在類加載的過程中,準備階段是其中一個非常重要的步驟。準備階段是在類加載的連接階段中的一個子階段,它的主要任務是為類的靜態變量分配內存,並…

    編程 2025-04-28
  • Lazarus LoadLibrary:DLL動態鏈接庫的加載和使用

    本文將從以下幾個方面介紹Lazarus中LoadLibrary和FreeLibrary函數的使用方法: 一、簡介 LoadLibrary和FreeLibrary是Windows動態…

    編程 2025-04-27
  • Spring Boot本地類和Jar包類加載順序深度剖析

    本文將從多個方面對Spring Boot本地類和Jar包類加載順序做詳細的闡述,並給出相應的代碼示例。 一、類加載機制概述 在介紹Spring Boot本地類和Jar包類加載順序之…

    編程 2025-04-27
  • 用Python加載鳶尾花數據

    本文將詳細介紹如何使用Python加載鳶尾花數據,包括數據源的介紹、數據的獲取和清洗、數據可視化等方面。 一、數據源的介紹 鳶尾花數據集(Iris dataset)是常用的分類實驗…

    編程 2025-04-27
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25

發表回復

登錄後才能評論