Mybatis(2)-本地缓存(一级缓存)的使用和原理

MOSFET高频响应实战:如何用LTspice仿真内部电容效应(附模型文件) 本文深入解析MOSFET高频响应中的内部电容效应,通过LTspice仿真工具详细展示如何提取模型参数并优化高频特性。从栅极相关电容到结电容的物理本质,再到实战案例中的开关损耗分析和频率响应扫描,提供全面的设计优化方法,帮助工程师有效应对高速开关电路中的电容挑战。 阅读详情

Mybatis-本地缓存(一级缓存)的使用和原理

①什么是Mybatis-本地缓存
Mybatis 使用到了两种缓存:本地缓存(local cache)和二级缓存(second level cache)。

每当一个新 session 被创建,MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询结果都会被保存在本地缓存中,所以,当再次执行参数相同的相同查询时,就不需要实际查询数据库了。本地缓存将会在做出修改、事务提交或回滚,以及关闭 session 时清空。

默认情况下,本地缓存数据的生命周期等同于整个 session 的周期。由于缓存会被用来解决循环引用问题和加快重复嵌套查询的速度,所以无法将其完全禁用。但是你可以通过设置 localCacheScope=STATEMENT 来只在语句执行时使用缓存。

以上引用自官网:https://mybatis.org/mybatis-3/zh/java-api.html

②如何使用Mybatis-本地缓存

mybatis本地缓存默认是开启的,具体对应 settings 配置下的 localCacheScope 属性,属性值默认为 **SESSION **

属性名描述可以设置的值默认值
localCacheScopeMyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。SESSION /STATEMENTSESSION
以上来自官方API: https://mybatis.org/mybatis-3/zh/configuration.html#settings
③测试本地缓存使用情况
package com.hs.mybatis;

import com.hs.mybatis.bean.Actor;
import com.hs.mybatis.mapper.ActorMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class CacheTest {
    public static void main(String[] args) {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session  = sqlSessionFactory.openSession();
        ActorMapper actorMapper = session.getMapper(ActorMapper.class);
        Actor actor = actorMapper.selectOneActor(1);
        System.out.println(actor);
        Actor actor2 = actorMapper.selectOneActor(1);
        System.out.println(actor2);
        session.close();

        SqlSession  session2 = sqlSessionFactory.openSession();
        ActorMapper actorMapper2 = session2.getMapper(ActorMapper.class);
        Actor actor3 = actorMapper2.selectOneActor(1);
        System.out.println(actor3);
        session2.close();
    }
}

以上结果中 actor 直接查询数据库(第一次查询),actor2 使用本地缓存中结果(在同一session会话周期内),actor3 查询数据库(上一个会话关闭,新开启了一个会话)

④Mybatis 本地缓存源码分析

1)获取 ActorMapper 代理对象

ActorMapper actorMapper = session.getMapper(ActorMapper.class);

交给org.apache.ibatis.binding.MapperProxyFactory 类创建,如下列出Mapper代理工厂类主要方法:


package org.apache.ibatis.binding;
public class MapperProxyFactory<T> {
    private final Class<T> mapperInterface;
    private final Map<Method, MapperMethodInvoker> methodCache = new ConcurrentHashMap();

    protected T newInstance(MapperProxy<T> mapperProxy) {
        return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
    }

    public T newInstance(SqlSession sqlSession) {
        MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
        return this.newInstance(mapperProxy);
    }
}

如上通过jdk动态代理方式创建 对应接口的实现类,MapperProxy 实现了InvocationHandler 接口

2)执行 ActorMapper selectOneActor 方法
实际执行入口即为 MapperProxy invoke 方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            return Object.class.equals(method.getDeclaringClass()) ? method.invoke(this, args) : this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession);
        } catch (Throwable var5) {
            throw ExceptionUtil.unwrapThrowable(var5);
        }
    }

invoke方法具体执行过程交给了 MapperProxy.DefaultMethodInvoker 处理,MapperProxy.DefaultMethodInvoker 类初始化过程如下:

private MapperProxy.MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
        try {
            MapperProxy.MapperMethodInvoker invoker = (MapperProxy.MapperMethodInvoker)this.methodCache.get(method);
            return invoker != null ? invoker : (MapperProxy.MapperMethodInvoker)this.methodCache.computeIfAbsent(method, (m) -> {
                if (m.isDefault()) {
                    try {
                        return privateLookupInMethod == null ? new MapperProxy.DefaultMethodInvoker(this.getMethodHandleJava8(method)) : new MapperProxy.DefaultMethodInvoker(this.getMethodHandleJava9(method));
                    } catch (InstantiationException | InvocationTargetException | NoSuchMethodException | IllegalAccessException var4) {
                        throw new RuntimeException(var4);
                    }
                } else {
                    return new MapperProxy.PlainMethodInvoker(new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration()));
                }
            });
        } catch (RuntimeException var4) {
            Throwable cause = var4.getCause();
            throw (Throwable)(cause == null ? var4 : cause);
        }
    }

真正执行 invoke 的操作为 org.apache.ibatis.binding.MapperProxy.PlainMethodInvoker 类的 invoke 方法

public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
            return this.mapperMethod.execute(sqlSession, args);
        }

继续定位:org.apache.ibatis.binding.MapperMethod execute 方法

public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        Object param;
        switch(this.command.getType()) {
        case INSERT:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
            break;
        case UPDATE:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
            break;
        case DELETE:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
            break;
        case SELECT:
            if (this.method.returnsVoid() && this.method.hasResultHandler()) {
                this.executeWithResultHandler(sqlSession, args);
                result = null;
            } else if (this.method.returnsMany()) {
                result = this.executeForMany(sqlSession, args);
            } else if (this.method.returnsMap()) {
                result = this.executeForMap(sqlSession, args);
            } else if (this.method.returnsCursor()) {
                result = this.executeForCursor(sqlSession, args);
            } else {
                param = this.method.convertArgsToSqlCommandParam(args);
                result = sqlSession.selectOne(this.command.getName(), param);
                if (this.method.returnsOptional() && (result == null || !this.method.getReturnType().equals(result.getClass()))) {
                    result = Optional.ofNullable(result);
                }
            }
            break;
        case FLUSH:
            result = sqlSession.flushStatements();
            break;
        default:
            throw new BindingException("Unknown execution method for: " + this.command.getName());
        }

        if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
            throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
        } else {
            return result;
        }
    }

可知 执行上述查询操作时调用的是 DefaultSqlSession 类 selectOne 方法,selectOne 方法内部调用 selectList 方法

public <T> T selectOne(String statement, Object parameter) {
        List<T> list = this.selectList(statement, parameter);
        if (list.size() == 1) {
            return list.get(0);
        } else if (list.size() > 1) {
            throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
        } else {
            return null;
        }
    }
public <E> List<E> selectList(String statement, Object parameter) {
        return this.selectList(statement, parameter, RowBounds.DEFAULT);
    }

    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
        List var5;
        try {
            MappedStatement ms = this.configuration.getMappedStatement(statement);
            var5 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
        } catch (Exception var9) {
            throw ExceptionFactory.wrapException("Error querying database.  Cause: " + var9, var9);
        } finally {
            ErrorContext.instance().reset();
        }

        return var5;
    }

3)数据查询以及缓存
上述代码执行完成后开始调用 org.apache.ibatis.executor.CachingExecutor query 方法,

public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
        BoundSql boundSql = ms.getBoundSql(parameterObject);
        //根据方法及参数等参数生成 cacheKey,保存数据到缓存时使用的就是这个key
        CacheKey key = this.createCacheKey(ms, parameterObject, rowBounds, boundSql);
        return this.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }

继续调用如下方法,在下面方法中 Cache cache = ms.getCache(); 取得是二级缓存,本例中没有配置,所以为null

public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        Cache cache = ms.getCache();
        if (cache != null) {
            this.flushCacheIfRequired(ms);
            if (ms.isUseCache() && resultHandler == null) {
                this.ensureNoOutParams(ms, boundSql);
                List<E> list = (List)this.tcm.getObject(cache, key);
                if (list == null) {
                    list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                    this.tcm.putObject(cache, key, list);
                }

                return list;
            }
        }

        return this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }

继续定位 this.delegate.query方法,此处 delegate 即为 SimpleExecutor ,SimpleExecutor继承自 BaseExecutor,query为其父类BaseExecutor的方法

BaseExecutor query 方法

public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
        if (this.closed) {
            throw new ExecutorException("Executor was closed.");
        } else {
            if (this.queryStack == 0 && ms.isFlushCacheRequired()) {
                this.clearLocalCache();
            }

            List list;
            try {
                ++this.queryStack;
                //首先从 localCache 本地缓存中取数据
                list = resultHandler == null ? (List)this.localCache.getObject(key) : null;
                if (list != null) {
                    this.handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
                } else {
                    //没有值的时候直接查数据库
                    list = this.queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
                }
            } finally {
                --this.queryStack;
            }

            if (this.queryStack == 0) {
                Iterator var8 = this.deferredLoads.iterator();

                while(var8.hasNext()) {
                    BaseExecutor.DeferredLoad deferredLoad = (BaseExecutor.DeferredLoad)var8.next();
                    deferredLoad.load();
                }

                this.deferredLoads.clear();
                //localCacheScope 配置为 STATEMENT 时清除本地缓存
                if (this.configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
                    this.clearLocalCache();
                }
            }

            return list;
        }
    }

BaseExecutor queryFromDatabase 方法

private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
       //往缓存中存入默认值
        this.localCache.putObject(key, ExecutionPlaceholder.EXECUTION_PLACEHOLDER);

        List list;
        try {
            //从数据库查询数据
            list = this.doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
        } finally {
            //移除缓存中的默认值
            this.localCache.removeObject(key);
        }
        //将查询到的结果存入缓存
        this.localCache.putObject(key, list);
        if (ms.getStatementType() == StatementType.CALLABLE) {
            this.localOutputParameterCache.putObject(key, parameter);
        }

        return list;
    }

以上是Mybatis 本地缓存 存取过程的简单理解,通过 如下代码块可以很清楚的知道为什么localCacheScope 配置了 STATEMENT 值后mybatis不会使用本地缓存,因为,这里判断localCacheScope 属性值为STATEMENT 后清除了本地缓存

 if (this.configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
                    this.clearLocalCache();
                }

同理,为何 session.close 方法执行完后本地缓存也失效了,原因也是close方法内部调用了clearLocalCache方法
org.apache.ibatis.executor.BaseExecutor close 方法:

public void close(boolean forceRollback) {
        try {
            try {
                this.rollback(forceRollback);
            } finally {
                if (this.transaction != null) {
                    this.transaction.close();
                }

            }
        } catch (SQLException var11) {
            log.warn("Unexpected exception on closing transaction.  Cause: " + var11);
        } finally {
            this.transaction = null;
            this.deferredLoads = null;
            this.localCache = null;
            this.localOutputParameterCache = null;
            this.closed = true;
        }

    }

org.apache.ibatis.executor.BaseExecutor rollback 方法:

public void rollback(boolean required) throws SQLException {
        if (!this.closed) {
            try {
                //清除本地缓存
                this.clearLocalCache();
                this.flushStatements(true);
            } finally {
                if (required) {
                    this.transaction.rollback();
                }

            }
        }

    }
⑤ Mybatis 本地缓存本质

Mybatis 本地缓存类为 org.apache.ibatis.cache.impl.PerpetualCache,具体如下,内部使用HashMap保存数据

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.ibatis.cache.impl;

import java.util.HashMap;
import java.util.Map;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheException;

public class PerpetualCache implements Cache {
    private final String id;
    private final Map<Object, Object> cache = new HashMap();

    public PerpetualCache(String id) {
        this.id = id;
    }

    public String getId() {
        return this.id;
    }

    public int getSize() {
        return this.cache.size();
    }

    public void putObject(Object key, Object value) {
        this.cache.put(key, value);
    }

    public Object getObject(Object key) {
        return this.cache.get(key);
    }

    public Object removeObject(Object key) {
        return this.cache.remove(key);
    }

    public void clear() {
        this.cache.clear();
    }

    public boolean equals(Object o) {
        if (this.getId() == null) {
            throw new CacheException("Cache instances require an ID.");
        } else if (this == o) {
            return true;
        } else if (!(o instanceof Cache)) {
            return false;
        } else {
            Cache otherCache = (Cache)o;
            return this.getId().equals(otherCache.getId());
        }
    }

    public int hashCode() {
        if (this.getId() == null) {
            throw new CacheException("Cache instances require an ID.");
        } else {
            return this.getId().hashCode();
        }
    }
}

本地缓存在初始化 Executor时创建

protected BaseExecutor(Configuration configuration, Transaction transaction) {
        this.transaction = transaction;
        this.deferredLoads = new ConcurrentLinkedQueue();
        this.localCache = new PerpetualCache("LocalCache");
        this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
        this.closed = false;
        this.configuration = configuration;
        this.wrapper = this;
    }
海康威视VS互联网大厂:薪资、福利、工作强度全方位对比 本文全面对比了海康威视与互联网大厂在薪资、福利和工作强度等方面的差异。海康威视提供稳定的薪资结构和较低的工作强度,适合追求专业深度的职场人;而互联网大厂则以高薪和快速成长吸引人才,但工作压力较大。文章还分析了职业发展路径和长期价值,帮助求职者做出明智选择。 阅读详情

相关推荐

【同花顺公式编辑教程】第3章 获取数据

学习同花顺公式编辑器,其提供的数据有量价数据以及财务数据。在本章中,我们讲解了编辑器执行代码的原理,并给出了可调用数据的汇总表。

LiaoYi2016218的博客 1万+

mybatis 源码分析(四) 自带连接池-

mybatis 源码分析(四) 自带连接池 mybatis 源码分析(一) Xml解析,容器初始化 mybatis 源码分析(二) sql执行路径分析 mybatis 源码分析(三) 插件原理 mybatis 源码分析(四) 自带连接池 mybatis 连接池 mybatis 自带3种连接池 1) jndi 无 2) pooled 连接池实现 ...

java_magicsun的专栏 1683

新华DCS系统仿真测试方法详细介绍

新华DCS ICAN3.1系统是应用广泛并且功能非常强大的国产DCS系统。具有管理虚拟CPU并仿真运行的功能。并且上位机画面可以与虚拟DPU数据实时同步仿真。具体仿真方法如下所示: 1、 需要设备及软件: 2、步骤如下: 2.1硬件步骤: 1)电脑开机。 2)交换机连接电脑网卡。 3)交换机上电运行。 2.2软件步骤: 1)设置电脑IP 一般配置IP为A网工程站IP。 222.222.221.201/255.255.255.0 2)建立虚拟DPU 登录 D:\iCAN\Program\Vxcu 文件夹。

lw_waston的博客 6896

Mybatis源码解读

一:先看下面一个简单的mybatis的程序 package com.hanwei; import org.junit.Before; import com.hanwei.dao.Istudent; import com.hanwei.dao.impl.IstudentImpl; import com.hanwei.pojo.Student; public class Test

哦绝影 588

保姆级教程:用STM32CubeMX给STM32F407配置RTC秒中断,并解决掉电时间丢失问题

本文详细介绍了如何使用STM32CubeMX为STM32F407配置RTC秒中断,并解决掉电时间丢失问题。通过硬件原理与软件配置的双视角解析,帮助开发者实现精确计时与时间持久化,适用于物联网设备和工业控制器等场景。

weixin_42519733的博客 137

USB2.0学习1--基本概念

USB全称是 Universal Serial Bus,即通用串行总线,是一种计算机与外围设备进行数据交互的串行通信标准。USB协议是在1994年底由英特尔、IBM、Microsoft等公司联合提出的,现由USB协会(USB-IF)管理。USB使用差分信号来传输数据,具有传输速度快、支持热插拔、连接灵活、独立供电、协议向下兼容等优点,目前应用十分广泛。

原海青木的博客 3762

Mybatis介绍之缓存

Mybatis介绍之缓存

记事本 4342

H3C设备VRF配置实战:5步搞定多业务网络隔离(附排错技巧)

本文详细介绍了在H3C设备上配置VRF(虚拟路由转发)实现多业务网络隔离的实战方法。通过五步配置流程,从创建VPN-instance、绑定接口到配置独立路由表,帮助网络工程师在单台设备上构建逻辑隔离的企业级网络,并分享了高级路由配置与常见排错技巧。

gold8的专栏 938

一文彻底读懂优秀开源产品MyBatis一级缓存设计!

- 前言 -缓存是 MyBatis 中非常重要的特性。合理使用缓存能够减少数据库 IO,显著提升系统性能。但是在分布式环境下,如果使用不当,则可能会带来数据一致性问题。M...

musicml的博客 299

使用 Simulink 搭建一个地震信号反射系数反演与滤波联合仿真的系统模型

《Simulink地震信号处理仿真指南》摘要:本文详细介绍了使用Simulink进行地震信号反射系数反演与滤波联合仿真的完整流程。从创建模型、生成含噪合成地震记录(包含子波卷积与随机反射系数),到设计滤波模块(带通/小波/自适应滤波)和实现反演算法(Wiener-Hopf方程/RLS方法),最后通过可视化模块分析结果。教程涵盖理论准备、7个实施步骤、优化建议及实际应用场景,为地震勘探、地质调查等领域提供标准化的信号处理仿真方案,特别适合需要掌握地震信号反演与实时滤波技术的工程人员学习。

amy_mhd的博客 114

LVGL 蜂巢气泡菜单(Hex Menu)

h。

摸鱼专家 177

一文搞懂MyBatis的一级缓存和二级缓存

在本篇文章中,将结合示例与源码,对MyBatis中的一级缓存和二级缓存进行说明。MyBatis3.5.6关于MyBatis的一级缓存,总结如下。MyBatis的一级缓存默认开启,且默认作用范围为SESSION,即一级缓存在一个会话中生效,也可以通过配置将作用范围设置为STATEMENT,让一级缓存仅针对当前执行的SQL语句生效;在同一个会话中,执行增删改操作会使本会话中的一级缓存失效;不同会话持有不同的一级缓存,本会话内的操作不会影响其它会话内的一级缓存。关于MyBatis的二级缓存,总结如下。

2301_76607156的博客 2915

从源码编译CesiumForUnreal

从源码编译CesiumForUnreal插件

专注GIS开发 5644

Mybatis一级缓存和二级缓存

缓存可以将数据保存在内存中,是互联网系统常常用到的。目前流行的缓存服务器有 MongoDB、Redis、Ehcache 等。缓存是在计算机内存上保存的数据,读取时无需再从磁盘读入,因此具备快速读取和使用的特点。和大多数持久化框架一样,MyBatis 提供了一级缓存和二级缓存的支持。默认情况下,MyBatis 只开启一级缓存。mybatis的的一级缓存是SqlSession级别的缓存,一级缓存缓存的是对象,当SqlSession提交、关闭以及其他的更新数据库的操作发生后,一级缓存就会清空。

qq_53123736的博客 6897

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

MyBatis 的一级缓存和二级缓存

文章目录一、前言二、一级缓存三、二级缓存3.1、开启二级缓存:四、测试一下五、总结: 一、前言 先说缓存,合理使用缓存是优化中最常见的,将从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询,而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能。 二、一级缓存 一级缓存 是 SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有...

猎人在吃肉 7776

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

MyBatis 一级缓存原理

值去本地缓存中查找,如果在缓存中,就直接从缓存中取出,然后返回给用户;执行结果:我们可以看到,只有第一次真正查询了数据库,后续的查询使用了一级缓存。的学生的名字还是小明,出现了重复读,说明一级缓存只在数据库会话内部共享。中更新数据库,验证一级缓存只在数据库会话内部共享。通过上面的使用,能够清楚的发现,一级缓存主要是基于。会话中执行的所有语句,都会共享这一个缓存。的一级缓存进行可重复读,就需要进行一级缓存清除。,对于每一次查询,都会尝试根据执行的语句生成的。中查询数据,使一级缓存生效,在。

程序猿进阶 1960

Mybatis一级缓存和二级缓存原理区别(图文详解)

Java面试经常问到Mybatis一级缓存和二级缓存,今天就给大家重点详解Mybatis一级缓存和二级缓存原理与区别@mikechen

mikechen的互联网架构 1万+

mybatis缓存详解,一级缓存和二级缓存举例讲解

mybatis缓存详解,一级缓存和二级缓存举例讲解

相关项目可以查看https://gitee.com/fan-pl或https://github.com/fpl1116 2279

理解Mybatis一级缓存,以及如何真正使用到一级缓存

阅读这篇文章,你将会了解 1.什么是会话(SqlSession)、执行器(Executor) 2.什么是Mybatis一级缓存 3.一级缓存的生命周期 4.一级缓存的CacheKey生成策略 5.在日常开发时,怎么才能用到一级缓存(通过事务) 一.类关系图: 二.什么是会话(SqlSession) 在Mybatis中,SqlSession可以理解为数据库访问的最小粒度,每次的数据库访问,...

Java程序员的进阶之路 4965

MyBatis的一级缓存和二级缓存

在首次访问时,查询数据库,将查询的数据库信息存入内存中;再次访问时可直接访问缓存,以减少IO、硬盘读写次数、提高效率。

Bbbcccccc的博客 2920

MyBatis中的一级缓存和二级缓存介绍

先说缓存,合理使用缓存是优化中最常见的,将从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询,而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能。 一级缓存 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构用于存储缓存数据。不同的sqlSession之间的缓存数据区域是互相不影响的。也

Java知音 1万+

MyBatis一级缓存和二级缓存详解

在Java持久层框架中,MyBatis因其灵活性和易用性而备受开发者青睐。作为一款优秀的ORM框架,MyBatis不仅提供了强大的SQL映射功能,还内置了完善的缓存机制,以提高应用程序的性能和响应速度。本文将深入探讨MyBatis的一级缓存和二级缓存,从原理、配置到实际应用场景,帮助开发者更好地理解和使用MyBatis缓存,优化应用性能。缓存是提高系统性能的重要手段,通过减少数据库访问次数,可以显著降低系统响应时间,提高并发处理能力。

weixin_56018532的博客 1257

MyBatis一级缓存和二级缓存

根据缓存存放位置,缓存可以分为本地缓存和分布式缓存。根据缓存作用范围,缓存可以分为永久缓存和临时缓存。在 MyBatis 中,根据作用范围,分别有一级缓存和二级缓存两种类型。

weixin_58724261的博客 1万+

Mybatis中一级缓存和二级缓存使用详解

一级缓存是SqlSession级别的缓存。 在操作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。 不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。 一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),

小小默:进无止境 5957

Mybatis 一级缓存和二级缓存的使用

目录Mybatis缓存一级缓存二级缓存缓存原理 Mybatis缓存 官方文档:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制 Mybatis中默认定义了两级缓存:一级缓存和二级缓存 默认情况下,只启用了一级缓存(sqlSession级别的缓存),它仅仅对一个会话中的数据进行缓存。 二级缓存需要手动开启和配置,它是基于 namespace级别的缓存 为了提高扩展性,M

weixin_44953227的博客 2万+

Mybatis 一级缓存和二级缓存

Mybatis 一. 前言 MyBatis是一个简单,小巧但功能非常强大的ORM开源框架,它的功能强大也体现在它的缓存机制上。MyBatis提供了一级缓存、二级缓存 这两个缓存机制,能够很好地处理和维护缓存,以提高系统的性能。本文的目的则是向读者详细介绍MyBatis的一级缓存,深入源码,解析MyBatis一级缓存的实现原理,并且针对一级缓存的特点提出了在实际使用过程中应该注意的事项。 一级缓存 Mybatis的一级缓存是指SQLSession,一级缓存的作用域是SQlSession, Mabits默认开启

DY. 2509
上一篇: Mybatis(1)-入门使用
下一篇: JavaSE-多线程(1)- 线程概念
sql2008help
博客等级 码龄11年 80粉丝 145原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值