MyBatis学习总结

MyBatis分页如何实现

分页分为
逻辑分页:查询出所有的数据缓存到内存里面,在从内存中筛选出需要的数据进行分页
物理分页:直接用数据库语法进行分页limit
mybatis提供四种方法分页:

  1. 直接在sql语句中分页,传递分页参数
    select _column,_column from _table [where Clause] [limit N][offset M]
    select * : 返回所有记录
    limit N : 返回 N 条记录
    offset M : 跳过 M 条记录, 默认 M=0, 单独使用似乎不起作用
    limit N,M = limit M offset N , 从第 N+1 条记录开始, 返回 M 条记录
  2. MyBatis提供了RowBounds对象实现逻辑分页
 @Testpublic void getUserByRowBounds(){SqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);//RowBounds实现RowBounds rowBounds = new RowBounds(1,2);//通过java代码层面实现分页List<Map> userList = sqlSession.selectList("com.jin.mapper.UserMapper.getUserByRowBounds", null, rowBounds);for (Map map1 : userList) {System.out.println(map1);}sqlSession.close();}

但是:RowBounds是将所有符合条件的数据全都查询到内存中,然后在内存中对数据进行分页,数据量非常大时,造成内存OOM。
3.MyBatis拦截器interceptor实现分页,截获所执行方法的sql语句与参数,动态拼接sql分页语句

利用拦截器实现Mybatis分页的一个思路就是拦截StatementHandler接口的prepare方法,然后在拦截器方法中把Sql语句改成对应的分页查询Sql语句,之后再调用StatementHandler对象的prepare方法,即调用invocation.proceed()

4.分页插件
例如pagehelper,物理分页,实际原理就是修改最后的执行sql,增加相应的分页内容,是基于拦截器实现的。
在这里插入图片描述

MyBatis二级缓存

  1. 功能 - 提高查询效率
  2. 工作流程-一级缓存-缺点-二级缓存
  3. 实现原理
    MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率。默认定义了两级缓存,分别是一级缓存和二级缓存。
    默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启。二级缓存需要手动开启和配置,他是基于namespace级别的缓存。为了提高扩展性,MyBatis定义了缓存接口Cache,我们可以通过实现Cache接口来自定义二级缓存。
    一级缓存(本地缓存)
    sqlSession级别的缓存,一级缓存一直是开启的,它实质上就是sqlSession级别的一个Map。
    一级缓存失效:
    sqlSession不同。
    sqlSession相同,查询条件不同(当前一级缓存中还没有这个数据)。
    sqlSession相同,两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响),实际上,这个是因为每个增删改查都有标签flushCache,增删改默认为flushCache=“true”,即执行完后就清除一级缓存和二级缓存。
    sqlSession相同,手动清除了一级缓存(缓存清空,session.clearCache(),注意,该方法只清除当前session的一级缓存)。
    二级缓存(全局缓存)
    namespace级别的缓存,一个namespace对应一个二级缓存。
    工作机制
    一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中。
    如果会话关闭或提交,一级缓存中的数据会被保存到二级缓存中,新的会话查询信息,就可以参照二级缓存中的内容。
    注意:不同的namespace查出的数据会放在自己对应的缓存(map)中。
    效果:数据会从二级缓存中取出。查出的数据都会被默认先放在一级缓存中,只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中。

先查询二级缓存,再查询一级缓存,最后查询数据库。
在这里插入图片描述
原理:sqlSession的executor持有一个Local cache对象,当用户发起查询,会根据执行语句到缓存查找,如果命中,直接返回,否则查询数据库再写入缓存。二级缓存则是executor的基础上做了一个装饰CachingExecutor装饰器,查询时先通过CachingExecutor查询二级缓存。

{}和\${}的区别

mybatis会对这两个符号解析,实现动态sql。

#{}匹配的是一个占位符,相当于JDBC中的一个?,会对一些敏感的字符进行过滤,编译过后会对传递的值加上双引号,因此可以防止SQL注入问题。

\${}匹配的是真实传递的值,传递过后,会与sql语句进行字符串拼接。${}会与其他sql进行字符串拼接,不能预防sql注入问题。

#{}的应用场景是为给SQL语句的where字句传递条件值,${}的应用场景是为了传递一些需要参与SQL语句语法生成的值。

mybatis代理模式

在这里插入图片描述
mapper接口和mapper配置文件的目录要对应。

//mybatis代理开发
public class MyBatisDemo2 {public static void main(String[] args) throws IOException {//1. 加载mybatis的核心配置文件,获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象,用来执行sqlSqlSession sqlSession = sqlSessionFactory.openSession();//3.执行sql namespace+id//List<Student> students = sqlSession.selectList("test.findAll");//3.1 获取StudentMapper接口的代理对象StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);studentMapper.findAll();//System.out.println(students);//mybatis提供了mapper接口代理的开发方式,不需要再编写dao类,只需要编写一个mapper接口,一个mapper的接口和一个mapper.xml相对应,// 只需要调用SqlSession对象上的getMapper(),传入mapper接口的class信息,即可获得一个mapper代理对象,// 直接调用mapper接口中的方法,即相当于调用mapper.xml中的各个SQL标签,此时就不需要指定SQL标签的id字符串了,// mapper接口中的一个方法,就对应了mapper.xml中的一个SQL标签//4.释放资源sqlSession.close();}

mybatis动态数据源配置

Spring内置了一个AbstractRoutingDataSource,它可以把多个数据源配置成一个Map,然后,根据不同的key返回不同的数据源。因AbstractRoutingDataSource也是一个DataSource接口。应用程序可以先设置好key, 访问数据库的代码就可以从AbstractRoutingDataSource拿到对应的一个真实的数据源,从而访问指定的数据库。
源码中有一个核心的方法 setTargetDataSources(Map<Object, Object> targetDataSources) ,它需要一个Map,在方法注释中我们可以得知,这个Map存储的就是我们配置的多个数据源的键值对。我们整理一下这个类切换数据源的运作方式,这个类在连接数据库之前会执行determineCurrentLookupKey()方法,这个方法返回的数据将作为key去targetDataSources中查找相应的值,如果查找到相对应的DataSource,那么就使用此DataSource获取数据库连接它是一个abstract类,所以我们使用的话,推荐的方式是创建一个类来继承它并且实现它的determineCurrentLookupKey() 方法,这个方法介绍上面也进行了说明,就是通过这个方法进行数据源的切换。

public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {@Nullableprivate Map<Object, Object> targetDataSources;@Nullableprivate Object defaultTargetDataSource;private boolean lenientFallback = true;private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();// 存放的数据对象的Map集合类@Nullableprivate Map<Object, DataSource> resolvedDataSources;@Nullableprivate DataSource resolvedDefaultDataSource;public AbstractRoutingDataSource() {}// 初始化设置数据源public void setTargetDataSources(Map<Object, Object> targetDataSources) {this.targetDataSources = targetDataSources;}// ...protected DataSource determineTargetDataSource() {Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");// 决策当前选择的数据源的KeyObject lookupKey = this.determineCurrentLookupKey();// 当前选择的数据源DataSource dataSource = (DataSource)this.resolvedDataSources.get(lookupKey);if (dataSource == null && (this.lenientFallback || lookupKey == null)) {dataSource = this.resolvedDefaultDataSource;}if (dataSource == null) {throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");} else {return dataSource;}}// 数据源Key的实现方法,由子类去实现@Nullableprotected abstract Object determineCurrentLookupKey();
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/260739.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

主流开发语言和开发环境介绍

主流开发语言和开发环境介绍文章目录 ⭐️ 主流开发语言&#xff1a;2024年2月编程语言排行榜&#xff08;TIOBE前十&#xff09;⭐️ 主流开发语言开发环境介绍1.Python2.C3.C4.Java5.C#6.JavaScript7.SQL8.GO9.Visual Basic10.PHP ⭐️ 主流开发语言&#xff1a;2024年2月编程…

二叉树(6)——二叉树的创建和销毁

1 二叉树的创建 整体思路 将数组里的元素一直分为根&#xff0c;左子树&#xff0c;右子树&#xff0c;遇到#就返回NULL&#xff0c;链接到上层递归的左子树或者右子树&#xff0c;一定要把一个节点的左子树全部递归完才能返回到右子树。这种方法也可以scanf一个数组里的元素&…

苍穹外卖——第一天nginx

放到全是英文路径的打不开 到安装路径进入cmd&#xff0c;输入nginx -t nginx: the configuration file E:\Astudy\nginx-1.20.2/conf/nginx.conf syntax is ok nginx: [emerg] bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbid…

考研证件照可以自己用手机拍吗?考研证件照p过可以通过审核吗?考研证件照有什么要求

一、考研证件照可以自己用手机拍吗 现在的智能手机相机技术先进&#xff0c;大多都配备了高像素摄像头&#xff0c;使得自拍照片的质量有了大幅提升。相较于传统的证件照拍摄&#xff0c;使用手机自拍考研证件照理论上是可行的。然而&#xff0c;考研证件照需要满足一定的规定…

ansible剧本中的角色

1 roles角色 1.1 roles角色的作用&#xff1f; 可以把playbook剧本里的各个play看作为一个角色&#xff0c;将各个角色打的tasks任务、vars变量、template模版和copy、script模块使用的相关文件等内容放置在指定角色的目录里统一管理&#xff0c;在需要的时候可在playbook中使…

【linux】查看openssl程序的安装情况

【linux】查看openssl程序的安装情况 1、查看安装包信息 $ rpm -qa |grep openssl 2、安装路径 $ rpm -ql openssl $ rpm -ql openssl-libs $ rpm -ql openssl-devel 3、相关文件和目录 /usr/bin/openssl /usr/include/openssl /usr/lib64/libssl.so.* /usr/lib64/libcrypto…

Java实现Redis延时队列

“如何实现Redis延时队列”这个面试题应该也是比较常见的&#xff0c;解答如下&#xff1a; 使用sortedset&#xff08;有序集合&#xff09; &#xff0c;拿时间戳作为 score &#xff0c;消息内容作为key 调用 zadd 来生产消息&#xff0c;消费者用zrangebyscore 指令获取 N …

视频生成模型作为世界模拟器

我们探索了在视频数据上大规模训练生成模型。具体来说&#xff0c;我们联合训练文本条件扩散模型&#xff0c;处理不同持续时间、分辨率和宽高比的视频和图像。我们利用一种在时空补丁上操作视频和图像潜码的transformer架构。我们最大的模型&#xff0c;Sora&#xff0c;能够生…

LeetCode 450.删除二叉搜索树中的节点和669.修建二叉搜索树思路对比 及heap-use-after-free问题解决

题目描述 450.删除二叉搜索树中的节点 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;…

java 使用documents4j将XML转为pdf文件的方式

1.背景&#xff1a; 通过spire.doc.free将word转换成PDF时存在缺陷&#xff1a;只能获取前3页。获取全文另外需支付费用。 2.解决办法 使用documents4j&#xff0c;documents4j会保留原word文件中更多的样式&#xff0c;如修订模式下的差异化字体颜色、文档右侧修订记录等。 …

掌握Go并发:Go语言并发编程深度解析

&#x1f3f7;️个人主页&#xff1a;鼠鼠我捏&#xff0c;要死了捏的主页 &#x1f3f7;️系列专栏&#xff1a;Golang全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&…

【Docker】集群容器监控和统计 Portainer基本用法

Portainer是一款轻量级的应用&#xff0c;它提供了图形化界面&#xff0c;用川于方便地管理Docker环境&#xff0c;包括单机环境和集群环境。 主要功能&#xff1a;实现集群容器的监控和统计 下载安装 官网&#xff1a;https://www.portainer.io 文档&#xff1a;https://do…

C#分部类的应用:记录学生信息

目录 一、分部类及其用途 二、实例 再发一个分部类的应用&#xff0c;巩固一下。 一、分部类及其用途 C#中的部分类也被称为分部类。 C#中的部分类是一种将类的定义分成多个部分&#xff0c;每个部分都位于自己的文件中&#xff0c;然后在编译时合并在一起的机制。 部分类…

(十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)

简述 操作路径如下: 作用:通过逐步增加线程数来模拟用户并发访问。配置:设置This group will start、First,wait for 、Then start、Next , add等参数。使用场景:模拟逐步增长的并发访问,观察应用程序的性能变化。优点:适用于测试应用程序在逐步增加负载下的性能表现。…

stm32——hal库学习笔记(定时器)

这里写目录标题 一、定时器概述&#xff08;了解&#xff09;1.1&#xff0c;软件定时原理1.2&#xff0c;定时器定时原理1.3&#xff0c;STM32定时器分类1.4&#xff0c;STM32定时器特性表1.5&#xff0c;STM32基本、通用、高级定时器的功能整体区别 二、基本定时器&#xff0…

智慧城市与数字孪生:实现城市可持续发展的关键

一、引言 随着全球城市化进程的加速&#xff0c;城市面临着诸多挑战&#xff0c;如资源紧张、环境恶化、交通拥堵等。为了解决这些问题&#xff0c;智慧城市的概念应运而生。智慧城市利用先进的信息通信技术&#xff0c;提升城市治理水平&#xff0c;改善市民的生活质量。而数…

[C#]winform基于opencvsharp结合pairlie算法实现低光图像增强黑暗图片变亮变清晰

【低光图像增强介绍】 在图像处理领域&#xff0c;低光图像增强是一个具有挑战性的任务。由于光线不足&#xff0c;这些图像往往呈现出低对比度、高噪声和细节丢失等问题&#xff0c;严重影响了图像的视觉效果和后续分析的准确性。因此&#xff0c;开发有效的低光图像增强方法…

Redis(03)——发布订阅

基础命令 基于频道 publish channel message&#xff1a;将信号发送到指定的频道pubsub subcommand [argument [argyment]]&#xff1a;查看订阅或发布系统状态subscribe channel [channel]&#xff1a;订阅一个或多个频道的信息unsubscribe [channel [channel]]&#xff1a;退…

SpringBootWeb学习笔记——12万字详细总结!

0. 写在前面 注:这套笔记是根据黑马程序员B站2023-3-21的视频学习的成果,其中省略了前端基础部分、Maven部分和数据库基础部分,详情可见目录。 注注:目前文章内结尾处多幅图片加载不出来,因为图片还存在本地没被传上来,过段时间再改~ 所有的Spring项目都基于Spring Fra…

Vue路由组件练习

Vue 路由组件练习 1. 演示效果 2. 代码分析 2.1. 安装 vue-router 命令&#xff1a;npm i vue-router 应用插件&#xff1a;Vue.use(VueRouter) 2.2. 创建路由文件 在 src 文件夹下&#xff0c;创建router文件夹&#xff0c;并在该文件夹创建index.js文件 2.3. 导入依赖…