Mybatis從入門到精通——二級緩存和一級緩存(16)

一、一級緩存和二級緩存

程序中緩存對系統效率的提升是極大的,在Mybatis中,緩存分別爲一級緩存和二級緩存,其中一級緩存是默認開啓的,二級緩存需要手動開啓。

 

二、一級緩存

說明:

1.Mybatis的一級緩存是默認開啓的。

2.若要停止Mybatis的一級緩存可以通過設置select標籤上的flushCache屬性爲true,會每一次執行完查詢就情況一級緩存。

3.一級緩存的生命週期是一個SqlSession,不能跨SqlSession域

4.該SqlSession下的任何增、刪、改操作都會清空一級緩存

案例

mapepr映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.my.mapper.UserMapper">

  <resultMap id="BaseResultMap" type="com.my.entity.User">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="user_name" jdbcType="VARCHAR" property="userName" />
    <result column="real_name" jdbcType="VARCHAR" property="realName" />
    <result column="sex" jdbcType="CHAR" property="sex" />
    <result column="mobile" jdbcType="VARCHAR" property="mobile" />
    <result column="email" jdbcType="VARCHAR" property="email" />
    <result column="note" jdbcType="VARCHAR" property="note" />
    <result column="position_id" jdbcType="INTEGER" property="positionId" />
  </resultMap>

  <sql id="Base_Column_List">
    id, user_name, real_name, sex, mobile, email, note, position_id
  </sql>

  <!-- flushCache設置爲true則爲關閉一級緩存 -->
  <select id="selectById" parameterType="java.lang.Integer" resultMap="BaseResultMap" flushCache="false">
    select
    <include refid="Base_Column_List" />
    from user
    where id = #{id,jdbcType=INTEGER}
  </select>

  <update id="updateByUserSelective" parameterType="com.my.entity.User">
    update user
    <set>
      <if test="userName != null">
        user_name = #{userName,jdbcType=VARCHAR},
      </if>
      <if test="realName != null">
        real_name = #{realName,jdbcType=VARCHAR},
      </if>
      <if test="sex != null">
        sex = #{sex,jdbcType=CHAR},
      </if>
      <if test="mobile != null">
        mobile = #{mobile,jdbcType=VARCHAR},
      </if>
      <if test="email != null">
        email = #{email,jdbcType=VARCHAR},
      </if>
      <if test="note != null">
        note = #{note,jdbcType=VARCHAR},
      </if>
      <if test="positionId != null">
        position_id = #{positionId,jdbcType=INTEGER},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  
</mapper>

測試代碼:

public class MybatisTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws IOException {
        String resource = "mybatis-config.xml";
        //1.使用mybatis的工具讀取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //2.創建sqlSessionFactory
        sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        inputStream.close();
    }

    /**
     * 測試一級緩存,需要通過查看日誌的SQL打印判斷是否緩存
     */
    @Test
    public void testOneCache() {
        //自動提交
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.selectById(1);
        //再次查詢
        user = userMapper.selectById(1);
        user.setNote("test");
        //更新
        userMapper.updateByUserSelective(user);
        //再次查詢
        user = userMapper.selectById(1);
        System.out.println(user);
        sqlSession.close();
    }

    /**
     * 測試一級緩存跨Session,需要通過查看日誌的SQL打印判斷是否緩存
     */
    @Test
    public void testOneCacheSession() {
        //自動提交
        SqlSession sqlSession = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        User user = userMapper.selectById(1);
        User user2 = userMapper2.selectById(1);
        sqlSession.close();
        sqlSession2.close();
    }


}

說明:緩存效果不能通過代碼直接看到,需要自己debug查看打印日誌進行觀察。

 

三、二級緩存

說明:

1.二級緩存默認是不使用的,需要手動添加。

2.二級緩存需要把Mybatis配置文件中的cacheEnabled設爲true(默認是true,但設置後更直觀)。

3.開啓二級緩存後還需要去mapper.xml文件中通過使用cache或cache-ref開啓二級緩存的使用。

4.二級緩存的生命週期是一個SqlSessionFactory(一般一個項目中只用一個)。

5.二級緩存是跨SqlSession的,但是並不跨命名空間(每個mapper.xml)。

6.同一個命名空間下的任意SqlSession的增、刪、改操作都會清空二級緩存。

cache和cache-ref標籤介紹:

cache標籤用在mapper.xml文件中,開啓該命名空間的二級緩存,和cache-ref標籤衝突,常用三個屬性:

    1.eviction:緩存策略,一般用FIFO

    2.flushInterval:多久清空一次,單位秒

    3.size:緩存列表數量

cache-ref標籤用在mapper.xml文件中,和其它命名空間共用一個緩存,和cache標籤衝突,只有一個屬性:

    1.namespace:需要其共用緩存的命名空間(該值的命名空間需要開啓二級緩存)

案例:

mapper映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.my.mapper.PositionMapper">

  <!-- 開啓二級緩存,使用默認配置 -->
  <cache> </cache>

<!-- 和其它命名空間共用一個緩存 -->
<!--  <cache-ref namespace="命名空間"/>-->
  
  <resultMap id="BaseResultMap" type="com.my.entity.Position">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="posname" jdbcType="VARCHAR" property="posname" />
    <result column="note" jdbcType="VARCHAR" property="note" />
  </resultMap>
  
  <sql id="Base_Column_List">
    id, posname, note
  </sql>
  
  <select id="selectById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from position
    where id = #{id,jdbcType=INTEGER}
  </select>

  <update id="updateByPositionSelective" parameterType="com.my.entity.Position">
    update position
    <set>
      <if test="posname != null">
        posname = #{posname,jdbcType=VARCHAR},
      </if>
      <if test="note != null">
        note = #{note,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

測試代碼:

public class MybatisTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws IOException {
        String resource = "mybatis-config.xml";
        //1.使用mybatis的工具讀取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //2.創建sqlSessionFactory
        sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        inputStream.close();
    }


    /**
     * 測試二級緩存,需要通過查看日誌的SQL打印判斷是否緩存
     */
    @Test
    public void testTowCache() {
        //自動提交
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
        PositionMapper positionMapper = sqlSession.getMapper(PositionMapper.class);
        PositionMapper positionMapper2 = sqlSession2.getMapper(PositionMapper.class);
        Position position = positionMapper.selectById(1);
        //再次查詢
        position = positionMapper.selectById(1);
        position.setNote("test");
        //更新
        positionMapper.updateByPositionSelective(position);
        //再次查詢
        position = positionMapper.selectById(1);
        System.out.println(position);
        sqlSession.close();
    }

}

說明:緩存效果不能通過代碼直接看到,需要自己debug查看打印日誌進行觀察。

 

四、補充說明

1.緩存之間執行的順序,二級緩存—一級緩存—數據庫

2.一般不用二級緩存,因爲二級緩存可能會造成髒讀,例如A命名空間開啓了二級緩存,當B命名空間對A命名空間中的表進行修改時,A命名空間的緩存是無法知曉的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章