MyBatis 緩存

一級緩存

對於一級緩存來說,Mybatis是直接單個線程隔離的
在執行add,update,delete 的時候,會自動清空緩存,避免髒讀造成的影響
此時mapper爲線程隔離的,而管理對象爲所有線程所共享的.

修改展示層

<%@ page import="org.apache.ibatis.session.SqlSession" %>
<%@ page import="com.ming.Util.SqlSessionFactoryUtil" %>
<%@ page import="com.ming.MyBatis.RoleMapper" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="com.ming.MyBatis.POJO.Student" %>
<html>
<body>
<h2>Hello World!</h2>

<%
    long startTime = System.currentTimeMillis(); //獲取開始時間
    SqlSession sqlSession = null;
    List<Student> students = null;
    List<Student> students1 = null;
        try {
            sqlSession = SqlSessionFactoryUtil.openSqlSesion();
            RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
            students = roleMapper.getStudent(1);
            students1 = roleMapper.getStudent(1);
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
    }
    long endTime = System.currentTimeMillis(); //獲取結束時間

%>

<%
    Iterator iterator = students.iterator();
    while(iterator.hasNext()){
        %>
            <%=((Student)iterator.next()).getGender()%>

        <%
    }
    iterator = students1.iterator();
    while(iterator.hasNext()){
        %>
            <%=((Student)iterator.next()).getGender()%>
        <%
    }
%>
</body>
</html>

查看日誌

2019-04-17 22:33:38.147 [DEBUG] org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:136) - Opening JDBC Connection
2019-04-17 22:33:38.147 [DEBUG] org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:397) - Checked out connection 879027360 from pool.
2019-04-17 22:33:38.148 [DEBUG] org.apache.ibatis.transaction.jdbc.JdbcTransaction.setDesiredAutoCommit(JdbcTransaction.java:100) - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3464e4a0]
2019-04-17 22:33:38.161 [DEBUG] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143) - ==>  Preparing: SELECT student.uid, student.gender, student.remarks, student.student_id_number, student.student_name FROM student WHERE student.uid = 1; 
2019-04-17 22:33:38.162 [DEBUG] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143) - ==> Parameters: 
2019-04-17 22:33:38.181 [DEBUG] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143) - <==      Total: 1
2019-04-17 22:33:38.183 [DEBUG] org.apache.ibatis.transaction.jdbc.JdbcTransaction.resetAutoCommit(JdbcTransaction.java:122) - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3464e4a0]
2019-04-17 22:33:38.200 [DEBUG] org.apache.ibatis.transaction.jdbc.JdbcTransaction.close(JdbcTransaction.java:90) - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3464e4a0]
2019-04-17 22:33:38.201 [DEBUG] org.apache.ibatis.datasource.pooled.PooledDataSource.pushConnection(PooledDataSource.java:362) - Returned connection 879027360 to pool.

可以看到只查詢了一次

需要注意的是緩存在各個SqlSession是相互隔離的

二級緩存

二級緩存直接添加cache即可

<?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.ming.MyBatis.RoleMapper">
    
    <resultMap type="role" id="roleMap">
        <!-- id爲主鍵映射關係 其中數據庫中的id爲主鍵 -->
        <id column="id" property="id" javaType="int" jdbcType="INTEGER"/>
        <!-- result爲其他基本數據類型和實體類之間的映射 映射關係爲role_name 到 roleName之間的映射 數據類型爲string到VARCHAR之間的映射關係 -->
        <result column="role_name" property="roleName" javaType="string" jdbcType="VARCHAR"/>
        <!-- 這裏使用typeHandler表示遇到此處理集的時候,將會執行com.ming.MyBatis.StringTypeHandler -->
        <result column="note" property="note" typeHandler="com.ming.MyBatis.StringTypeHandler"/>
    </resultMap>
    
    <select id="getRole" parameterType="int" resultType="com.ming.MyBatis.POJO.Role">
        SELECT id, role_name as roleName, note FROM t_role WHERE id = #{id}
    </select>
    
    <select id="findRoleByteMap" parameterType="map" resultMap="roleMap">
        SELECT id, role_name, note FROM t_role
        WHERE role_name LIKE CONCAT('%', #{roleName}, '%')
        AND note LIKE CONCAT('%', #{note}, '%')
    </select>
    
    <select id="findRoleByteMap1" resultMap="roleMap">
        SELECT id, role_name, note FROM t_role
        WHERE role_name LIKE CONCAT('%', #{roleName}, '%')
        AND note LIKE CONCAT('%', #{note}, '%')
    </select>
    
    
    <resultMap id="studentSelfCardMap" type="com.ming.MyBatis.POJO.StudentCard">
        <id column="uid" property="uid"/>
        <result column="student_number" property="studentNumber"/>
        <result column="birthplace" property="birthplace" />
        <result column="date_of_issue" property="dateOfIssue" jdbcType="DATE" javaType="java.util.Date"/>
        <result column="end_date" property="endDate" jdbcType="DATE" javaType="java.util.Date"/>
        <result column="remarks" property="remarks" />
    </resultMap>

    <select id="findStudentSelfCardByStudentId" parameterType="int" resultMap="studentSelfCardMap">
        SELECT student_card.uid, student_card.student_number, student_card.remarks,
        student_card.end_date, student_card.date_of_issue, student_card.birthplace
        FROM student_card WHERE student_card.uid = #{studentId};
    </select>
    
    <resultMap id="studentMap" type="com.ming.MyBatis.POJO.Student">
        <id column="uid" property="uid"/>
        <result column="student_name" property="studentName"/>
        <result column="gender" property="gender"/>
        <result column="student_id_number" property="studentIdNumber"/>
        <result column="remarks" property="remarks"/>
        <!--將會調用接口代表的SQL 進行執行查詢 -->
        <association property="studentCard" column="uid" select="com.ming.MyBatis.RoleMapper.findStudentSelfCardByStudentId"/>
    </resultMap>
    
    <select id="getStudent" parameterType="int" resultMap="studentMap">
        SELECT student.uid, student.gender, student.remarks, student.student_id_number,
        student.student_name
        FROM student
        WHERE student.uid = 1;
    </select>
    
    <cache/>
</mapper>

此時select語句將會緩存
insert update delete 將會刷新緩存
會使用LRU算法進行回收
根據時間表 緩存不會用任何時間順序來刷新緩存
緩存會存儲列表集合或對象 1024個引用

由於對象需要序列化所以需要實現 java.io.Serializable接口

父類實現序列化 子類會自動實現序列化 若子類實現序列化 父類沒有實現序列化 此時在子類中保存父類的值,直接跳過

2019-04-18 00:55:44.428 [DEBUG] org.apache.ibatis.cache.decorators.LoggingCache.getObject(LoggingCache.java:62) - Cache Hit Ratio [com.ming.MyBatis.RoleMapper]: 0.7586206896551724
2019-04-18 00:55:44.430 [DEBUG] org.apache.ibatis.cache.decorators.LoggingCache.getObject(LoggingCache.java:62) - Cache Hit Ratio [com.ming.MyBatis.RoleMapper]: 0.7666666666666667
2019-04-18 00:55:44.433 [DEBUG] org.apache.ibatis.cache.decorators.LoggingCache.getObject(LoggingCache.java:62) - Cache Hit Ratio [com.ming.MyBatis.RoleMapper]: 0.7741935483870968
2019-04-18 00:55:44.435 [DEBUG] org.apache.ibatis.cache.decorators.LoggingCache.getObject(LoggingCache.java:62) - Cache Hit Ratio [com.ming.MyBatis.RoleMapper]: 0.78125

查看日誌,可以發現再次讀取的時候,直接從緩存中獲取了.
緩存生效,併爲執行sql語句

已經命中緩存

自定義緩存

這個需要實現cache接口

package com.ming.MyBatis;

import java.util.concurrent.locks.ReadWriteLock;

/**
 * @author ming
 */
public class Cache implements org.apache.ibatis.cache.Cache {
    /**
     * @return The identifier of this cache
     */
    @Override
    public String getId() {
        return null;
    }

    /**
     * @param key   Can be any object but usually it is a {@link CacheKey}
     * @param value The result of a select.
     */
    @Override
    public void putObject(Object key, Object value) {

    }

    /**
     * @param key The key
     * @return The object stored in the cache.
     */
    @Override
    public Object getObject(Object key) {
        return null;
    }

    /**
     * As of 3.3.0 this method is only called during a rollback
     * for any previous value that was missing in the cache.
     * This lets any blocking cache to release the lock that
     * may have previously put on the key.
     * A blocking cache puts a lock when a value is null
     * and releases it when the value is back again.
     * This way other threads will wait for the value to be
     * available instead of hitting the database.
     *
     * @param key The key
     * @return Not used
     */
    @Override
    public Object removeObject(Object key) {
        return null;
    }

    /**
     * Clears this cache instance.
     */
    @Override
    public void clear() {

    }

    /**
     * Optional. This method is not called by the core.
     *
     * @return The number of elements stored in the cache (not its capacity).
     */
    @Override
    public int getSize() {
        return 0;
    }

    /**
     * Optional. As of 3.2.6 this method is no longer called by the core.
     * <p>
     * Any locking needed by the cache must be provided internally by the cache provider.
     *
     * @return A ReadWriteLock
     */
    @Override
    public ReadWriteLock getReadWriteLock() {
        return null;
    }
}

然後redis直接操作即可

額...暫時先不連接

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