Mybatis扩展

 1. Myabtis注解开发

​    这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper映射文件了。我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作。

 1.1 常见注解

  @Insert:实现新增
  @Update:实现更新
  @Delete:实现删除
  @Select:实现查询
  @Result:实现结果集封装
  @Results:可以与@Result 一起使用,封装多个结果集
  @One:实现一对一结果集封装
  @Many:实现一对多结果集封装

​    使用注解开发 可以省略编写mapper的xml映射文件,直接在dao层的接口方法上面使用注解执行sql ,因为省略了映射文件,所以要把接口直接配置在核心配置文件的mapper标签中进行绑定

 1.2 核心配置文件

扫描使用注解的接口

<mappers><!--扫描使用注解的接口--><mapper class="com.demo.mapper.IUserMapper"></mapper>
</mappers>

或者指定扫描包含映射关系的接口所在的包也可以

<mappers><!--扫描使用注解的接口所在的包--><package name="com.demo.mapper"></package>
</mappers>

 2. 单表的操作

​    只需要在方法上加入对应操作的注解 参数中写要执行的sql即可

 查询全部用户 

public interface IUserMapper {@Select(" select * from user")List<User> findAll();}


 删除id为1的用户

 @Delete("delete from user where id = #{id}")int deleteUserById(int id);

 修改id为2的用户姓名

 @Update("update user set username = #{username} where id = #{id}")int updateUserById(@Param("username") String username, @Param("id") int id);

 添加一个用户

@Insert("insert into user values(null,#{username},#{password},#{birthday})")
int insertUser(User user);


 3. 多表的操作

 3.1 一对一查询

​    使用订单表和用户表 实现查询订单以及所属的用户信息

1. 创建实体类

2. 创建Mapper接口

 public interface IOrderMapper {List<Orders> findAllOrders();}

 方法上加入注解 

 public interface IUserMapper {//根据ID查询用户@Select("select * from user where id = #{id}")User findUserById(int id);}
 //查询全部订单@Select("select * from orders")@Results({    //id = true,代表是主键@Result(id = true, property = "id", column = "id"),@Result(property = "ordertime", column = "ordertime"),@Result(property = "total", column = "total"),@Result(property = "uid", column = "uid"),@Result(property = "user", column = "uid",javaType = User.class,one = @One(select = "com.demo.mapper.IUserMapper.findUserById")//与用户接口中的方法关联)})List<Orders> findAllOrder();

 测试结果

  在单元测试中 调用查询全部订单的方法 查看结果 查看执行的sql语句

 //查询全部订单信息 包含用户@Testpublic void findAllOrders(){List<Orders> ordersList = mapper.findAllOrder();//遍历结果for (Orders orders : ordersList) {System.out.println(orders);}}

 3.2 一对多查询

​    使用订单表和用户表 实现查询用户以及关联的订单列表

1. 创建实体类

2. 创建Mapper接口
 

 public interface UserMapper {//查询全部用户 并且 查询出每个用户的订单@Select("select * from user")@Results({@Result(id = true,property = "id",column = "id"),@Result(property = "username",column = "username"),@Result(property = "password",column = "password"),@Result(property = "birthday",column = "birthday"),@Result(property = "ordersList",column = "id",javaType = List.class,many = @Many(select = "com.zrrd.mapper.OrderMapper.findOrderByUid"))})List<User> findAllUser();}
 //根据uid查询订单  订单接口中@Select("select * from orders where uid = #{uid}")List<Orders> findOrderByUid(int uid);


 注解方式实现多表查询
         使用@select注解 执行执行一次查询的sql
         使用@Results来进行结果映射 
         一对一:
                 javaType = 对象.class
                 one = @One(select = "指向一个新的查询方法的全路径")
         一对多:
                 javaType = List.class
                 many = @Many(select = "指向一个新的查询方法的全路径")

执行流程:

​        其实就是将Sql拆分 执行多次来完成结果映射 

​如查询全部员工 以及 所属部门

1. 先查询全部员工
2. 将查询到的每个员工的did 传入到指向的查询中进行查询

3.3 多对多查询

​    课堂案例

​    多对多的本质 就是双向的一对多查询

​    使用学生表和课程表 使用注解的方式 完成需求:

​    需求:

- 查询全部学生 以及学生学习的课程
- 查询全部课程 以及课程关联的学生

4. Mybatis的延迟加载策略

4.1 什么是延迟加载

​    通过前面的学习,我们已经掌握了 Mybatis 中一对一,一对多,多对多关系的配置及实现,可以实现对象的关联查询。实际开发过程中很多时候我们并不需要总是在加载用户信息时就一定要加载他的账户信息。此时就是我们所说的延迟加载。

​    延迟加载:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.

​    好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。【提高了数据库性能 单表操作】

​    坏处:因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。

 总结
         什么是延迟加载:在真正使用数据时才发起查询,不用的时候不查询。按需加载(懒加载)
         什么是立即加载:不管用不用,只要一调用方法,马上发起查询。
         使用场景: 在对应的三种表关系中:一对多,一对一,多对多
                            一对多,多对多:通常情况下我们都是采用延迟加载。
                            一对一:通常情况下我们都是采用立即加载。

4.2 实现延迟加载

 property:表示对象中的属性
 javaType:属性的类型
 column:指定按照那一列的值再去查询
 select:指定按照哪一个查询去查询 写法:接口的全类名 + 方法名。

4.2.1 全局实现

​    全局配置

 <!--配置--><settings><!--开启懒加载--><setting name="lazyLoadingEnabled" value="true"/><!--关闭立即加载 按需加载--><setting name="aggressiveLazyLoading" value="false"/></settings>

 注意:
    ​    全局配置设置后 代表所有的加载 都设置为延迟加载
    ​    局部设置 优先级高于全局设置
    ​    在核心配置文件中要遵循mybatis的标签顺序 否则报错

4.2.2 局部实现

​    查询订单以及订单所属的用户

​    只要在接口方法中 加入一个设置延迟加载

fetchType = FetchType.LAZ 

 @Select("select * from user")@Results({@Result(id = true,property = "id",column = "id"),@Result(property = "username",column = "username"),@Result(property = "password",column = "password"),@Result(property = "birthday",column = "birthday"),@Result(property = "ordersList",column = "id",javaType = List.class,many = @Many(select = "com.zrrd.mapper.OrderMapper.findOrderByUid",fetchType = FetchType.LAZY))})List<User> findAllUser();

5. Mybatis中的缓存

5.1 什么是缓存

​    缓存这个概念其实就是在查询一次的时候 将结果存下来,下次直接可以获取,避免直接访问数据库,造成数据库压力过大。

5.2 为什么要使用缓存

​    像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。

​    Mybatis 中缓存分为一级缓存,二级缓存。

​    缓存的使用场景

1. 适用缓存
     经常使用
     不经常发生改变
     数据的正确与否对最终结果影响不大的
     如 省份信息 部门信息 专业信息
2. 不适用缓存
     经常改变的是数据
     数据的正确与否对最终结果影响很大的
     例如:商品的库存,银行的汇率,股市的牌价

5.3 一级缓存

​    一级缓存 也叫本地缓存,它指的是Mybatis中SqlSession对象的缓存,一级缓存是一直开启的; 

​    与数据库同一次会话期间查询到的数据会放在本地缓存中。以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库;

​    当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用。

​    当SqlSession对象消失时,mybatis的一级缓存也就消失了。

​    一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。

一级缓存失效情况

1. sqlSession不同。
2. sqlSession相同,查询条件不同.(当前一级缓存中还没有这个数据)
3. sqlSession相同,两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响)
4. sqlSession相同,手动清除了一级缓存(缓存清空)  openSession.clearCache();

5.4 二级缓存

     二级缓存也叫全局缓存 基于namespace级别的缓存:一个namespace对应一个二级缓存。

​    工作机制:

1. 一个会话(SqlSession),查询一条数据,这个数据就会被放在当前会话的一级缓存中;
2. 如果会话关闭(close);一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;
3. 不同namespace查出的数据会放在自己对应的缓存中(map)

​         使用步骤:

1. 让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
2. 让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
3. 让当前的操作支持二级缓存(在select标签中配置)默认就是支持的
4. 让封装数据的实体类实现Serializable接口

<settings>
<!-- 开启二级缓存的支持 -->
<setting name="cacheEnabled" value="true"/>
</settings>
@CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存
public interface IUserDao {}

​    因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为false 代表不开启二级缓存

二级缓存的注意事项:
  ​    当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这样就可以使用序列化方式来保存对象。

注解方式实现:

maybatis基于注解的二级缓存的步骤

1. 在 SqlMapConfig 中开启二级缓存支持
2. 在持久层接口中使用注解配置二级缓存
3. 实体类实现implements Serializable接口

5.5 一级缓存和二级缓存的区别

  一级缓存:也称为本地缓存,是MyBatis中SqlSession对象的一部分,生命周期与SqlSession相同。一级缓存是默认开启的,无法关闭。
  二级缓存:是Mapper级别的缓存,同一个namespace共享,生命周期与SqlSessionFactory相同,因此跨多个SqlSession。二级缓存需要手动开启和配置。
  一级缓存不能跨SqlSession使用,而二级缓存可以。
  一级缓存不可以关闭,二级缓存可以手动关闭(默认也是开启的)


  其实Mybatis中的缓存 我们基本上不用 因为我们之后会学习更好的框架来做缓存 Redis

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

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

相关文章

Docker镜像的创建和Dockerfile

一. Docker 镜像的创建&#xff1a; 1.基于现有镜像创建: &#xff08;1&#xff09;首先启动一个镜像&#xff0c;在容器里做修改docker run -it --name web3 centos:7 /bin/bash #启动容器​yum install -y epel-release #安装epel源yum install -y nginx #安…

物联网小demo

机智云生成代码 具体参考之前的文章 初始化 ADC用来使用光敏电阻 连续采样开启 采样的周期调高 定时器 定时器1用来实现延时 为了只用温湿度模块DHT11 定时器4用来和51进行交互 实现定时的发送和检测心跳信号 IIC 用来使用oled屏幕 USART 串口1和串口2是机智云自己…

ROS是什么

一、ROS通信机制--松耦合分布式通信 1、核心概念 ①节点&#xff08;node&#xff09;---软件模块 ②节点管理器&#xff08;ROS master&#xff09;---控制中心&#xff0c;提供参数管理 ③话题&#xff08;topic&#xff09;---异步通信机制&#xff0c;传输消息&#xf…

【设计模式】13、template 模板模式

文章目录 十三、template 模板模式13.1 ppl13.1.1 目录层级13.1.2 ppl_test.go13.1.3 ppl.go13.1.4 llm_ppl.go13.1.5 ocr_ppl.go 十三、template 模板模式 https://refactoringguru.cn/design-patterns/template-method 如果是一套标准流程, 但有多种实现, 可以用 template …

Leetcode 3132. Find the Integer Added to Array II

Leetcode 3132. Find the Integer Added to Array II 1. 解题思路2. 代码实现 题目链接&#xff1a;3132. Find the Integer Added to Array II 1. 解题思路 这一题由于是统一增加了一个位移&#xff0c;然后再删除了两个元素&#xff0c;因此我们将两个数组进行排序&#x…

MySQL入门学习-使用数据库.创建和删除数据库

MySQL是一种流行的关系型数据库管理系统&#xff0c;可以用于存储和管理大量数据。在MySQL中&#xff0c;可以通过创建和删除数据库来组织和管理数据。 一、关于MySQL中创建和删除数据库的概述&#xff1a; 1. 创建数据库&#xff1a; 在MySQL中&#xff0c;可以使用CREATE …

Py脚本_文件分类

最近发现通过Edge和chrome或者其他浏览器下载的文件都存放在一个地方就很繁琐&#xff0c;于是翻找以前的脚本来归纳这些文件&#xff0c;虽然有IDM下载独有会自动分类&#xff0c;但是相信很多同学都在一个文件里找文件&#xff0c;这次就写个Py脚本来实现这个功能。 # -*- c…

XML:基础

一、语法 基本结构&#xff1a; 实例一&#xff1a; <?xml version"1.0" encoding"ISO-8859-1"?> <note data"2008/08/08"> <to>George</to> <from>John</from> <heading>Reminder</heading&…

深入理解Java中的Lambda表达式

Java 8引入的Lambda表达式&#xff08;或称匿名函数&#xff09;是一种简洁优雅的语法&#xff0c;极大简化了开发者编写代码的方式。它可以作为参数传递给方法或赋值给变量&#xff0c;适用于简化代码的场景。本文将详细介绍Lambda表达式的使用&#xff0c;并结合代码实例进行…

C语言 void 指针就是空指针吗?它有什么作⽤?

一、问题 这是⼀个在⾯试时很容易出现的问题&#xff0c;但是也是很多⼈混淆的问题&#xff0c;这个问题如何回答&#xff1f; 二、解答 void 指针⼀般称为通⽤指针&#xff0c;要与空指针严格区分。void 指针⽤于指向⼀个不属于任 何类型的对象&#xff0c;所以 void 指针称为…

k8s集群安装

目录 部署步骤概览 1、基础环境部署 2、docker环境部署 3、配置k8s集群 4、集群初始化 5、安装dashboard软件 写在前面&#xff1a;本文安装单点master多node的k8s集群&#xff0c;主要用于k8s学习或k8s环境测试&#xff1b;部署的是1.23版本&#xff0c;在1.24版本起&am…

什么是TCP粘包?

TCP粘包 数据的接收和发送是无关的&#xff0c;read()/recv() 函数不管数据发送了多少次&#xff0c;都会尽可能多的接收数据。也就是说&#xff0c;read()/recv() 和 write()/send() 的执行次数可能不同。 举个栗子 write()/send() 重复执行三次&#xff0c;每次都发送字符…

stm32单片机开发四、USART“串口通信“

串口的空闲状态时高电平&#xff0c;起始位是低电平&#xff0c;来打破空闲状态的高电平 必须要有停止位&#xff0c;停止位一般为一位高电平 串口常说的数据为8N1&#xff0c;其实就是8个数据位&#xff08;固定的&#xff09;&#xff0c;N就是none&#xff0c;也就是0个校验…

【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解

一、计算机网络的发展背景 1、网络的定义 网络是指将多个计算机或设备通过通信线路、传输协议和网络设备连接起来&#xff0c;形成一个相互通信和共享资源的系统。 &#xff08;1&#xff09; 独立模式 独立模式 &#xff1a; 计算机之间相互独立。 &#xff08;2&#xff09;…

数据结构——二叉树链式结构的实现(下)

二叉树找值找为x的结点 找值不简单吗&#xff1f;轻轻松松拿捏&#xff0c;大部分同学都会写出这样的代码 但这种代码有问题&#xff0c;因为没有把查找结果返回给上一层&#xff0c;没有用返回值接收。 当找到3时返回给了上一层&#xff0c;但并没有用返回值接收&#xff0c;…

游戏名台词大赏

文章目录 原神&#xff08;圈内&#xff09; 崩坏&#xff1a;星穹铁道&#xff08;圈内&#xff09; 崩坏3&#xff08;圈内&#xff09; 原神 只要不失去你的崇高&#xff0c;整个世界都会为你敞开。 总会有地上的生灵&#xff0c;敢于直面雷霆的威光。 谁也没有见过风&…

Rust 生命周期浅谈

1. 简述 Rust 中的每一个引用都有其 生命周期&#xff08;lifetime&#xff09;&#xff0c;也就是引用保持有效的作用域。大部分时候生命周期是隐含并可以推断的&#xff0c;正如大部分时候类型也是可以推断的一样。类似于当因为有多种可能类型的时候必须注明类型&#xff0c;…

Arxml文件解析02- 自动驾驶Radar服务radar_svc.arxml

<AUTOSAR xmlns="http://autosar.org/schema/r4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://autosar.org/schema/r4.0 AUTOSAR_00045.xsd

大数据面试题(九):Hive的高频面试考点(值得收藏)

文章目录 Hive的高频面试考点 一、Hive中两个大表实现join的操作,简单描述一下

书接上文,助力智能化诊断高质提效,基于轻量级CNN模型MobileNet开发构建人体手骨X光骨骼骨龄分析识别系统

骨龄是骨骼年龄的简称&#xff0c;需要借助于骨骼在X光摄像中的特定图像来确定。通常要拍摄左手手腕部位的X光片&#xff0c;医生通过X光片观察来确定骨龄。这在临床上是一件非常消耗精力和时间的一项放射临床工作。写一个骨龄可能要10多分钟去完成。如果一天要写几十个骨龄&am…