MyBatis延迟加载缓存分页逆向工程

news2025/1/20 1:51:24

文章目录

  • 延迟加载
    • 概述
    • 步骤
  • 缓存
    • 一级缓存
      • 介绍
      • 原理
    • 二级缓存
      • 介绍
    • 设置缓存对象策略
      • 原理
      • 开启步骤
      • 属性解释
      • 是否使用一级缓存
  • 分页插件
    • 使用步骤
  • 逆向工程
    • 介绍
    • 搭建
    • 使用
      • 修改

延迟加载

概述

延迟加载本身是依赖于多表查询的

  • 延迟加载中返回值要选择resultMap
  • 返回的结果一定是Dto

延迟加载也可以成为按需加载;默认是没有开启的

步骤

  1. 在config.xml中配置下面代码
<!-- lazyLoadingEnabled:延迟加载全局开关,开启后所有关联对象
		都会延迟加载;默认是false
		aggressiveLazyLoading:按需加载;
		开启时,任一方法的调用都会加载该对象的所有延迟加载属性,因此设置为false;
		设置为false表示的意思就是按需加载;mybatis版本3.4以上默认是false
	 -->
   <setting name="lazyLoadingEnabled" value="true"/>
   <setting name="aggressiveLazyLoading" value="false"/>

使用的时候需要将lazyLoadingEnabled设置为true,将aggressiveLazyLoading设置为false

  1. 在mapper.xml中书写下面代码
	<!-- 一对多 -->
		<select id="selectOrderAndDetails" resultMap="map1" >
			select * from b_order
		</select>
		<resultMap type="BOrderDto" id="map1" extends="BaseMap">
			<!-- 延迟加载和多表查询(高级映射)的区别:
				在标签(collection或者association)中,添加column属性和select属性;
				select属性中:里面的内容写的是:namespace.sqlID;
					    表示的是:用来封装当前collection或者association的返回结果
					    	也就是select属性值中的sqlid查询出来的应该是和ofType同等类型;
				column属性指的是:第一步查询结果中的列名——》用作参数传入到select调用的sqlId中;
			 -->
			<collection property="details" ofType="BOrderDetailDto" column="id" select="selectDetails">
								
			</collection>
		</resultMap>
		<!-- 按需加载,如果还需要查看订单详情信息,则调用该方法: -->
		<select id="selectDetails" resultMap="map2">
			select  id detail_id, goods_id, main_id, price, num
			from b_order_detail where main_id = #{id}
		</select>
		<resultMap type="BOrderDetailDto" id="map2">
			<id column="detail_id" property="id"></id>
			<result column="goods_id" property="goodsId"/>
			<result column="main_id" property="mainId"/>
			<result column="price" property="price"/>
			<result column="num" property="num"/>
		</resultMap>

缓存

mybatis为减轻数据库压力,提高数据库性能。提供了两级缓存机制:
mybatis框架中包含了一级缓存和二级缓存

一级缓存

介绍

框架中默认开启了一级缓存,一级缓存是sqlSession级别的缓存,缓存的数据只在SqlSession内有效

原理

  1. 第一次查询用户id为1的用户信息,先去缓存中查询是否有id为1的用户信息,如果没有,从数据库中查询用户信息。得到用户信息后,再将用户信息存储到一级缓存中
  2. 如果sqlSession去执行commit操作(插入,更新,删除),就会清空sqlSession中的一级缓存,保证缓存中始终保存的是最新的信息,避免脏读
  3. 第二次查询用户id为1的信息,先去缓存中查询是否有id为1的用户信息,如果缓存中有,则直接从缓存中获取
  4. :两次查询须在同一个sqlSession中完成,否则将不会走mybatis的一级缓存。在mybatis与spring进行整合开发时,事务控制在service中进行,重复调用俩次service将不会走一级缓存,因为在第一次调用时session方法结束,SqlSession就关闭了

注意事项

  1. 一个SqlSession结束后那么它里面的一级缓存也就不存在了
  2. mybatis的缓存是基于[namespace:sql:参数]来进行缓存的,意思就是,SqlSession的HashMap存储缓存数据时,是使用[namespace:sql:参数]作为key,查询返回的语句作为value保存的

二级缓存

介绍

  1. mapper级别的缓存,同一个namespace公用这一个缓存,所以对SqlSession是共享的,多个sqlSession去操作同一个Mapper的sql语句,多个sqlSession可以共用二级缓存,二级缓存是跨SqlSession的
  2. 二级缓存需要我们手动开启
  3. 作用域为namespace是指对该namespace对应的配置文件中所有的select操作结果都缓存,这样不同线程之间就可以共用二级缓存

设置缓存对象策略

  1. readOnly=“true”(只读):Mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。Mybatis为了加快获取数据,直接就会将数据在缓存中的引用交给用户。不安全,速度快
  2. readOnly=“false”(读写,默认):Myabtis觉得获取的数据可能会被修改,Mybatis会利用序列化或反序列化的技术克隆一份新的数据。安全,速度相对慢

原理

  1. 当一个sqlSession执行了一次select后,并关闭此session的时候,就会将查询结果存储到二级缓存中
  2. 当另一个sqlSession执行相同select时,首先会查询二级缓存,二级缓存中无对应数据,再去查询一级缓存,一级缓存中也没有,最后去数据库查找,从而减少了数据库压力提高了性能

注意事项

  1. 原理和一级缓存原理一样
  2. 开启了二级缓存后,还需要将要缓存的pojo实现Serializable接口,为了将缓存数据取出执行反序列化操作

开启步骤

  1. 在mybatis-config.xml中添加下列代码
<setting name="cacheEnabled" value="true"/>
  1. 在xxxMapper.xml文件中添加
<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"/>
  1. 对返回的结果对应的实体类进行序列化:implements Serializable
  2. 执行的时候对SqlSession进行关闭

属性解释

  1. eviction:缓存的回收策略,默认是LRU
  • LRU:最近最少使用,移除最长时间不被使用的对象
  • FIFO:先进先出,按对象进入缓存的顺序来移除它们
  • SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
  • WEAK:弱引用,更积极地移除基于垃圾收集器和弱引用规则的对象
  1. flushInterval:缓存刷新间隔。缓存多长时间清空一次,默认不清空,设置一个毫秒值
  2. readOnly:是否只读
  • true:只读
  • false:读写,默认
  1. size:缓存存放多少个元素
  2. type:指定自定义缓存的全类名(实现Cache接口即可)

是否使用一级缓存

如果一条语句每次都需要最新的数据,就意味着每次都需要从数据库中查询数据,可以把这个属性设置为false,如

<select id="selectUserById" resultMap="map" useCache="false">

二级缓存默认会在insert,update,delete操作后刷新缓存,但可以手动配置不更新缓存

<update id="updateUserById" parameterType="User" flushCache="false">

分页插件

pageHelper
官网:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md

使用步骤

  1. 在pom.xml中添加如下依赖
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>最新版本</version>
</dependency>
  1. 配置拦截器插件(在config.xml中)
<!--
    plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下:
    properties?, settings?,
    typeAliases?, typeHandlers?,
    objectFactory?,objectWrapperFactory?,
    plugins?,
    environments?, databaseIdProvider?, mappers?
-->
<plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
        <property name="param1" value="value1"/>
    </plugin>
</plugins>
  1. 书写代码

方式1:

//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(1, 10);
List<User> list = userMapper.selectAll();
//用PageInfo对结果进行包装
PageInfo page = new PageInfo(list);
//测试PageInfo全部属性
//PageInfo包含了非常全面的分页属性
assertEquals(1, page.getPageNum()); // 当前页
assertEquals(10, page.getPageSize()); //每页显示条数
assertEquals(1, page.getStartRow()); 
assertEquals(10, page.getEndRow());
assertEquals(183, page.getTotal());   //总条数
assertEquals(19, page.getPages());   //总页数
assertEquals(1, page.getFirstPage());
assertEquals(8, page.getLastPage());
assertEquals(true, page.isFirstPage());
assertEquals(false, page.isLastPage());
assertEquals(false, page.isHasPreviousPage());  //是否有前一页
assertEquals(true, page.isHasNextPage());

方式2:

//对应的lambda用法
pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(() -> userMapper.selectGroupBy());

逆向工程

介绍

正向工程操作:项目->需求分析->创建uml类图->创建实体类->表
逆向工程:表->创建实体类

搭建

  1. 逆向工程通常创建java项目,导入逆向工程所需要的maven插件
<build>
    <!--可配置多个插件-->
    <plugins>
      <!--其中的⼀个插件:mybatis逆向⼯程插件-->
      <plugin>
        <!--插件的GAV坐标-->
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>1.4.2</version>
        <!--允许覆盖-->
        <configuration>
          <overwrite>true</overwrite>
        </configuration>
        <!--插件的依赖-->
        <dependencies>
          <!--mysql驱动依赖-->
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
  1. 在resources下创建文件名为generatorConfig.xml(文件名必须是这个)
  • xml
<!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:一个配置文件中可以有多个context标签;
			id:表示唯一标识;
			defaultModelType:
				conditional:正常生成一个实体类,如果实体类中只有一个主键字段,不会生成实体类;
				flat:会为每张表生成一个实体类,实体类中包含表中所有字段;
				hierarchical:
					如果表中存在主键则生成主键类;
					表中非主键列并且非Blob类型的列,会生成一个类,该类继承主键类
					如果存在Blob类型的列,则为该类型的列生成专门的类,该类继承非主键类;
	  	targetRuntime:目标运行环境:
    -->
    <context id="DB2Tables"  targetRuntime="MyBatis3">
        <!--防⽌⽣成重复代码-->
        <plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>

        <commentGenerator>
            <!--是否去掉⽣成⽇期-->
            <property name="suppressDate" value="true"/>
            <!--是否去除注释-->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--连接数据库信息-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/db11?nullCatalogMeansCurrent=true"
                        userId="root"
                        password="123456">
        </jdbcConnection>
        <!-- ⽣成pojo包名和位置 -->
        <javaModelGenerator targetPackage="cn.ry.pojo" targetProject="src/main/java">
            <!--是否开启⼦包-->
            <property name="enableSubPackages" value="true"/>
            <!--是否去除字段名的前后空⽩-->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- ⽣成SQL映射⽂件的包名和位置 -->
        <sqlMapGenerator targetPackage="cn.ry.mapper" targetProject="src/main/resources">
            <!--是否开启⼦包-->
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- ⽣成Mapper接⼝的包名和位置 -->
        <javaClientGenerator
                type="xmlMapper"
                targetPackage="cn.ry.mapper"
                targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!-- 表名和对应的实体类名-->
        <table tableName="tb_item" domainObjectName="Item"/>
    </context>
</generatorConfiguration>
  1. 执行

image.png

  1. 出现BUID SUCCESS就是创建成功

image.png

使用

方法名含义
insert(obj)新增
insertSelective(obj)新增

区别:如果表中某列设置了默认值,新增语句中,刚好没给这一列赋值,此时前者赋值为null,后者赋值为默认值

方法名含义
deleteByPrimaryKey(key)根据主键id进行删除
deleteByExample(example)自定义条件删除

修改

方法名含义
updateByPrimaryKeySelective(obj)根据id进行修改,只更新不为空的数据;如果某列不想修改,直接不写,不会修改原来的值
updateByPrimaryKey(obj)根据id进行修改
updateByExampleSelective(obj,example)根据自定义条件进行修改
updateByExample(obj,example)根据自定义条件进行修改,如果没有设置id会报错

方法名含义
selectByPrimaryKey(key)根据主键去查询
countByExample(example)根据自定义条件查询数量
selectByExample(example)根据自定义条件查询

example的代码使用如下

			SqlSession s = SqlSessionUtil.getSqlSession();
			BOrderMapper mapper = s.getMapper(BOrderMapper.class);
		
			BOrderExample example =new BOrderExample();
			//创建条件对象;
			Criteria c = example.createCriteria();
			//使用条件对象中的方法:
			c.andOrderNoLike("%02%");
			c.andTotalGreaterThan(1);
			
			创建条件对象2;
			Criteria c1 = example.createCriteria();
			c1.andIdIsNotNull();
			
			example.or(c1);
			 List<BOrder> list = mapper.selectByExample(example);
			 System.out.println(list.size());

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

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

相关文章

[ROS 系列学习教程] 建模与仿真 - Xacro 语法

ROS 系列学习教程(总目录) 本文目录 一、属性与属性块二、数学表达式三、宏3.1 宏的基本使用3.2 属性块做为宏的入参3.3 任意数量元素做为宏的入参3.4 指定多个块元素的处理顺序3.5 宏嵌套3.6 默认参数3.7 局部属性 四、Rospack 命令五、包含其他 xacro 文件六、条件语句七、YA…

连锁超市能源能效管理方案

1.概述 连锁超市的能源消耗是其运营成本的重要组成部分。有效的能源能效管理不仅可以降低运营成本&#xff0c;也有助于环保&#xff0c;实现可持续发展。本文将探讨几种关键的能源能效管理策略。 2.智能照明系统 采用智能照明系统是提高能效的关键一步。这些系统可以根据店…

运维开发详解之指标收集

一、指标收集 运维开发中的指标收集是指收集、监控和分析系统运行的各种指标数据&#xff0c;用于评估系统的性能、健康状况和可靠性。这些指标可以包括服务器的 CPU 使用率、内存利用率、磁盘空间使用情况、网络流量等等。 指标收集的目的是为了及时发现系统存在的问题&…

【题解 | 分享】2023年十四届蓝桥杯国赛(Java B组)

互质 答案&#xff1a;640720414 参考&#xff1a; public class Main {static int mod 1000000007;public static void main(String[] args) {long sum power(2023, 2023);long p1 ((sum % mod) * power( 7, mod - 2)) % mod;long p2 ((sum % mod) * power( 17, mod -…

【Python爬虫--scrapy+selenium框架】超详细的Python爬虫scrapy+selenium框架学习笔记(保姆级别的,非常详细)

六&#xff0c;selenium 想要下载PDF或者md格式的笔记请点击以下链接获取 python爬虫学习笔记点击我获取 Scrapyselenium详细学习笔记点我获取 Python超详细的学习笔记共21万字点我获取 1&#xff0c;下载配置 ## 安装&#xff1a; pip install selenium## 它与其他库不同…

docker compose完成简单项目部署

1. 项目环境 centos7 docker mysql redis ruoyi项目 ruoyi项目链接&#xff1a;https://gitee.com/y_project/RuoYi-Vue.git 2. 进行项目前后端代码打包 后端打包&#xff1a; 修改mysql连接的相关配置文件 RuoYi-Vue/ruoyi-admin/src/main/resources/application-dru…

软件和系统集成项目确认测试报告的费用需要多少?

确认测试报告 软件和系统集成项目确认测试报告的费用因多种因素而异&#xff0c;包括项目的规模、复杂度、测试范围、测试周期等。第三方软件测试机构价格区间一般是几千到几万不等&#xff0c;还有些会根据建设费用的2-5%进行收费。 一般来说&#xff0c;软件和系统集成项目…

2024年5月架构试题

2024年5月份架构师考试真题完整版 截至2024-5-28 19:24:14已全部收录完成 共75道选择题&#xff0c;5道案例题&#xff0c;4道论文题。题目顺序不分先后。 全网最全的2024年5月份架构师考试真题回忆版&#xff0c;包含答案和解析。 选择题 计算机基础 操作系统调度算法 选先来先…

Linux基本命令的使用(cp mv)

一、cp命令-1 1、CP命令作用&#xff1a;复制一个源文件到目标文件&#xff08;夹&#xff09; 2、 语法&#xff1a;cp [选项] 源文件 目标文件&#xff08;夹&#xff09; ① 复制到文件夹下&#xff0c;则文件名保持不变 ② 复制到文件中&#xff0c;则文件名变更 二、cp命…

基于安卓的虫害识别软件设计--(1)模型训练与可视化

引言 简介&#xff1a;使用pytorch框架&#xff0c;从模型训练、模型部署完整地实现了一个基础的图像识别项目计算资源&#xff1a;使用的是Kaggle&#xff08;每周免费30h的GPU&#xff09; 1.创建名为“utils_1”的模块 模块中包含&#xff1a;训练和验证的加载器函数、训练…

Uniapp发布流程存档

发布成小程序 配置微信小程序的appid 配置小程序的域名 修改静态资源路径为线上路径 发布成H5 配置H5 发行 运行 发布成安卓 基础配置

JS-Lodash工具库

文档&#xff1a;Lodash Documentation orderBy函数&#xff1a;根据条件进行排序 注&#xff1a;第一个是要排序的数组&#xff0c;第二个是根据什么字段进行排序&#xff0c;第三个是排序的方式&#xff08;desc倒序&#xff09; 安装方式&#xff1a;Lodash npm i lodash…

Presto 从提交SQL到获取结果 源码详解(3)

物理执行计划 回到SqlQueryExecution.startExecution() &#xff0c;执行计划划分以后&#xff0c; // 初始化连接&#xff0c;获取Connect 元数据&#xff0c;添加会话&#xff0c;初始ConnectId metadata.beginQuery(getSession(), plan.getConnectors()); // 构建物理执行…

关于MD5

首先还是介绍一下关于md5的基本信息&#xff1a; MD5&#xff08;Message Digest Algorithm 5&#xff09;是一种常用的哈希函数&#xff0c;用于产生128位&#xff08;16字节&#xff09;的哈希值&#xff0c;通常以32个十六进制数字表示。MD5广泛用于计算文件或文本数据的校…

LeetCode-131 分割回文串

LeetCode-131 分割回文串 题目描述解题思路C 代码 题目描述 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串。返回 s 所有可能的分割方案。 示例 1&#xff1a; 输入&#xff1a;s “aab” 输出&#xff1a;[[“a”,“a”,“b”],…

Zynq学习笔记--AXI4-Stream 图像数据从仿真输出到图像文件

目录 1. 简介 2. 构建工程 2.1 Vivado 工程 2.2 TestBench 代码 2.3 关键代码分析 3. VPG Background Pattern ID (0x0020) Register 4. 总结 1. 简介 使用 SystemVerilog 将 AXI4-Stream 图像数据从仿真输出到图像文件 (PPM)。 用到的函数包括 $fopen、$fwrite 和 $f…

vmware esxi虚拟化数据迁移

1、启用esxi的ssh 登录esxi的web界面&#xff0c;选择主机-》操作——》服务——》启动ssh 2.xshell登录esxi 3、找到虚拟机所在目录 blog.csdnimg.cn/direct/d57372536a4145f2bcc1189d02cc7da8.png)#### 3在传输数据前需关闭防火墙服务 查看防火墙状态&#xff1a;esxcli …

Android MediaCodec 简明教程(九):使用 MediaCodec 解码到纹理,使用 OpenGL ES 进行处理,并编码为 MP4 文件

系列文章目录 Android MediaCodec 简明教程&#xff08;一&#xff09;&#xff1a;使用 MediaCodecList 查询 Codec 信息&#xff0c;并创建 MediaCodec 编解码器Android MediaCodec 简明教程&#xff08;二&#xff09;&#xff1a;使用 MediaCodecInfo.CodecCapabilities 查…

【传知代码】双深度学习模型实现结直肠癌检测(论文复现)

前言&#xff1a;在医学领域&#xff0c;科技的进步一直是改变人类生活的关键驱动力之一。随着深度学习技术的不断发展&#xff0c;其在医学影像诊断领域的应用正日益受到关注。结直肠癌是一种常见但危害极大的恶性肿瘤&#xff0c;在早期发现和及时治疗方面具有重要意义。然而…

【VSCode】快捷方式log去掉分号

文章目录 一、引入二、解决办法 一、引入 我们使用 log 快速生成的 console.log() 都是带分号的 但是我们的编程习惯都是不带分号&#xff0c;每次自动生成后还需要手动删掉分号&#xff0c;太麻烦了&#xff01; 那有没有办法能够生成的时候就不带分号呢&#xff1f;自然是有…