[SSM]MyBatisPlus高级

news2024/11/26 9:56:48

四、高级篇

4.1主键策略

  • 主键的作用就是唯一标识,我们可以通过这个唯一标识来定位到这条数据。
  • 对于表数据中的主键,我们可以自己设计生成规则,生成主键。但是在更多的场景中,没有特殊要求的话,我们每次自己手动生成的比较麻烦,我们可以借助框架提供好的主键生成策略来生成主键,这样比较方便。
  • 在MybatisPlus中提供了一个注解,是@TableId,该注解提供了各种的主键生成策略,我们可以通过使用该注解来对于新增的数据指定主键生成的策略。那么在以后新增数据的时候,数据就会按照我们指定的主键生成策略来生成对应的主键。

4.1.1AUTO策略

  • 该策略为跟随数据库表的主键递增策略,前提是数据库表的主键要设置为自增。
  • 实体类添加主键,指定主键生成策略。
//设置主键自增
@TableId(type = IdType.AUTO)
private Long id;
  • 插入数据
@Test
void primary() {
    User user = new User();
    user.setName("Mary");
    user.setAge(30);
    user.setEmail("mary@qq.com");

    userMapper.insert(user);
}

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=C%3A%5CUsers%5CAdministrator%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20230904171525148.png&pos_id=img-wn0ndijF-1694007802578)在这里插入图片描述

4.1.2INPUT策略

  • 该策略表示,必须由我们手动的插入id,否则无法添加数据。
  • 由于不使用AUTO了,所以将数据库中的自动递增去掉。
//手动设置主键值
@TableId(type = IdType.INPUT)
private Long id;
@Test
void primary() {
    User user = new User();
    user.setId(8L);
    user.setName("Mary");
    user.setAge(30);
    user.setEmail("mary@qq.com");

    userMapper.insert(user);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.1.3ASSIGN_ID策略

  • 如果我们将来一张表的数据量很大,我们需要进行分表。
  • 常见的分表策略有两种:
  1. 水平拆分

  • 水平拆分就是将一个大的表按照数据量进行拆分
  1. 垂直拆分

  • 垂直拆分就是将一个大的表按照字段进行拆分

  • 其实对于拆分后的数据,有三点需求,以水平拆分为例:

    • 之前的表的主键是有序的,拆分后还是有序的。
    • 虽然做了表的拆分,但是每条数据还需要保证主键的唯一性
    • 主键最好不要直接暴露数据的数量,这样容易被外界知道关键信息
  • 那就需要有一种算法,能够实现这三个需求,这个算法就是雪花算法。

  • 雪花算法是由一个64位的二进制组成的,最终就是一个Long类型的数值。主要分为四部分存储

    • 1位的符号位,固定值为0
    • 41位的时间戳
    • 10位的机器码,包含5位机器id和5位服务id
    • 12位的序列号

  • 使用雪花算法可以实现有序、唯一且不直接暴露排序的数字。
//使用雪花算法,默认为type = IdType.ASSIGN_ID,可省略
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@Test
void primary() {
    User user = new User();
    user.setName("Mary");
    user.setAge(30);
    user.setEmail("mary@qq.com");

    userMapper.insert(user);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 在插入后发现一个19位长度的id,该id就是雪花算法生成的id,这是二进制的十进制表示形式。

4.1.4NONE策略

//不指定主键生成策略
@TableId(type = IdType.NONE)
private Long id;
  • NONE策略表示不指定主键生成策略,当我们没有指定主键生成策略或者主键策略为NONE的时候,他跟随的是全局策略。
#主键生成策略全局配置(默认为assign_id)
mybatis-plus.global-config.db-config.id-type=assign_id
  • 全局配置中id-type是用于配置主键生成策略的,id-type默认值为IdType.ASSIGN_ID

4.1.5ASSIGN_UUID策略

  • UUID是全局唯一标识符,定义一个字符串主键,采用32位数字组成,编码采用16进制,定义了在时间和空间都完全唯一的系统信息。
  • UUID的编码规则:
    • 1~8位采用系统时间,在系统时间上精确到毫秒级保证时间上的唯一性
    • 9~16位采用底层的IP地址,在服务器集群中的唯一性
    • 17~24位采用当前对象的HashCode值,在一个内部对象上的唯一性
    • 25~32位采用调用方法的一个随机数,在一个对象内的毫秒级的唯一性
  • 通过以上4中策略可以保证唯一性,在系统中需要用到随机数的地方都可以考虑采用UUID算法。
  • 使用UUID需要将数据库表的字段类型改为varchar(50),将实体类的属性类型改为String,并指定主键生成策略。
//主键采用ASSIGN_UUID策略
@TableId(type = IdType.ASSIGN_UUID)
private String id;
  • 完成数据的添加
@Test
void primary() {
    User user = new User();
    user.setName("Mary");
    user.setAge(30);
    user.setEmail("mary@qq.com");

    userMapper.insert(user);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.2分页

  • 在MybatisPlus中的查询语句有两种实现方式
    • 通过MybatisPlus提供的方法来实现条件查询
    • 通过自定义SQL语句的方式来实现查询

4.2.1分页插件

  • 在大部分情况下,如果我们的SQL没有这么复杂,是可以直接通过MybatisPlus提供的方法来实现查询的,在这种情况下,我们可以通过配置分页插件来实现分页效果。
  • 分页的本质就是需要设置一个拦截器,通过拦截器拦截了SQL,通过在SQL语句的结尾添加limit关键字来实现分页的效果

1.通过配置类来指定一个具体的数据库的分页插件,自动生成分页语句

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

2.实现分页效果查询

@Test
void selectPage() {
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //指定分页对象,分页对象包含分页信息 IPage
    Page<User> userPage = new Page<>(2, 3);
    //执行查询
    userMapper.selectPage(userPage, lambdaQueryWrapper);
    //获取分页查询的信息
    System.out.println("当前页:" + userPage.getCurrent());
    System.out.println("每页显示条数:" + userPage.getSize());
    System.out.println("总页数:" + userPage.getPages());
    System.out.println("总条数:" + userPage.getTotal());
    System.out.println("分页数据:" + userPage.getRecords());
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.2.2自定义分页插件

  • 在某些场景下,我们需要自定义SQL语句来进行查询。

1.在UserMapper.xml映射配置文件中提供查询语句

<mapper namespace="com.hhb.mp02.mapper.UserMapper">
    <select id="selectByName" resultType="com.hhb.mp02.domain.User" parameterType="String">
        select * from t_user where username=#{name}
    </select>
</mapper>

2.在Mapper接口中提供对应的方法,方法中将Page对象作为参数传入

@Mapper
public interface UserMapper extends BaseMapper<User> {
    Page<User> selectByName(Page<User> page, String name);
}

3.实现分页查询效果

@Test
void selectPage2() {
    Page<User> userPage = new Page<>(1, 2);
    userMapper.selectByName(userPage,"Mary");
    System.out.println("当前页:" + userPage.getCurrent());
    System.out.println("每页显示条数:" + userPage.getSize());
    System.out.println("总页数:" + userPage.getPages());
    System.out.println("总条数:" + userPage.getTotal());
    System.out.println("分页数据:" + userPage.getRecords());
}

4.3ActiveRecord模式

1.实体类继承Model

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User extends Model<User> {
    private Long id;
    @TableField("username")
    private String name;
    private Integer age;
    private String email;
    @TableField("`desc`")
    private String desc;
}
  • 我们可以看到,Model类中提供了一些增删改查的方法,这样的话我们就可以直接使用实体类对象调用这些增删改查方法了,简化了操作的语法,但是他的底层依然是需要UserMapper的,所以持久化层接口并不能省略。

2.测试ActiveRecord模式的增删改查

@SpringBootTest
public class ActiveRecordTest {

    //添加操作
    @Test
    void activeRecordAdd() {
        User user = new User();
        user.setName("张三");
        user.setEmail("zhang@qq.com");
        user.setAge(33);
        user.insert();
    }

    //删除操作
    @Test
    void activeRecordDelete() {
        User user = new User();
        user.setId(9L);
        user.deleteById();
    }

    //修改操作
    @Test
    void activeRecordUpdate() {
        User user = new User();
        user.setId(10L);
        user.setName("李四");
        user.setAge(26);
        user.setEmail("lisi@qq.com");
        user.updateById();
    }

    //查询操作
    @Test
    void activeRecordSelect() {
        User user = new User();
        user.selectAll();
    }
}

4.4SimpleQuery工具类

  • SimpleQuery可以对selectList查询后的结构用Stream流进行一些封装,使其可以返回一些指定结果,简洁了API的调用。

4.4.1list

基于字段封装集合

@Test
void testList() {
    List<Long> list = SimpleQuery.list(new LambdaQueryWrapper<User>().eq(User::getName, "Mary"), User::getId);
    System.out.println(list);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于封装后的字段进行lambda操作

@Test
void testList2() {
    List<String> list = SimpleQuery.list(new LambdaQueryWrapper<User>().eq(User::getName, "Mary"), User::getName, new Consumer<User>() {
        @Override
        public void accept(User user) {
            //map转化
           Optional.of(user.getName()).map(String::toLowerCase).ifPresent(user::setName);
        }
    });
    System.out.println(list);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.4.2map

将所有的对象以id=实体类的方式封装为Map集合

@Test
void testMap() {
    Map<Long, User> map = SimpleQuery.keyMap(new LambdaQueryWrapper<User>(), User::getId);
    System.out.println(map);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将单个对象以id=实体类的方式封装为Map集合

@Test
void testMap2() {
    Map<Long, User> map = SimpleQuery.keyMap(new LambdaQueryWrapper<User>().eq(User::getId, 1L), User::getId);
    System.out.println(map);
}

由id和name组成的map

@Test
void testMap3() {
    Map<Long, String> map = SimpleQuery.map(new LambdaQueryWrapper<User>(), User::getId, User::getName);
    System.out.println(map);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.4.3Group

@Test
    void testGroup() {
        Map<String, List<User>> maps = SimpleQuery.group(new LambdaQueryWrapper<User>(), User::getName);
        for (Map.Entry<String, List<User>> stringListEntry : maps.entrySet()) {
            System.out.println(stringListEntry);
        }
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

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

相关文章

第 2 章 线性表(线性表的动态分配顺序存储结构实现)

1. 背景说明 线性表(linear Iist)是最常用且最简单的一种数据结构。简言之&#xff0c;一个线性表是 n 个数据元素的有限序列。 至于每个数据元素的具体含义&#xff0c;在不同的情况下各不相同&#xff0c;它可以是一个数或一个符号&#xff0c;也可以是一页书&#xff0c;甚…

千粉福利——— ubuntu安装

&#xff08;一&#xff09;配置虚拟机&#xff0c;首先打开虚拟机 点击创建新的虚拟机或者左上角文件->新建虚拟机&#xff0c;或者使用快捷键CtrlN,选择自定义安装 选择虚拟机就硬件兼容性&#xff0c;默认点击下一步就好 安装客户机操作系统&#xff1a;选择稍后安装操作…

tensorflow QAT

tensorflow qat https://www.wpgdadatong.com/tw/blog/detail/70672 在边缘运算的重点技术之中&#xff0c;除了简化复杂的模块构架&#xff0c;来简化参数量以提高运算速度的这项模块轻量化网络构架技术之外。另一项技术就是各家神经网络框架&#xff08;TensorFlow、Pytorc…

Day7:浅谈useEffect

「目标」: 持续输出&#xff01;每日分享关于web前端常见知识、面试题、性能优化、新技术等方面的内容。 Day7-今日话题 useEffect 是 React 中一个非常重要的 Hook&#xff0c;用于处理副作用和订阅外部数据源的变化。它可以在函数式组件中执行各种操作&#xff0c;例如数据获…

小程序如何上传微信聊天记录的文件

wx.chooseMessageFile({count: 10,type: image,success (res) {// tempFilePath可以作为img标签的src属性显示图片const tempFilePaths res.tempFiles} })参数说明 回调函数说明

数据库实现学生管理系统

1.QT将数据库分为三个层次&#xff1a; 1> 数据库驱动层&#xff1a;QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorBase、QSqlDriverPlugin 2> sql接口层&#xff1a;QSqlDatabase、QSqlQuery、QSqlRecord、QSqlError 3> 用户接口层&#xff1a;提供一些模型QSql…

开眼“观天”,从墨迹天气服贸会之旅看气象服务新未来

今年夏天&#xff0c;天气焦人。先是高温早早上线&#xff0c;然后台风来势汹汹&#xff0c;北京高温、河北暴雨&#xff0c;杜苏芮、苏拉、海葵轮番“奔袭”&#xff0c;极端气象事件频繁登上热搜&#xff0c;其险象环生的过程&#xff0c;让大众对气候问题的关注度节节走高。…

架构师 软件测试

架构师 软件测试 目录概述需求&#xff1a; 设计思路实现思路分析1.软件测试方法 软件测试工具 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for c…

cudnn-windows-x86_64-8.6.0.163_cuda11-archive 下载

网址不太好访问的话,请从下面我提供的分享下载 Download cuDNN v8.6.0 (October 3rd, 2022), for CUDA 11.x 此资源适配 cuda11.x 将bin和include文件夹里的文件&#xff0c;分别复制到C盘安装CUDA目录的对应文件夹里 安装cuda时自动设置了 CUDA_PATH_V11_8 及path C:\Progra…

1123. 最深叶节点的最近公共祖先

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;递归 写在最后 Tag 【递归】【最近公共祖先】【二叉树】 题目来源 1123. 最深叶节点的最近公共祖先&#xff0c;865. 具有所有最深节点的最小子树 此二题系重复的题目。 题目解读 题目意思很明确&#xff0c;找出二叉…

String类的常用方法(Java)

目录 一、字符串构造二、String对象的比较1、比较是否引用同一个对象2、boolean equals(Object anObject) 方法&#xff1a;按照字典序比较3、int compareTo(String s) 方法: 按照字典序进行比较4、int compareToIgnoreCase(String str) 方法&#xff1a;与compareTo方式相同&a…

SpringMVC相对路径和绝对路径

1.相对地址与绝对地址定义 在jsp&#xff0c;html中使用的地址&#xff0c;都是在前端页面中的地址&#xff0c;都是相对地址 地址分类&#xff1a;&#xff08;1&#xff09;&#xff0c;绝对地址&#xff0c;带有协议名称的是绝对地址&#xff0c;http://www.baidu.com&…

c语言练习41:深入理解字符串函数strlen strcpy strcat

深入理解字符串函数strlen strcpy strcat 模拟实现&#xff1a;”strlen strcpy strcat strlen strcat: #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<assert.h> strlen 1.通过指针移动模拟 //int my_strlen(char* str) { // size_t c…

Unity之创建第一个游戏

一 Unity环境配置 1.1 Untity资源官网下载&#xff1a;https://unity.cn/releases 1.2 Unity Hub集成环境&#xff0c;包含工具和项目的管理 1.3 Unity Editor编辑器 1.4 Visual Studio 2022脚本编辑器 1.5 AndroidSKD&#xff0c;JDK&#xff0c;NDK工具&#xff0c;用于and…

Python之写文件操作(二十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

长风破浪会有时,直挂云帆济沧海!(工作室年会总结)

前言 我也是有段时间没写过总结性的博客了。最近是很忙的&#xff0c;尤其是年会那两天&#xff0c;我甚至可以说这是我这辈子目前最忙的两天。但这段经历还是很值得我记录下来的&#xff0c;也是给后面有需要的人提供的一些建议。我个人也是第一次筹办这种大型些的活动&#x…

SpringBoot_第六章(知识点总结)

目录 1&#xff1a;拦截器(Interceptor) 1.1&#xff1a;拦截器代码实现 1.2&#xff1a;拦截器源码分析和流程总结 2&#xff1a;过滤器(Filter)、自定义(Servlet)、监听器(Listener) 3&#xff1a;文件上传 3.1&#xff1a;文件上传代码实现 3.2&#xff1a;文件上传源…

部署Redis集群

文章目录 部署Redis集群1. 准备集群主机2. 启用集群功能3. 配置管理主机并创建集群3.1 配置管理主机 192.168.88.573.2 创建集群创建集群命令创建集群失败解决办法 3.3 查看集群信息查看集群统计信息查看集群详细信息 4. **测试集群及集群工作原理**4.1. 访问集群存取数据4.2 *…

Jmeter进阶使用指南-使用参数化

Apache JMeter是一个广泛使用的开源负载和性能测试工具。在进行性能测试时&#xff0c;我们经常需要模拟不同的用户行为和数据&#xff0c;这时候&#xff0c;参数化就显得尤为重要。此文主要介绍如何在JMeter中使用参数化。 什么是参数化&#xff1f; 参数化是一种将静态值替…

OpenCV之ellipse函数

ellipse函数用来在图片中绘制椭圆、扇形&#xff0c;有两个重载函数。 函数原型1&#xff1a; void cv::ellipse( InputOutputArray img,Point center,Size axes,double angle,double startAngle,double …