<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] ***** # 7.2 二級緩存 MyBatis的二級緩存在于 SqlSessionFactory 的 生命周期中。 當存在多個SqlSessionFactory時, 它們的緩存都是綁定在各自對象上的, 緩存數據在一般情況下是不相通的。 只有在使用如 Redis這樣的緩存數據庫時, 才可以共享緩存。 ## **7.2.1 配置二級緩存** **全局配置** 在mybatis-config.xml中, 這個參數值默認為 true, 可以不必配置。 ![](https://box.kancloud.cn/751b7875e5e3cc84ae0568b4e658c02e_589x122.png) ***** MyBatis的二級緩存是和命名空間綁定的, 即二級緩存需要配置在Mapper.xml映射文件中或者配置在 Mapper.java 接口中。 * 在XML中, 命名空間就是 XML 根節點 mapper 的namespace屬性。 * 在Mapper接 口中, 命名空間就是接口的全限定名稱。 ### **7.2.1.1 Mapper.xml中配置二級緩存** 在RoleMapper.xml 開啟二級緩存,加cache標簽 ![](https://box.kancloud.cn/fcb0c70430819e26833f097dd0b5ab4d_721x256.png) #### **默認的二級緩存會有如下效果** * 映射語句文件中的所有SELECT語句將會被緩存。 * 映射語句文件中的所有INSERT、 UPDATE、 DELETE語句**會刷新二級緩存**。 * *緩存會使用Least Recently Used(LRU, 最近最少使用的) 算法來收回。* * *根據時間表(如no Flush Interval, 沒有刷新間隔) ,緩存不會以任何時間順序來刷新。* * 緩存會存儲集合或對象(無論查詢方法返回什么類型的值) 的1024個引用。 * 緩存會被視為read/write(可讀/可寫)的,對象不是共享的, 可以安全地被調用者修改, 并且不干擾其他調用者或線程所做的修改 **二級緩存屬性配置示例** ![](https://box.kancloud.cn/d162b5ea9eb6d84408a64abdc5419936_363x189.png) * 創建了一個FIFO緩存 * 每隔60秒刷新一次 * 存儲集合或對象的512個引用 * 返回的對象被認為是只讀的, 在不同線程中的調用者之間修改它們會導致沖突。 ***** #### **cache可以配置的屬性** **eviction(收回策略)** * LRU(最近最少使用的) : 移除最長時間不被使用的對象, 這是默認值。 * FIFO(先進先出) : 按對象進入緩存的順序來移除它們。 * *SOFT(軟引用) : 移除基于垃圾回收器狀態和軟引用規則的對象。* * *WEAK(弱引用) : 更積極地移除基于垃圾收集器狀態和弱引用規則的對象。* **flushInterval(刷新間隔)** 。 可以被設置為任意的正整數, 而且它們代表一個合理的毫秒形式的時間段。 默認情況不設置, 沒有刷新間隔, 緩存僅僅在調用語句(insert,update,delete)時刷新。 **size(引用數目**) 。 可以被設置為任意正整數, 要記住緩存的對象數目和運行環境的可用內存資源數目。 默認值是1024。 **readOnly(只讀)** * 只讀,true。給調用者返回緩存對象的相同實例。性能有優勢,對象不能被修改。 * 可讀寫,false。通過序列化返回緩存對象的拷貝(不同的實例)。 慢, 但安全。 ## **7.2.2 使用二級緩存** * MyBatis使用SerializedCache(org.apache.ibatis.cache.decorators.SerializedCache)序列化緩存來實現可讀寫緩存類, 并通過序列化和反序列化來通過緩存獲取數據時, 得到的是一個新的實例。 * 因為使用可讀寫緩存,可以使用SerializedCache序列化緩存,這個緩存類要求所有被序列化的對象必須實現Serializable(java.io.Serializable) 接口, 所以還需要修改SysRole對象 ![](https://box.kancloud.cn/76b400762dfd9bf32eb4ed2f2dd5eda9_794x266.png) **在CacheTest.java中測試二級緩存** ``` @Test public void testL2Cache(){ //獲取 sqlSession SqlSession sqlSession = getSqlSession(); SysRole role1 = null; try { //獲取 RoleMapper 接口 RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class); //調用 selectById 方法,查詢 id = 1 的用戶 role1 = roleMapper.selectById(1l); //對當前獲取的對象重新賦值 role1.setRoleName("New Name"); //再次查詢獲取 id 相同的用戶 SysRole role2 = roleMapper.selectById(1l); //雖然我們沒有更新數據庫,但是這個用戶名和我們 role1 重新賦值的名字相同了 Assert.assertEquals("New Name", role2.getRoleName()); //不僅如何,role2 和 role1 完全就是同一個實例 因為此時默認使用一級緩存,返回同一個實例 Assert.assertEquals(role1, role2); } finally { //關閉當前的 sqlSession sqlSession.close(); } System.out.println("開啟新的 sqlSession"); //開始另一個新的 session sqlSession = getSqlSession(); try { //獲取 RoleMapper 接口 RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class); //調用 selectById 方法,查詢 id = 1 的用戶 SysRole role2 = roleMapper.selectById(1l); //第二個 session 獲取的用戶名仍然是 New Name Assert.assertEquals("New Name", role2.getRoleName()); //這里的 role2 和 前一個 session 查詢的結果是兩個不同的實例 Assert.assertNotEquals(role1, role2); //獲取 role3 SysRole role3 = roleMapper.selectById(1l); //這里的 role2 和 role3 是兩個不同的實例 Assert.assertNotEquals(role2, role3); } finally { //關閉 sqlSession sqlSession.close(); } } ``` 在第一個try塊中使用的是一級緩存, 所以role1和role2是同一個實例。 在第二個try塊中,當調用close方法關閉SqlSession時, SqlSession才會保存查詢數據到二級緩存中。 在這之后二級緩存才有了緩存數據。role2和 role3都是反序列化得到的結果, 所以它們不是相同的實例。 在這一部分, 這兩個實例是讀寫安全的, 其屬性不會互相影響。 **只讀緩存** 配置為只讀緩存,MyBatis就會使用Map來存儲緩存值, 從緩存中獲取的對象就是同一個實例。 #### **注意** 在這個例子中并沒有真正的讀寫安全, 為什么?因為這個測試中加入了一段不該有的代碼, 即role1.setRoleName("New Name"); , 這里修改role1的屬性值后, 按照常理應該更新數據, 更新后會清空一、 二級緩存, 這樣就可以避免人 為產生的臟數(數據庫里的roleName和緩存中的roleName不一樣), 避免緩存和數據庫的數據不一致。 所以想要安全使用, 需要避免毫無意義的修改。 #### **總結** **一級緩存:** 當一個SqlSession結束后該SqlSession中的一級緩存也就不存在了。 **二級緩存:** 是mapper級別的緩存。使用二級緩存時,多個SqlSession使用同一個Mapper的sql語句去操作數據庫,得到的數據會存在二級緩存區域,它同樣是使用HashMap進行數據存儲。相比一級緩存SqlSession,二級緩存的范圍更大,多個Sqlsession可以共用二級緩存,二級緩存是跨SqlSession的。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看