當前位置:
首頁 > 知識 > MyBatis中的緩存

MyBatis中的緩存

Mybatis作為持久化框架,提供了非常強大的緩存特性。一般在提到Mybatis緩存的時候,指的都是二級緩存。一級緩存,即本地緩存,默認會啟用並且不能控制,可能會導致一些難以發現的錯誤。

一、一級緩存

[java] view plain copy

  1. public

    void

    testL1Cache() {
  2. SqlSession sqlSession = getSqlSession();
  3. SysUser user1 =

    null

    ;
  4. try

    {

  5. UserMapper userMapper = sqlSession.getMapper(UserMapper.

    class

    );
  6. user1 = userMapper.selectById(1L);
  7. user1.setUserName("New Name");
  8. SysUser user2 = userMapper.selectById(1L);
  9. // 雖然沒有更新資料庫,但是這個用戶名和user1重新複製的名字相同
  10. Assert.assertEquals("New Name", user2.getUserName());
  11. // 無論如何,user2和user1完全就是同一個實例
  12. Assert.assertEquals(user1, user2);
  13. }

    finally

    {
  14. sqlSession.close();
  15. }
  16. System.out.println("開啟新的sqlSession");
  17. sqlSession = getSqlSession();
  18. try

    {
  19. UserMapper userMapper = sqlSession.getMapper(UserMapper.

    class

    );
  20. SysUser user2 = userMapper.selectById(1L);
  21. Assert.assertNotSame("New Name", user2.getUserName());
  22. Assert.assertNotSame(user1, user2);
  23. // 執行刪除操作
  24. userMapper.deleteById(2L);
  25. //獲取user3
  26. SysUser user3 = userMapper.selectById(1L);
  27. Assert.assertNotSame(user3, user2);
  28. }

    finally

    {

  29. sqlSession.close();
  30. }
  31. }

在如上的測試代碼中,獲取到user1之後,重新設置了username的值,但並未更新到資料庫中;當再次執行該對象的查詢之後,發現得到的user2對象的username屬性和user1之前重新設置的值一樣,並且此時user1和user2是同一個對象。這就是一級緩存導致的。

Mybatis的一級緩存存在於SqlSession的生命周期當中,意思就是說,在同一個SqlSession中執行的查詢操作,且中間不包括增刪改的操作時,如果該對象在之前已經查詢過,新查詢獲取到的都將是保存在緩存中的這個對象。當二級緩存沒有開啟時,我們重新開啟一個SqlSession,這時再查詢,就不再是之前的緩存的那個對象了。這是因為在SqlSession關閉時,緩存已經被清空了。

如果不想讓該方法使用一級緩存,可以在該方法的xml文件中增加 flushCache="true" 的屬性。這樣配置之後,在該方法的每次查詢之前都會清空當前的一級緩存,重新從資料庫中查詢對象,可以避免上面的問題。但是這個方法由於清空了一級緩存,會影響當前SqlSession緩存的所有查詢,會增加資料庫的查詢次數,導致性能的下降。

二、二級緩存

不同於一級緩存,二級緩存的生命周期可以理解為SqlSessionFactory的生命周期。二級緩存的相關配置在這裡就不敘述了。需要注意的是,xml配置方式和註解配置方式不能同時使用,會因為命名空間的衝突而導致異常,可以將其中一個改為參照緩存即可。

[java] view plain copy

  1. public

    void

    testL2Cache(){
  2. SqlSession sqlSession = getSqlSession();
  3. SysRole role1 =

    null

    ;

  4. try

    {
  5. RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.

    class

    );
  6. role1 = roleMapper.selectById(1L);
  7. role1.setRoleName("New Name");
  8. SysRole role2 = roleMapper.selectById(1L);
  9. Assert.assertEquals("New Name", role2.getRoleName());
  10. Assert.assertEquals(role1, role2);
  11. }

    finally

    {
  12. sqlSession.close();
  13. }
  14. System.out.println("開啟新的SqlSession");
  15. try

    {
  16. sqlSession = getSqlSession();
  17. RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.

    class

    );
  18. SysRole role2 = roleMapper.selectById(1L);
  19. Assert.assertEquals("New Name", role2.getRoleName());
  20. Assert.assertNotEquals(role1, role2);
  21. SysRole role3 = roleMapper.selectById(1L);
  22. Assert.assertNotEquals(role3, role2);
  23. }

    finally

    {
  24. sqlSession.close();
  25. }
  26. }

上面的測試代碼中,再次獲取role2時,即使已經在一個新的SqlSession當中,一級緩存已經清空,role2並不會執行資料庫的查詢操作,而是到Mybatis的二級緩存中取出對象,此時role2的rolename屬性為之前修改後的值。由於在本測試用例中,配置的二級緩存屬性為可讀寫緩存,role2和role3都是反序列化的介面,所以他們並不是相同的實例。如果配置為只讀緩存,role2和role3獲得的將是緩存中role1的引用,將會是相同的實例。

目前,mybatis支持EhCache緩存框架以及Redis緩存資料庫來保存mybatis的二級緩存。

MyBatis中的緩存

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

主機 電子郵件訪問
AppML  Products 之完整的應用程序

TAG:程序員小新人學習 |