Mybatis 缓存

news/2024/10/23 5:30:44/

JPA 原理

事务

事务是计算机应用中不可或缺的组件模型,它保证了用户操作的原子性 ( Atomicity )、一致性

( Consistency )、隔离性 ( Isolation ) 和持久性 ( Durabilily )

本地事务

紧密依赖于底层资源管理器(例如数据库连接 ),事务处理局限在当前事务资源内。此种事务处理方式不存在对应用服务器的依赖,因而部

署灵活却无法支持多数据源的分布式事务。在数据库连接中使用本地事务示例如下:

分布式事务

public void transferAccount() {

Connection conn = null; Statement stmt = null;

try{

conn = getDataSource().getConnection();

// 将自动提交设置为 false,若设置为 true 则数据库将会把每一次数据更新认定为一个事务并自动提交

conn.setAutoCommit(false); stmt = conn.createStatement();

// A 账户中的金额减少 500

stmt.execute("update t_account set amount = amount - 500 where account_id = 'A'");

// B 账户中的金额增加 500

stmt.execute("update t_account set amount = amount + 500 where account_id = 'B'");

// 提交事务

conn.commit();

// 事务提交:转账的两步操作同时成功

} catch(SQLException sqle){

// 发生异常,回滚在本事务中的操做

conn.rollback();

// 事务回滚:转账的两步操作完全撤销

stmt.close(); conn.close();

}

}Java 事务编程接口(JTAJava Transaction API)和 Java 事务服务 (JTSJava Transaction Service)  J2EE 平台提供了分布式事务服务。分

布式事务(Distributed Transaction)包括事务管理器(Transaction Manager)和一个或多个支持 XA 协议的资源管理器 ( Resource

Manager )。我们可以将资源管理器看做任意类型的持久化数据存储;事务管理器承担着所有事务参与单元的协调与控制。

两阶段提交

两阶段提交主要保证了分布式事务的原子性:即所有结点要么全做要么全不做,所谓的两个阶段是指:第一阶段:准备阶段;第二阶段:提

交阶段。

1准备阶段

事务协调者(事务管理器)给每个参与者(资源管理器)发送 Prepare 消息,每个参与者要么直接返回失败(如权限验证失败),要么在本地执行事

务,写本地的 redo  undo 日志,但不提交,到达一种万事俱备,只欠东风的状态。

2提交阶段:

如果协调者收到了参与者的失败消息或者超时,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据协

调者的指令执行提交或者回滚操作,释放所有事务处理过程中使用的锁资源。(注意:必须在最后阶段释放锁资源) 将提交分成两阶段进行的目

的很明确,就是尽可能晚地提交事务,让事务在提交前尽可能地完成所有能完成的工作。

Mybatis 缓存

Mybatis中有一级缓存和二级缓存,默认情况下一级缓存是开启的,而且是不能关闭的。一级缓存是指 SqlSession 级别的缓存,当在同一个

SqlSession 中进行相同的 SQL 语句查询时,第二次以后的查询不会从数据库查询,而是直接从缓存中获取,一级缓存最多缓存 1024

SQL。二级缓存是指可以跨 SqlSession 的缓存。是 mapper 级别的缓存,对于 mapper 级别的缓存不同的 sqlsession 是可以共享的。

public void transferAccount() {

UserTransaction userTx = null;

Connection connA = null; Statement stmtA = null; Connection connB = null; Statement stmtB

= null;

try{

// 获得 Transaction 管理对象 userTx = (UserTransaction)getContext().lookup("java:comp/UserTransaction");

connA = getDataSourceA().getConnection();// 从数据库 A 中取得数据库连接 connB =

getDataSourceB().getConnection();// 从数据库 B 中取得数据库连接

userTx.begin(); // 启动事务 stmtA = connA.createStatement();// A 账户中的金额减少 500

stmtA.execute("update t_account set amount = amount - 500 where account_id = 'A'");

// B 账户中的金额增加 500

stmtB = connB.createStatement();

stmtB.execute("update t_account set amount = amount + 500 where account_id = 'B'");

userTx.commit();// 提交事务

// 事务提交:转账的两步操作同时成功(数据库 A 和数据库 B 中的数据被同时更新)

} catch(SQLException sqle){

// 发生异常,回滚在本事务中的操纵

userTx.rollback();// 事务回滚:数据库 A 和数据库 B 中的数据更新被同时撤销 } catch(Exception ne){

}

}Mybatis 的一级缓存原理(sqlsession级别)

第一次发出一个查询 sqlsql 查询结果写入 sqlsession 的一级缓存中,缓存使用的数据结构是一个 map

keyMapperID+offset+limit+Sql+所有的入参

value:用户信息

同一个 sqlsession 再次发出相同的 sql,就从缓存中取出数据。如果两次中间出现 commit 操作(修改、添加、删除),本 sqlsession 中的

一级缓存区域全部清空,下次再去缓存中查询不到所以要从数据库查询,从数据库查询到再写入缓存。

二级缓存原理(mapper基本

二级缓存的范围是mapper 级别(mapper同一个命名空间),mapper以命名空间为单位创建缓存数据结构,结构是 mapmybatis 的二

级缓存是通过 CacheExecutor 实现的。CacheExecutor 其实是 Executor 的代理对象。所有的查询操作,在 CacheExecutor 中都会先匹配

缓存中是否存在,不存在则查询数据库。

keyMapperID+offset+limit+Sql+所有的入参

具体使用需要配置:

1. Mybatis 全局配置中启用二级缓存配置

2. 在对应的 Mapper.xml 中配置 cache 节点

3. 在对应的 select 查询节点中添加 useCache=true

MyBatis缓存

MyBatis缓存机制的设计与实现

本文主要讲解*MyBatis*非常棒的缓存机制的设计原理,给读者们介绍一下*MyBatis*的缓存机制的轮廓,然后会分别针对缓存机制中的方

方面面展开讨论。

*MyBatis*将数据缓存设计成两级结构,分为一级缓存、二级缓存:**一级缓存是\**Session\**会话级别的缓存**,位于表示一次数据库会话的***\*SqlSession\****对象之中,又被称之为本地缓存。一级缓存

***\*MyBatis\****内部实现的一个特性,用户不能配置,默认情况下自动支持的缓存,用户没有定制它的权利(不过这也不是绝对的,可以通过

开发插件对它进行修改);

**二级缓存是\**Application\**应用级别的缓存**,它的是生命周期很长,跟***\*Application\****的声明周期一样,也就是说它的作用范

围是整个***\*Application\****应用。

*MyBatis*中一级缓存和二级缓存的组织如下图所示:

*一级缓存的工作机制:*

一级缓存是*Session*会话级别的,一般而言,一个*SqlSession*对象会使用一个*Executor*对象来完成会话操作,*Executor*对象

会维护一个*Cache*缓存,以提高查询性能。

二级缓存的工作机制:

如上所言,一个*SqlSession*对象会使用一个*Executor*对象来完成会话操作,MyBatis的二级缓存机制的关键就是对这个

*Executor*对象做文章。如果用户配置了"*cacheEnabled=true*",那么MyBatis在为*SqlSession*对象创建*Executor*对象时,会

*Executor*对象加上一个装饰者:CachingExecutor,这时*SqlSession*使用CachingExecutor对象来完成操作请求。

CachingExecutor对于查询请求,会先判断该查询请求在Application级别的二级缓存中是否有缓存结果,如果有查询结果,则直接

返回缓存结果;如果缓存中没有,再交给真正的*Executor*对象来完成查询操作,之后CachingExecutor会将真正*Executor*返回的

查询结果放置到缓存中,然后在返回给用户。MyBatis的二级缓存设计得比较灵活,你可以使用MyBatis自己定义的二级缓存实现;你也可以通过实现

*org.apache.ibatis.cache.Cache*接口自定义缓存;也可以使用第三方内存缓存库,如*Memcached*等,这个我们会在后续的文章

中详细讨论。


http://www.ppmy.cn/news/75233.html

相关文章

【BBQ: A Hand-Built Bias Benchmark for Question Answering 论文精读】

BBQ: A Hand-Built Bias Benchmark for Question Answering 论文精读 InformationAbstract1 Introduction2 Related Work3 The Dataset3.1 Coverage3.2 Template Construction3.3 Vocabulary4 Validation5 Evaluation6 Results7 Discussion8 Conclusion9 Ethical Consideration…

shell sed命令

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 sed 命令sed 编辑器sed 的工作流程的三个过程命定格式常用选项常用操作 实验操作打印内容使用地址删除行替换插入 sed 命令 sed 编辑器 sed是一种流编辑器&#x…

【JavaScript】线程和进程,JavaScript线程,事件队列,事件循环 ,微任务、宏任务

❤️ Author: 老九 ☕️ 个人博客:老九的CSDN博客 🙏 个人名言:不可控之事 乐观面对 😍 系列专栏: 文章目录 进程和线程JavaScript线程事件队列、事件循环微任务、宏任务面试题1面试题2 进程和线程 进程&a…

Ceres简介及示例(8)On Derivatives(Analytic Derivatives)

考虑以下曲线(Rat43) 的拟合问题: y b 1 ( 1 e b 2 − b 3 x ) 1 / b 4 y \frac{b_1}{(1e^{b_2-b_3x})^{1/b_4}} y(1eb2​−b3​x)1/b4​b1​​ 也就是说,给定一些数据 { x i , y i } , ∀ i 1 , . . . , n \{x_i, y_i\},\ \forall i1,... ,n {xi​,yi​}, ∀…

小红书数据分析:如何用ChatGPT输出爆文笔记

ChatGPT的热度依旧不减,随着技术升级,越来越多更高级的玩法被发掘。今天我们就来聊聊,如何用ChatGPT写出小红书风格的文章。 首先,小红书笔记制作分为两个步骤: 1、找选题 2、写小红书风格的笔记 我们用例子说话&a…

SQL执行过程

1. select 语句执行过程 一条 select 语句的执行过程如上图所示 1、建立连接 连接器会校验你输入的用户名和密码是否正确,如果错误会返回提示,如果正确,连接器会查询当前用户对于的权限。连接器的作用就是校验用户权限 2、查询缓存 MySQL…

17.plantUML画类图的语法、组合关系和聚合关系之间的区别

文章目录 plantUML画类图的语法组合关系和聚合关系之间的区别依赖关系和关联关系的区别一个类图语法示例 plantUML画类图的语法 泛化关系就是继承关系 语法解释&#xff1a;<|-- 表示组合&#xff0c;<|-表示继承 表示 public&#xff0c; #表示protect - 表示 private…

新华三发布绿洲平台3.0,五大能力升级,构筑坚实用数底座

当前我国数字经济飞速发展&#xff0c;据中国信息通信研究院发布的《中国数字经济发展研究报告&#xff08;2023年&#xff09;》显示&#xff0c;2022年&#xff0c;我国数字经济规模达到50.2万亿元&#xff0c;同比名义增长10.3%&#xff0c;已连续11年显著高于同期GDP名义增…