[SSM]MyBatis的缓存与逆向工程

news2024/11/27 9:47:09

目录

十三、MyBatis的缓存

13.1一级缓存

13.2二级缓存

13.3MyBatis集成EhCache

十四、MyBatis的逆向工程

14.1逆向工程配置与生成

14.2测试


十三、MyBatis的缓存

  • 缓存:cache

  • 缓存的作用:通过减少IO的方式,来提高程序的执行效率。

  • mybatis的缓存:将select语句的查询结果放到缓存(内存)当中,下一次还是执行这条select语句的话,直接从缓存中取,不再查数据库。

    • 减少了IO

    • 不再执行繁琐的查找算法,效率大大提升。

  • mybatis的缓存包括:

    • 一级缓存:将查询的数据存储到SqlSession中。

    • 二级缓存:将查询到的数据存储到SqlSessionFactory中。

    • 或者集成其它第三方的缓存:比如EhCache[Java语言开发的]、Memcache[C语言开发的]等。

  • 缓存只针对DQL语句,也就是说缓存机制只对应select语句。

13.1一级缓存

  • 一级缓存是默认开启的,不需要做任何配置。

  • 原理:只要使用同一个SqlSession对象执行同一条SQL语句,就会走缓存。

  • 什么情况下不走缓存:

    • 第一种:不同的SqlSession对象。

    • 第二种:查询条件变化了。

  • 一级缓存失效情况包括两种:

    • 第一种:第一次查询和第二次查询之间,手动清空了一级缓存。

     @Test
        public void testSelectById(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
    ​
            CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);
            Car car1 = mapper1.selectById(164L);
            System.out.println(car1);
    ​
            // 手动清空一级缓存
            sqlSession.clearCache();
    ​
            CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);
            Car car2 = mapper2.selectById(164L);
            System.out.println(car2);
    ​
            sqlSession.commit();
            sqlSession.close();
    • 第二种:第一次查询和第二次查询之间,执行力增删改操作。【这个增删改和哪张表没有关系,只有insert delete update操作,一级缓存就失效】

    @Test
        public void testSelectById(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
    ​
            CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);
            Car car1 = mapper1.selectById(164L);
            System.out.println(car1);
    ​
            // 在这里执行了INSERT DELETE UPDATE中的任意一个语句。并且和表没有关系。
            CarMapper mapper = sqlSession.getMapper(CarMapper.class);
            mapper.insertClazz(2000, "高三三班");
    ​
            CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);
            Car car2 = mapper2.selectById(164L);
            System.out.println(car2);
    ​
            sqlSession.commit();
            sqlSession.close();

13.2二级缓存

  • 二级缓存的范围是SqlSessionFactory。

  • 使用二级缓存需要具备以下几个条件:

    • <setting name="cacheEnabled" value="true">在mybatis核心配置文件中全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。默认是true,无需设置。

    • 在需要使用二级缓存的SqlMapper.xml文件中添加配置:<cache/>

    <?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.hhb.mapper.CarMapper">
    ​
        <cache/>
    ​
        <select id="selectById" resultType="car">
            select *
            from t_car
            where id = #{id};
        </select>
    ​
    </mapper>
    • 使用二级缓存的实体类对象必须是可序列化的,也就是必须实现java.io.Serializable接口。

    • SqlSession对象关闭或提交之后,一级缓存中的数据才会被写入到二级缓存当中,此时二级缓存才可用。

     @Test
        public void testSelectById() throws IOException {
            //这里只有一个SqlSessionFactory对象,二级缓存对应的就是SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml"));
            SqlSession sqlSession1 = sqlSessionFactory.openSession();
            SqlSession sqlSession2 = sqlSessionFactory.openSession();
            CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
            CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);
    ​
            //这段代码执行之后,实际上数据是缓存到一级缓存当中了。(sqlSession1是一级缓存)
            Car car1 = mapper1.selectById(40L);
            System.out.println(car1);
            //如果这里不关闭SqlSession1对象的话,二级缓存中是没有数据的。
            //程序执行到这里的时候,会将sqlSession1这个一级缓存中的数据写入到二级缓存中。
            sqlSession1.close();
    ​
            //这段代码执行之后,实际上数据是缓存到一级缓存当中了。(sqlSession2是一级缓存)
            Car car2 = mapper2.selectById(40L);
            System.out.println(car2);
    ​
            sqlSession2.close();
        }
  • 二级缓存的失效:只要查询两次之间出现了增删改操作,二级缓存就会失效。【一级缓存也会失效】

  • 二级缓存的相关配置:

  • eviction(驱逐):指定从缓存中移除某个对象的淘汰算法。默认使用LRU策略。

    • LRU:Least Recently User。最近最少使用。优先淘汰在间隔时间内使用频率最低的对象。(其实还有一种淘汰算法LFU,最不常用。)

    • FIFO:First In First Out。一种先进先出的数据缓存器。先进入二级缓存的对象最先被淘汰。

    • SOFT:软引用。

    • WEAK:弱引用。

  • flushInterval:

    • 二级缓存的刷新时间间隔。单位毫秒。如果没有配置,就代表不刷新缓存,只要内存足够大,一直会向二级缓存中缓存数据,除非执行力增删改。

  • readOnly:

    • true:多条相同的sql语句执⾏之后返回的对象是共享的同⼀个。性能好。但是多线程并发可能会存在安全问题。

    • false:多条相同的sql语句执⾏之后返回的对象是副本,调⽤了clone⽅法。性能⼀般。但安全。

  • size:

    • 设置二级缓存中最多可存储的java对象数量,默认值是1024.

13.3MyBatis集成EhCache

  • 集成EhCache是为了代替mybatis自带的二级缓存,一级缓存是无法替代的。

  • mybatis对外提供了接口,也可以集成第三方的缓存组件。比如EhCache、Memcache等都可以。

  • EhCache是Java写的,Memcache是C语言写的,所以mybatis集成EhCache较为常见。

第一步:在pom.xml文件中引入mybatis整合ehcache的依赖。

<!--mybatis集成ehcache的组件-->
<dependency>
 <groupId>org.mybatis.caches</groupId>
 <artifactId>mybatis-ehcache</artifactId>
 <version>1.2.2</version>
</dependency>
<!--ehcache需要slf4j的⽇志组件,log4j不好使-->
<dependency>
 <groupId>ch.qos.logback</groupId>
 <artifactId>logback-classic</artifactId>
 <version>1.2.11</version>
 <scope>test</scope>
</dependency>

第二步:在类的根路径下新建echcache.xml⽂件,并提供以下配置信息。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
 updateCheck="false">
 <!--磁盘存储:将缓存中暂时不使⽤的对象,转移到硬盘,类似于Windows系统的虚拟内存-->
 <diskStore path="e:/ehcache"/>
 
 <!--defaultCache:默认的管理策略-->
 <!--eternal:设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有
效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断-->
 <!--maxElementsInMemory:在内存中缓存的element的最⼤数⽬-->
 <!--overflowToDisk:如果内存中数据超过内存限制,是否要缓存到磁盘上-->
 <!--diskPersistent:是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false-
->
 <!--timeToIdleSeconds:对象空闲时间(单位:秒),指对象在多⻓时间没有被访问就会失
效。只对eternal为false的有效。默认值0,表示⼀直可以访问-->
 <!--timeToLiveSeconds:对象存活时间(单位:秒),指对象从创建到失效所需要的时间。
只对eternal为false的有效。默认值0,表示⼀直可以访问-->
 <!--memoryStoreEvictionPolicy:缓存的3 种清空策略-->
 <!--FIFO:first in first out (先进先出)-->
 <!--LFU:Less Frequently Used (最少使⽤).意思是⼀直以来最少被使⽤的。缓存的元
素有⼀个hit 属性,hit 值最⼩的将会被清出缓存-->
 <!--LRU:Least Recently Used(最近最少使⽤). (ehcache 默认值).缓存的元素有⼀
个时间戳,当缓存容量满了,⽽⼜需要腾出地⽅来缓存新的元素的时候,那么现有缓存元素中时间戳
离当前时间最远的元素将被清出缓存-->
 <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDis
k="false" diskPersistent="false"
 timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStor
eEvictionPolicy="LRU"/>
</ehcache>

第三步:修改CarMapper.xml文件中的<cache/>标签,添加type属性。

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

十四、MyBatis的逆向工程

  • 所谓的逆向工程是:根据数据库表逆向生成Java的pojo类,SqlMapper.xml文件,以及Mapper接口类等。

  • 要想完成这个工作,需要借助别人写好的逆向工程插件。

  • 使用这个插件,需要给这个插件配置哪些信息?

    • pojo类名、包名以及生成位置。

    • SqlMapper.xml文件名以及生成位置。

    • Mapper接口名以及生成位置。

    • 连接数据库的信息。

    • 指定哪些表参与逆向工程。

    • ...

14.1逆向工程配置与生成

第一步:基础环境准备

  • 新建模块:mybatis012-generator1

  • 打包⽅式:jar

第二步:在pom.xml中添加逆向工程插件

<!--定制构建过程-->
<build>
 <!--可配置多个插件-->
 <plugins>
 <!--其中的⼀个插件:mybatis逆向⼯程插件-->
 <plugin>
 <!--插件的GAV坐标-->
 <groupId>org.mybatis.generator</groupId>
 <artifactId>mybatis-generator-maven-plugin</artifactId>
 <version>1.4.1</version>
 <!--允许覆盖-->
 <configuration>
 <overwrite>true</overwrite>
 </configuration>
 <!--插件的依赖-->
 <dependencies>
 <!--mysql驱动依赖-->
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>8.0.31</version>
 </dependency>
 </dependencies>
 </plugin>
 </plugins>
</build>

第三步:配置generatorConfig.xml

  • 该文件名必须叫做:generatorConfig.xml

  • 该文件必须放在类的根路径下。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
​
<generatorConfiguration>
    <!--
        targetRuntime有两个值:
            MyBatis3Simple:生成的是基础版,只有基本的增删改查。
            MyBatis3:生成的是增强版,除了基本的增删改查之外还有复杂的增删改查。
    -->
    <context id="DB2Tables" targetRuntime="MyBatis3Simple">
        <!--防止生成重复代码-->
        <plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
​
        <commentGenerator>
            <!--是否去掉生成日期-->
            <property name="suppressDate" value="true"/>
            <!--是否去除注释-->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
​
        <!--连接数据库信息-->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mybatis"
                        userId="root"
                        password="030522">
        </jdbcConnection>
​
        <!-- 生成pojo包名和位置 -->
        <javaModelGenerator targetPackage="com.hhb.pojo" targetProject="src/main/java">
            <!--是否开启子包-->
            <property name="enableSubPackages" value="true"/>
            <!--是否去除字段名的前后空白-->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
​
        <!-- 生成SQL映射文件的包名和位置 -->
        <sqlMapGenerator targetPackage="com.hhb.mapper" targetProject="src/main/resources">
            <!--是否开启子包-->
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
​
        <!-- 生成Mapper接口的包名和位置 -->
        <javaClientGenerator
                type="xmlMapper"
                targetPackage="com.hhb.mapper"
                targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
​
        <!-- 表名和对应的实体类名-->
        <table tableName="t_car" domainObjectName="Car"/>
​
    </context>
</generatorConfiguration>
  • MyBatis3Simple:生成的是基础班,只有基本的增删改查。

  • MyBatis3:生成的是增强版,除了基本的增删改查之外还有复杂的增删改查。

第四步:运行插件

14.2测试

 //CarExample类负责封装查询条件
    @Test
    public void testSelect() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        //执行查询
        //1.查询一个
        Car car = mapper.selectByPrimaryKey(39L);
        System.out.println(car);
        //2.查询所有(selectByExample,根据条件查询,如果条件是null表示没有条件)
        List<Car> cars = mapper.selectByExample(null);
        cars.forEach(car1 -> System.out.println(car1));
        //3.按条件查询
        //QBC风格:Query By Criteria 一种查询方式,比较面向对象,看不到sql语句。
        //封装条件:通过CarExample对象来封装查询条件
        CarExample carExample = new CarExample();
        //调用carExample.createCriteria()方法来创建查询条件
        carExample.createCriteria().andBrandLike("比亚迪秦").andGuidePriceGreaterThan(new BigDecimal(20.00));
        //添加or
        carExample.or().andCarTypeEqualTo("燃油车");
        //执行查询
        List<Car> cars2 =mapper.selectByExample(carExample);
        cars2.forEach(car2 -> System.out.println(car2));
        sqlSession.close();
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【分布式】 ELK 企业级日志分析系统 二

目录 一、FilebeatELK 部署1.1 环境部署 二、grok 正则捕获插件mutate 数据修改插件multiline 多行合并插件date 时间处理插件 一、FilebeatELK 部署 1.1 环境部署 Node1节点&#xff08;2C/4G&#xff09;&#xff1a;node1/192.168.137.101 Elasticsearch Node2节点&…

【C++顺序容器】forward_list的成员函数和非成员函数

目录 forward_list 1. forward_list的成员函数 1.1 构造、析构和赋值运算符重载 1.1.1 构造函数 1.1.2 析构函数 1.1.3 赋值运算符重载 1.2 迭代器 1.3 容量 1.4 元素访问 1.4.1 遍历方法 1.5 修改器 1.6 操作 1.7 观察者 2. forward_list的非成员函数 forward_l…

npm5中本地间模块引用的最好方式(附带引用方法总结)

引用其他的包 正常情况下在项目 package.json 所在的目录&#xff08;一般也是项目根目录&#xff09;运行npm install xxxx 命令之后&#xff0c;会从远程或者代理地址下载xxxx包到node_modules&#xff0c;然后在package.json生成对应的包名和版本 如果想要依赖本地自己开发…

TypeScript 学习笔记(一):类型

文章目录 一、常见类型1. 数组2. 布尔3. 数值4. 字符串5. object6. null 和 undefined7. symbol7.1 作为属性名7.2 属性名遍历7.3 静态方法&#xff1a;Symbol.for()和 Symbol.keyFor()7.4 内置 symbol 值7.4.1 Symbol.hasInstance7.4.2 Symbol.isConcatSpreadable7.4.3 Symbol…

第四十五章Java 接口

Java 接口 接口&#xff08;英文&#xff1a;Interface&#xff09;&#xff0c;在JAVA编程语言中是一个抽象类型&#xff0c;是抽象方法的集合&#xff0c;接口通常以interface来声明。一个类通过继承接口的方式&#xff0c;从而来继承接口的抽象方法。 接口并不是类&#x…

DevOps(二)

CD 1. 平台选择2. 技术选型3. 阶段性目标4. 搭建示例4.1 环境准备(节点机)1. java版本升级2. 编译安装git3. docker安装4. docker-compose安装5. sonarqube安装6. harbor安装7. gitlab私服 4.2 示例一&#xff08;手动&#xff09;1. 创建项目2. 编码3. Dockerfile4. 拷贝pytho…

【linux】线程详解

线程 线程的概念 在官方书籍对于线程的概念&#xff1a; 1.在进程内部的执行流 2.线程比进程粒度更细&#xff0c;调度成本更低。 3.线程是CPU调度的最小单位。 线程&#xff08;tcb&#xff09;&#xff1a;进程&#xff08;pcb&#xff09; n&#xff1a;1 进程和线程在执…

Java 动态规划 面试题 17.16. 按摩师

代码展示&#xff1a; class Solution {public int massage(int[] nums) {int nnums.length;if(n0){return 0;}//创建数组int f[]new int[n]; //f[i]表示接i位置的最长时间int g[]new int[n]; //g[i]表示不接i位置的最长时间//初始化f[0]nums[0];g[0]0;//填充数组for(int i1;i…

VectorCAST单元测试手动配置测试用例

一、单元测试 等待环境创建完成后&#xff0c;就可以开始单元测试。 二、生成测试用例 在 VectorCAST 中&#xff0c;一共有两种方法来生成测试用例&#xff0c;一种是手动生成测试用例&#xff0c;另外一种是自动 生成测试用例。 三、手动生成测试用例 在 VectorCAST 中&a…

《面试1v1》Redis分布式锁

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

泛微E-Cology SQL注入漏洞复现(QVD-2023-15672)

0x01 产品简介 泛微协同管理应用平台e-cology是一套兼具企业信息门户、知识文档管理、工作流程管理、人力资源管理、客户关系管理、项目管理、财务管理、资产管理、供应链管理、数据中心功能的企业大型协同管理平台。 0x02 漏洞概述 由于泛微e-cology未对用户的输入进行有效的…

matlab学习指南(2):安装工具箱Toolbox的方法(详细图解)

&#x1f305;*&#x1f539;** φ(゜▽゜*)♪ **&#x1f539;*&#x1f305; 欢迎来到馒头侠的博客&#xff0c;该类目主要讲数学建模的知识&#xff0c;大家一起学习&#xff0c;联系最后的横幅&#xff01; 喜欢的朋友可以关注下&#xff0c;私信下次更新不迷路&#xff0…

【项目 进程1】2.1 进程概述 2.2 进程状态转换

文章目录 2.1进程概述程序和进程**时间片****并行和并发****进程控制块(PCB)** 2.2进程状态转换**进程的状态** **进程相关命令****实时显示进程动态** 2.1进程概述 程序和进程 程序是包含一系列信息的文件&#xff0c;这些信息描述了如何在运行时创建一个进程&#xff1a; …

Linux的软链接与硬链接

Linux的软链接与硬链接 1&#xff0c;创建硬链接&#xff1a;2&#xff0c;创建软链接&#xff1a;3&#xff0c;软链接是什么4&#xff0c;软链接文件的权限5&#xff0c;硬链接是什么6&#xff0c;做个小实验 总结问题&#xff1a;为什么有软链接了&#xff08;快捷方式&…

Centos7.9通过expect脚本批量修改H3C交换机配置

背景&#xff1a; 公司有几百台H3C二层交换机设备&#xff0c;当需要批量更改配置时非常的消耗工作量 解决&#xff1a; 通过一台Linux服务器&#xff0c;编写shell脚本&#xff0c;模拟Telnet至各台交换机&#xff0c;让一切变的很容易 1.首先在安装Telnet服务前需要检测centO…

Java基础(动力节点课程)

JavaSE基础——第一章初识Java JavaSE JavaEE JavaMEJavaSEJavaEEJavaME Java语言跨平台性垃圾回收机制Java的加载和执行JDK、JRE、JVM关系安装JDK以及配置PATHJDK目录说明 第一个Java程序javac命令和java命令的具体用法javac命令的用法&#xff1a;java命令的用法&#xff1a;…

Transformer网络学习记录——基于空间约束自注意力和Transformer的RGB-D显著性检测方法研究

基于图半监督学习和图卷积的目标分割与跟踪算法研究 (wanfangdata.com.cn) 只能说看不懂&#xff0c;记录是为了有耐心慢消化 原文&#xff1a; 网络整体为通用的编码器-解码器架构 &#xff0c;总体上由骨干编码器、交互编码器、RGB 解码器、深度解码器组成。 具体来说&#…

ROCKSDB原理

按照读写的性质来分 分为读少写多和 写少读多 RocksDB适用于第一种。 磁盘中的数据结构 就地写和追加写 找到某一个页 然后将数据刷入到这一个页中. 这就导致了一个问题 就是追加写入的数据冗余 由于存在数据冗余 所以必须要对数据进行一定的处理才能保持查找性能 数据以块…

langchain系列:Model I/O模块之-Prompts

文章目录 Model I/O简介输入部分&#xff08;Prompts&#xff09;PromptTemplatefrom_template ChatPromptTemplate langchain是基于大语言模型而开发的一个框架&#xff0c;既然是基于大语言模型&#xff0c;自然最重要的就是先要介绍Model I/O模块。 Model I/O简介 Model I/O…

Helm3安装和使用

Helm3安装和使用 1、Helm简介 Helm 是 Kubernetes 上的包管理器&#xff0c;用来管理 Kubernetes 应用程序&#xff0c;Helm Charts 可帮助您定义&#xff0c;安装和升级 复杂的 Kubernetes 应用程序。Helm 把 Kubernetes 资源(比如deployments、services或ingress等) 打包到…