1. 程式人生 > >MyBatis學習(6)

MyBatis學習(6)

throws 垃圾回收器 安全 cep 正整數 sin ret 關系 行刷新

本視頻觀看地址:https://edu.51cto.com/sd/3ec2c

1、緩存

1.1、緩存的意義

將用戶經常查詢的數據放在緩存(內存)中,用戶去查詢數據就不用從磁盤上(關系型數據庫數據文件)查詢,從緩存中查詢,從而提高查詢效率,解決了高並發系統的性能問題

1.2、一級緩存

MyBatis的一級緩存的作用域是session,當openSession()後,如果執行相同的sql(相同語句和參數,MyBatis不執行sql,而是從緩存中命中並返回)
Mybatis執行查詢時首先去緩存區中命中,如果命中直接返回,沒有命中則執行sql,從數據庫中查詢
註意:mybatis和spring整合後進行mapper代理開發,不支持一級緩存,mybatis和spring整合,spring按照mapper的模板去生成mapper代理對象,模板中在最後統一關閉sqlsession

1.2.1、測試一級緩存

@Test
    public void testCache()throws Exception{
        User user = userMapper.selectUserById(8);
        System.out.println(user);

        User user2 = userMapper.selectUserById(8);
        System.out.println(user2);
    }

日誌文件

DEBUG - Opening JDBC Connection
DEBUG - Created connection 1667925979.
DEBUG - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@636a87db]
DEBUG - ==>  Preparing: select userid,user_name as userName,age,pwd,sex,birthday from tb_user where userid = ? 
DEBUG - ==> Parameters: 8(Integer)
DEBUG - <==      Total: 1
User [userid=8, userName=hello, pwd=123456, age=18, sex=男, birthday=Tue Aug 14 10:19:19 CST 2018]
User [userid=8, userName=hello, pwd=123456, age=18, sex=男, birthday=Tue Aug 14 10:19:19 CST 2018]
DEBUG - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@636a87db]
DEBUG - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@636a87db]
DEBUG - Returned connection 1667925979 to pool.

發現只發出一條sql語句,第二次執行實際上是從緩存拿去這個數據

1.2.2、刷新緩存操作

sqlSession.clearCache();

@Test
    public void testCache()throws Exception{
        User user = userMapper.selectUserById(8);
        System.out.println(user);
        //清除緩存
        sqlSession.clearCache();
        User user2 = userMapper.selectUserById(8);
        System.out.println(user2);
    }

日誌文件

DEBUG - Opening JDBC Connection
DEBUG - Created connection 823632238.
DEBUG - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@3117a16e]
DEBUG - ==>  Preparing: select userid,user_name as userName,age,pwd,sex,birthday from tb_user where userid = ? 
DEBUG - ==> Parameters: 8(Integer)
DEBUG - <==      Total: 1
User [userid=8, userName=hello, pwd=123456, age=18, sex=男, birthday=Tue Aug 14 10:19:19 CST 2018]
DEBUG - ==>  Preparing: select userid,user_name as userName,age,pwd,sex,birthday from tb_user where userid = ? 
DEBUG - ==> Parameters: 8(Integer)
DEBUG - <==      Total: 1
User [userid=8, userName=hello, pwd=123456, age=18, sex=男, birthday=Tue Aug 14 10:19:19 CST 2018]
DEBUG - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@3117a16e]
DEBUG - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@3117a16e]
DEBUG - Returned connection 823632238 to pool.

執行了更新操作

@Test
    public void testCache()throws Exception{
        User user = userMapper.selectUserById(8);
        System.out.println(user);
        user.setUserName("李白");
        userMapper.insertUser(user);
        sqlSession.commit();
        User user2 = userMapper.selectUserById(8);
        System.out.println(user2);
    }

日誌文件

DEBUG - Opening JDBC Connection
DEBUG - Created connection 1782252248.
DEBUG - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@6a3b02d8]
DEBUG - ==>  Preparing: select userid,user_name as userName,age,pwd,sex,birthday from tb_user where userid = ? 
DEBUG - ==> Parameters: 8(Integer)
DEBUG - <==      Total: 1
User [userid=8, userName=hello, pwd=123456, age=18, sex=男, birthday=Tue Aug 14 10:19:19 CST 2018]
DEBUG - ==>  Preparing: insert into tb_user(userid,user_name,age,pwd,sex,birthday) values(seq_user.nextval,?,?,?,?,?) 
DEBUG - ==> Parameters: 李白(String), 18(Integer), 123456(String), 男(String), 2018-08-14 10:19:19.0(Timestamp)
DEBUG - <==    Updates: 1
DEBUG - Committing JDBC Connection [oracle.jdbc.driver.T4CConnection@6a3b02d8]
DEBUG - ==>  Preparing: select userid,user_name as userName,age,pwd,sex,birthday from tb_user where userid = ? 
DEBUG - ==> Parameters: 8(Integer)
DEBUG - <==      Total: 1
User [userid=8, userName=hello, pwd=123456, age=18, sex=男, birthday=Tue Aug 14 10:19:19 CST 2018]
DEBUG - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@6a3b02d8]
DEBUG - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@6a3b02d8]
DEBUG - Returned connection 1782252248 to pool.

1.3、二級緩存

mybatis 的二級緩存的作用域是一個mapper的namespace ,同一個namespace中查詢sql可以從緩存中命中

每次查詢先看是否開啟二級緩存,如果開啟從二級緩存的數據結構中取緩存數據,

二級緩存的範圍是mapper級別(mapper同一個命名空間),mapper以命名空間為單位創建緩存數據結構,結構是map<key、value>。

如果從二級緩存沒有取到,再從一級緩存中找,如果一級緩存也沒有 ,從數據庫中查詢

1.3.1、二級緩存

mybatis二級緩存需要將查詢結果映射的pojo實現 java.io.serializable接口,如果不實現則拋出異常

二級緩存可以將內存的數據寫到磁盤,存在對象的序列化和反序列化,所以要實現java.io.serializable接口。

如果結果映射的pojo中還包括了pojo,都要實現java.io.serializable接口。

1.3.2、開啟二級緩存

開啟全局開關(mybatis-config.xml)

<settings>
        <setting name="mapUnderscoreToCamelCase" value="false"/>
        <!-- 二級緩存的全局開關 -->
        <setting name="cacheEnabled" value="true"/>
</settings>

開啟局部開關

<mapper namespace="cn.org.kingdom.mapper.UserMapper">
    <cache/>
    ...
</mapper>

1.3.3、測試二級緩存

@Test
    public void testCache2()throws Exception{
        User user = userMapper.selectUserById(8);
        System.out.println(user);
        sqlSession.close();
        sqlSession  = sqlSessionFactory.openSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
        User user2 = userMapper.selectUserById(8);
        System.out.println(user2);
    }

日誌文件

DEBUG - Checking to see if class cn.org.kingdom.mapper.UserMapper matches criteria [is assignable to Object]
DEBUG - Cache Hit Ratio [cn.org.kingdom.mapper.UserMapper]: 0.0
DEBUG - Opening JDBC Connection
DEBUG - Created connection 221388699.
DEBUG - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@d321f9b]
DEBUG - ==>  Preparing: select userid,user_name as userName,age,pwd,sex,birthday from tb_user where userid = ? 
DEBUG - ==> Parameters: 8(Integer)
DEBUG - <==      Total: 1
User [userid=8, userName=hello, pwd=123456, age=18, sex=男, birthday=Tue Aug 14 10:19:19 CST 2018]
DEBUG - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@d321f9b]
DEBUG - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@d321f9b]
DEBUG - Returned connection 221388699 to pool.
DEBUG - Cache Hit Ratio [cn.org.kingdom.mapper.UserMapper]: 0.5
User [userid=8, userName=hello, pwd=123456, age=18, sex=男, birthday=Tue Aug 14 10:19:19 CST 2018]

1.3.4、刷新緩存

如果sqlsession操作commit操作,對二級緩存進行刷新(全局清空)。設置statement的flushCache是否刷新緩存,默認值是true。

測試類

@Test
    public void testCache2()throws Exception{
        //查詢
        User user = userMapper.selectUserById(8);
        System.out.println(user);
        sqlSession.close();
        //更新操作
        user.setUserName("小喬");
        SqlSession session2 = sqlSessionFactory.openSession();
        UserMapper userMapper3 = session2.getMapper(UserMapper.class);
        userMapper3.updateUser(user);
        session2.commit();

        //再次查詢
        sqlSession  = sqlSessionFactory.openSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
        User user2 = userMapper.selectUserById(8);
        System.out.println(user2);
    }

mapper.xml中

<update id="updateUser" flushCache="false">
    update tb_user set user_name=#{userName},age=#{age},pwd=#{pwd},sex=#{sex},birthday=#{birthday}
    where userid=#{userid}
</update>

日誌

DEBUG - Created connection 876236253.
DEBUG - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@343a4ddd]
DEBUG - ==>  Preparing: select userid,user_name as userName,age,pwd,sex,birthday from tb_user where userid = ? 
DEBUG - ==> Parameters: 8(Integer)
DEBUG - <==      Total: 1
User [userid=8, userName=冰封戰神, pwd=123456, age=18, sex=男, birthday=Tue Aug 14 10:19:19 CST 2018]
DEBUG - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@343a4ddd]
DEBUG - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@343a4ddd]
DEBUG - Returned connection 876236253 to pool.
DEBUG - Opening JDBC Connection
DEBUG - Checked out connection 876236253 from pool.
DEBUG - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@343a4ddd]
DEBUG - ==>  Preparing: update tb_user set user_name=?,age=?,pwd=?,sex=?,birthday=? where userid=? 
DEBUG - ==> Parameters: 小喬(String), 18(Integer), 123456(String), 男(String), 2018-08-14 10:19:19.0(Timestamp), 8(Integer)
DEBUG - <==    Updates: 1
DEBUG - Committing JDBC Connection [oracle.jdbc.driver.T4CConnection@343a4ddd]
DEBUG - Cache Hit Ratio [cn.org.kingdom.mapper.UserMapper]: 0.5
User [userid=8, userName=冰封戰神, pwd=123456, age=18, sex=男, birthday=Tue Aug 14 10:19:19 CST 2018]

對於緩存使用,一般情況,我們要經常使用的數據,這些數據不會發生太大的變化,或者對用戶沒有什麽影響

1.3.5、緩存的高級設置

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>

這個更高級的配置創建了一個 FIFO 緩存,並每隔 60 秒刷新,存數結果對象或列表的 512 個引用,而且返回的對象被認為是只讀的,因此在不同線程中的調用者之間修改它們會 導致沖突。

可用的收回策略有:

  • LRU – 最近最少使用的:移除最長時間不被使用的對象。
  • FIFO – 先進先出:按對象進入緩存的順序來移除它們。
  • SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的對象。
  • WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的對象。

默認的是 LRU。

flushInterval(刷新間隔)可以被設置為任意的正整數,而且它們代表一個合理的毫秒 形式的時間段。默認情況是不設置,也就是沒有刷新間隔,緩存僅僅調用語句時刷新。

size(引用數目)可以被設置為任意正整數,要記住你緩存的對象數目和你運行環境的 可用內存資源數目。默認值是 1024。

readOnly(只讀)屬性可以被設置為 true 或 false。只讀的緩存會給所有調用者返回緩 存對象的相同實例。因此這些對象不能被修改。這提供了很重要的性能優勢。可讀寫的緩存 會返回緩存對象的拷貝(通過序列化) 。這會慢一些,但是安全,因此默認是 false。

最後歡迎關註我的網絡課堂:https://edu.51cto.com/sd/ef353

MyBatis學習(6)