前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MyBatis 缓存

MyBatis 缓存

原创
作者头像
mySoul
发布2019-04-19 20:04:59
6390
发布2019-04-19 20:04:59
举报
文章被收录于专栏:mySoul

一级缓存

对于一级缓存来说,Mybatis是直接单个线程隔离的

在执行add,update,delete 的时候,会自动清空缓存,避免脏读造成的影响

此时mapper为线程隔离的,而管理对象为所有线程所共享的.

修改展示层

代码语言:txt
复制
<%@ 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>

查看日志

代码语言:txt
复制
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即可

代码语言:txt
复制
<?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接口

代码语言:txt
复制
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直接操作即可

额...暂时先不连接

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一级缓存
  • 二级缓存
  • 自定义缓存
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档