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

文章目录

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

延迟加载

概述

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

  • 延迟加载中返回值要选择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());

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

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

相关文章

【QEMU 中文文档】0. Hello QEMU!

最近&#xff0c;我开始研究QEMU这个超强的虚拟化和仿真工具。不得不说&#xff0c;读英文文档真是让我头大 &#x1f974;。于是我灵机一动&#xff0c;为什么不做个QEMU的中文文档呢&#xff1f;毕竟&#xff0c;现在有了ChatGPT的强大翻译能力&#xff0c;我决定尝试一下&am…

分形之科赫雪花

前言 分形是一种具有自相似性的几何图形或数学对象。它的特点是无论在任何放大或缩小的尺度下,都能够看到与整体相似的图形。分形的形状可以非常复杂,常常具有分支、重复的图案,以及细节层次丰富的结构。 分形在自然界中广泛存在,如云朵、树枝、山脉、海岸线等,它们都展…

铁塔基站用能监控能效解决方案

截至2023年10月&#xff0c;我国5G基站总数达321.5万个&#xff0c;占全国通信基站总数的28.1%。然而&#xff0c;随着5G基站数量的快速增长&#xff0c;基站的能耗问题也逐渐日益凸显&#xff0c;基站的用电给运营商带来了巨大的电费开支压力&#xff0c;降低5G基站的能耗成为…

一图了解【电子面拦截】接口

【电子面拦截】又可以成为快递拦截 商品还在运输途中&#xff0c;买家申请仅退款、想修改地址怎么办&#xff1f; 百递云API开放平台最新推出「电子面单拦截」接口&#xff0c;提供三种拦截类型&#xff0c;助力快速拦截处理在途包裹。 下图带您了解&#x1f447;

Leecode---栈---每日温度 / 最小栈及栈和队列的相互实现

栈&#xff1a;先入后出&#xff1b;队列&#xff1a;先入先出 一、每日温度 Leecode—739题目&#xff1a; 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温…

2.6 Docker部署多个前端项目

2.6 Docker部署多个项目 三. 部署前端项目 1.将前端项目打包到同一目录下&#xff08;tcm-ui&#xff09; 2. 部署nginx容器 docker run --namenginx -p 9090:9090 -p 9091:9091 -d nginx3. 复制nginx.conf文件到主机目录 docker cp nginx:/etc/nginx/nginx.conf /root/ja…

大模型之路,从菜鸟到模型大师只需要一步

前言&#xff1a; 在这个数据爆炸的时代&#xff0c;大模型技术正以前所未有的速度发展。从自然语言处理到计算机视觉&#xff0c;从智能推荐到自动驾驶&#xff0c;大模型正逐渐渗透到我们生活的方方面面。那么&#xff0c;如何从菜鸟成长为模型大师呢&#xff1f;本文将为你…

【JMeter接口自动化】第8讲 Fiddler抓包Jmeter

1&#xff09;配置好Fiddler 设置Fiddler-Tools-Options-HTTPS 设置Fiddler-Tools-Options-Connections&#xff0c;设置端口为8888 2&#xff09;查看IP 在CMD中输入ipconfig 查看IP地址 3&#xff09;配置Jmeter Http请求——基本&#xff0c;设置Http请求&#xff0c;使用…

英语学习笔记30——What must I do?

What must I do? 我应该做点啥&#xff1f; 词汇 Vocabulary empty v. 倒空&#xff0c;变空 a. 空的 搭配&#xff1a;empty bottle 空瓶子    empty room 空屋子 例句&#xff1a;教室里空无一人。    The classroom is empty.    我有一个空瓶子。    I have…

智能家居元宇宙三维互动展示在线创作平台

卫浴行业正迎来一场全新的革命——卫浴元宇宙3D展厅搭建编辑器。它基于互联网信息技术、3D线上展示与VR虚拟现实技术&#xff0c;为您打造一个沉浸式的3D虚拟空间&#xff0c;让您的卫浴产品在线上展示中焕发出前所未有的光彩。 在这个卫浴元宇宙中&#xff0c;您可以随心所欲地…

大模型时代的具身智能系列专题(六)

UCSD 王小龙组 王小龙是UCSD电子与计算机工程系的助理教授。他曾在加州大学伯克利分校与Alexei Efros和Trevor Darrell一起担任博士后研究员&#xff0c;在CMU RI获得了机器人学博士学位&#xff0c;师从Abhinav Gupta。他的研究重点是通过视频和物理机器人交互数据来学习3D和…

vulnhub靶场之FunBox-9

一.环境搭建 1.靶场描述 Its a box for beginners, but not easy. Gather careful !!! Hint: Dont waste your time ! Every BruteForce-Attack at all ports can be stopped after 1500 trys per account. Enjoy the game and WYSIWYG ! This works better with VirtualBox…

数据在内存中的存储<C语言>

导言 在计算机中不同类型的数据在计算机内部存储形式各不相同&#xff0c;弄懂各种数据在计算机内部存储形式是有必要的&#xff0c;C语言的学习不能浮于表面&#xff0c;更要锻炼我们的“内功”&#xff0c;将来在写程序的时候遇见各种稀奇古怪的bug时&#xff0c;也便能迎刃而…

Redis之持久化、集群

1. Redis持久化 Redis为什么需要持久化?因为Redis的数据我们都知道是存放在内存中的&#xff0c;那么每次关闭或者机器断电&#xff0c;我们的数据旧丢失了。 因此&#xff0c;Redis如果想要被别人使用&#xff0c;这个问题就需要解决&#xff0c;怎么解决呢?就是说我们的数…

深度解析:从概念到变革——Transformer大模型的前世今生以及大模型预备知识讲解[知存科技]

深度解析&#xff1a;从概念到变革——Transformer大模型的前世今生 点击&#xff1a;知存科技相关课程推荐 知存科技是全球领先的存内计算芯片企业。针对AI应用场景&#xff0c;在全球率先商业化量产基于存内计算技术的神经网络芯片。凭借颠覆性的技术创新&#xff0c;知存科…

小米投屏怎么投?收好这3个投屏指南!(2024新)

近年来&#xff0c;小米凭借过硬的品质和合理的价格成为手机市场的一股强劲力量。随着其销量的上升&#xff0c;人们可以通过多种方式使用它来获得乐趣和便利。比如小米MIUI 11自带一个“光环”——Miracast&#xff0c;可以让用户在电脑上控制小米/红米/小米&#xff0c;获得更…

conda创建虚拟环境并激活

1 conda activate base 2 conda creat -n aaa python** 3 conda activate aaa 4 interpreter里面去选择刚搞好的编译器 ...../conda.exe

软考随记(二)

I/O系统的5种不同的工作方式&#xff1a; 程序控制方式&#xff1a; 无条件查询&#xff1a;I/O端口总是准备好接受主机的输出数据&#xff0c;或是总是准备好向主机输入数据&#xff0c;而CPU在需要时随时直接利用I/O指令访问相应的I/O端口&#xff0c;实现与外设的数据交换 …

9.Halcon3D点云力矩求解-平面拟合用法

1.实现效果 我们在使用3d相机对产品进行扫描生成点云的时候,由于安装问题,所以我们不可能保证每次产品扫描出来都在坐标系中位置和姿态非常标准。 上述算法描述的就是在某一个维度或者某几个维度上将点云数据和坐标系对齐; 至于怎么对齐,如何实现就是今天的内容。 本人能…

【UE5.1 角色练习】10-物体抬升、抛出技能 - part2

目录 前言 效果 步骤 一、让物体缓慢的飞向手掌 二、向着鼠标方向发射物体 前言 在上一篇&#xff08;【UE5.1 角色练习】08-物体抬升、抛出技能 - part1&#xff09;的基础上继续完成角色将物体吸向手掌&#xff0c;然后通过鼠标点击的方向来发射物体的功能。 效果 步骤…