文章出處

1. 什么是延遲加載

  舉個例子:如果查詢訂單并且關聯查詢用戶信息。如果先查詢訂單信息即可滿足要求,當我們需要查詢用戶信息時再查詢用戶信息。把對用戶信息的按需去查詢就是延遲加載。 所以延遲加載即先從單表查詢、需要時再從關聯表去關聯查詢,大大提高數據庫性能,因為查詢單表要比關聯查詢多張表速度要快。 
  我們來對比一下:

關聯查詢:SELECT orders.*, user.username FROM orders, USER WHERE orders.user_id = user.id 
延遲加載相當于: 
SELECT orders.*, 
(SELECT username FROM USER WHERE orders.user_id = user.id)username FROM orders

 所以這就比較直觀了,也就是說,我把關聯查詢分兩次來做,而不是一次性查出所有的。第一步只查詢單表orders,必然會查出orders中的一個user_id字段,然后我再根據這個user_id查user表,也是單表查詢。下面來總結一下如何使用這個延遲加載

2. 使用association實現延遲加載

  前面博文中總結了resultMap可以實現高級映射(使用association、collection實現一對一及一對多映射),其實association和collection還具備延遲加載的功能,這里我就拿association來說明,collection和association使用的方法都是一樣的。需求就是上面提到的,查詢訂單并且關聯查詢用戶,查詢用戶使用延遲加載。 
  由上面的分析可知,延遲加載要查詢兩次,第二次是按需查詢,之前一對一關聯查詢的時候只需要查一次,把訂單和用戶信息都查出來了,所以只要寫一個mapper即可,但是延遲加載查兩次,所以理所當然要有兩個mapper。

2.1 兩個mapper.xml

  需要定義兩個mapper的方法對應的statement。先來分析一下思路:

 

  1. 只查詢訂單信息的statement,使用resultMap
  2. 通過查詢到的訂單信息中的user_id去查詢用戶信息的statement,得到用戶
  3. 定義的resultMap將兩者關聯起來,即用訂單信息user_id去查用戶

下面來實現這個思路: 
1. 只查詢訂單信息的statement:

 

<select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap">
    SELECT * FROM orders
</select>

 

2. 只查詢用戶信息的statement:

<select id="findUserById" parameterType="int" resultType="user">
    select * from user where id = #{id}
</select>

3. 定義上面那個resultMap: 
resultMap

2.2 延遲加載的配置

  mybatis默認沒有開啟延遲加載,需要在SqlMapConfig.xml中setting配置。前面一篇博文中提到SqlMapConfig.xml中的一些配置,有一個<settings>,當時沒說,這里就派上用場了,可以通過這個標簽來配置一下延遲加載。

 

<settings>
    <!-- 打開延遲加載的開關 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 將積極加載改為消極加載,即延遲加載 -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

 

2.3 mapper.java

  別忘了寫mapper接口:

 

public interface UserMapperOrders {

    //省去不相關代碼

    //查詢訂單,關聯用戶查詢,用戶查詢用的是延遲加載
    public List<Orders> findOrdersUserLazyLoading() throws Exception;
}

 

到此為止,延遲加載就做完了,下面來測試一下:

@Test
public void testFindOrdersUserLazyLoading() throws Exception {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapperOrders userMapperOrders = sqlSession.getMapper(UserMapperOrders.class);
    //查詢訂單表(單表)
    List<Orders> list = userMapperOrders.findOrdersUserLazyLoading();

    //遍歷上邊的訂單列表
    for(Orders orders : list) {
        //執行getUser()去查詢用戶信息,這里實現按需加載
        User user = orders.getUser();
        System.out.println(user);
    }
}

看一下執行結果: 
執行結果
  執行結果很明顯,使用了延遲加載,將關聯查詢分成了兩次單表查詢,但是有個奇怪的地方,就是第二次查用戶的時候,并沒有發sql,而是直接就拿到了,其實這就是mybatis中的一級緩存,也是我下一篇博文要總結的東東。 
   

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()