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对象实现逻辑分页
 @Test
    public 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的核心配置文件,获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,用来执行sql
        SqlSession 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 {
    @Nullable
    private Map<Object, Object> targetDataSources;
    @Nullable
    private Object defaultTargetDataSource;
    private boolean lenientFallback = true;
    private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
	// 存放的数据对象的Map集合类
    @Nullable
    private Map<Object, DataSource> resolvedDataSources;
    @Nullable
    private 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");
		// 决策当前选择的数据源的Key
        Object 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的实现方法,由子类去实现
    @Nullable
    protected abstract Object determineCurrentLookupKey();
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

js设计模式:原型模式

作用: 使用js特有的原型链机制,可以通过Object.create方法创建新对象,将一个对象作为另外一个对象的原型 也可以通过修改原型链上的属性,影响新对象的行为 可以更方便的创建一些对象 示例: let obj {getName: function(){return this.name},getAge:function(){return this…

【Flutter】底部导航BottomNavigationBar的使用

常用基本属性 属性名含义是否必须items底部导航栏的子项List是currentIndex当前显示索引否onTap底部导航栏的点击事件&#xff0c; Function(int)否type底部导航栏类型&#xff0c;定义 [BottomNavigationBar] 的布局和行为否selectedItemColor选中项图标和label的颜色否unsel…

[office] excel图表怎么发挥IF函数的威力 #微信#媒体

excel图表怎么发挥IF函数的威力 IF函数应该是最常用的Excel函数之一了&#xff0c;在公式中经常能够看到她的“身影”。IF函数的基本使用如图1所示。 图1 IF函数之美 IF函数是一个逻辑函数&#xff0c;通过判断提供相应操作&#xff0c;让Excel更具智能。 然而&#xff0c;…

Positive Technologies 确保 Rostic‘s 网络应用程序的安全

☑️ PT BlackBox分析 Rostics 网络应用程序的安全性 快餐连锁店在其安全网络开发过程中使用了我们的扫描仪。PT BlackBox 总共扫描了 20 多个 Rostics 的外部服务&#xff08;每天访问量超过 100,000 人次&#xff09;和企业服务&#xff08;每天访问量≈7,000 名员工&#x…

UE开发01--part 1:创建游戏模式、角色、控制器

1&#xff0c;右键选择新建C类 2&#xff0c;选择GameModeBase 3&#xff0c;随便命名&#xff0c;类的类型-->选择&#xff1a;公共&#xff1b; 这个选项会把.h和.cpp文件分开&#xff0c;方便我们查看与修改代码。 4.打开 VS 编辑器&#xff0c;查看我们刚刚创建得两文件…

windows安装以及切换使用nodejs多版本

1 安装nvm nvm是一个简单的bash脚本&#xff0c;它是用来管理系统中多个已存的Node.js版本。 可以先把系统已有的node卸载掉&#xff0c;也可不卸载&#xff0c;但是以防没必要的冲突&#xff0c;尽量还是卸掉。 1.1 下载nvm 下载地址&#xff1a;https://github.com/corey…

基于Python3的数据结构与算法 - 03 插入排序

类似于抽扑克牌&#xff1a; 初始时手里&#xff08;有序区&#xff09;只有一张牌每次&#xff08;从无序区&#xff09;摸一张牌&#xff0c;插入到手里已有牌的正确位置。 示例代码如下&#xff1a; def insert_sort(li):for i in range(1, len(li)): # i 表示摸到牌的下…

SAP PP学习笔记02 - PP中配置品目Master时的顺序

配置品目Master的时候&#xff0c;最佳实践是要遵循什么顺序呢&#xff1f; 一般而言是如下顺序 - 新规物料类型&#xff08;或利用现有类型也可以&#xff09; - 设定料号范围 - 设定物料状态&#xff08;比如准备好之前&#xff0c;要先锁住&#xff0c;等准备好了之后再…

HCIA-HarmonyOS设备开发认证V2.0-IOT硬件子系统-WatchDog

目录 一、 WATCHDOG 概述功能简介基本概念 二、WATCHDOG 模块相关API三、WATCHDOG HDF驱动开发3.1、开发步骤(待续...) 坚持就有收获 一、 WATCHDOG 概述 功能简介 看门狗&#xff08;Watchdog&#xff09;&#xff0c;又称看门狗计时器&#xff08;Watchdog timer&#xff0…

【AI大模型】ChatGPT在地学、GIS、气象、农业、生态、环境等领域中的高级应用

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

miniblink简单demo分享

效果图&#xff1a; 通过wke.h和miniblink_4975_x32.dll进行环境的搭建。

【机器学习】数据清洗——基于Numpy库的方法删除重复点

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

Python开发户型图编辑器-2D/3D户型图展示

在现代家居设计中&#xff0c;户型图是不可或缺的工具&#xff0c;它为设计师和业主提供了一个直观的展示和规划空间的方式。然而&#xff0c;传统的户型图编辑软件往往复杂难用&#xff0c;限制了设计师的创作灵感。我们为您带来了一款全新的Python开发的户型图编辑器&#xf…

Node.js+vue+mysql高校人事管理系统7sgv0

进修培训系统用例描述 学校为更好的发展师资队伍&#xff0c;结合各二级学院的具体需求制定了一系列的访学进修计划。根据教育事业的发展需求&#xff0c;在校内选拔出各学科、专业的优秀教师代表&#xff0c;到国内外高校研究院所进修访学进修。教师代表首先需要根据人事部发布…

Leetcode日记 290. 单词规律 给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。 这里的 遵循 指完全匹配

Leetcode日记 290. 单词规律 给定一种规律 pattern 和一个字符串 s &#xff0c;判断 s 是否遵循相同的规律。 这里的 遵循 指完全匹配 解题思路制作不易&#xff0c;感谢三连&#xff0c;谢谢啦 给定一种规律 pattern 和一个字符串 s &#xff0c;判断 s 是否遵循相同的规律。…

微服务篇之注册中心

一、eureka 1.eureka的作用 2.eureka工作流程 1. 服务提供者和服务消费者向注册中心注册服务信息&#xff0c;然后注册中心记录了对应的服务器地址。 2. 服务消费者从注册中心拉取服务提供者的信息。 3. 通过负载均衡找到对应的服务提供者地址。 4. 服务消费者远程调用对应的服…

团簇束流沉积技术:氢气传感器守护安全与环境的利器

在当今日益增长的能源需求背景下&#xff0c;氢气作为一种清洁、高效的能源载体&#xff0c;正逐渐受到广泛关注。然而&#xff0c;氢气的易燃易爆特性也带来了不小的安全隐患。因此&#xff0c;精确、快速地监测氢气泄漏成为了确保生产安全和环境监测的重中之重。基于团簇束流…

如何用GPT进行论文写作?

一&#xff1a;AI领域最新技术 1.OpenAI新模型-GPT-5 2.谷歌新模型-Gemini Ultra 3.Meta新模型-LLama3 4.科大讯飞-星火认知 5.百度-文心一言 6.MoonshotAI-Kimi 7.智谱AI-GLM-4 二&#xff1a;GPT最新技术 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#x…

GoLand 2023:为Go开发者打造的智能IDE mac/win激活版

JetBrains GoLand 2023是一款专为Go语言开发者打造的集成开发环境(IDE)&#xff0c;它提供了强大的代码编辑、调试、测试和重构功能&#xff0c;帮助开发者更高效地开发Go应用程序。 GoLand 2023 软件获取 JetBrains GoLand 2023继承了JetBrains在开发工具领域的丰富经验&…

阿里云轻量应用服务器怎么样?有哪些好处?

阿里云轻量应用服务器有哪些优势&#xff1f;轻量服务器具有价格优惠、使用门槛低快速上手、灵活变配、可视化运维等优势&#xff0c;阿里云百科aliyunbaike.com整理轻量应用服务器详细优势&#xff1a; 1、价格优惠 阿里云轻量应用服务器性价比高&#xff0c;价格优惠&#x…