草庐IT

02-MyBatis-Plus

universe-mg 2023-04-19 原文

MyBatis-Plus实现数据库crud操作

1.mp是什么

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

2.创建并初始化数据库

快速开始 | MyBatis-Plus (baomidou.com)

  1. 创建数据库,创建数据库表

  2. 创建工程 springboot

    可以使用 Spring Initializer (opens new window)快速初始化一个 Spring Boot 工程

  3. 引入依赖

            <!-- mybatis-plus -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.5.2</version>
            </dependency>
    
            <!--mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.30</version>
            </dependency>
    
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
    
  4. 配置数据库信息

    spring:
      datasource:
        username: root
        password: 123456
        url: "jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8"
        driver-class-name: com.mysql.cj.jdbc.Driver
    
  5. 编写实体类

    User

    package com.mj.demomptest.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }
    
  6. mapper接口

    UserMapper

    package com.mj.demomptest.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.mj.demomptest.entity.User;
    
    public interface UserMapper extends BaseMapper<User> {
    
    }
    
  7. 包扫描

    package com.mj.demomptest;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    @MapperScan("com.mj.demomptest.mapper")
    /*
     mapper 是一个interface接口动态生成实现类对象
     动态生成对象默认找不到
     @MapperScan 才能找到动态生成的对象
     */
    public class DemomptestApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemomptestApplication.class, args);
        }
    
    }
    
  8. 测试

    package com.mj.demomptest;
    
    import com.mj.demomptest.entity.User;
    import com.mj.demomptest.mapper.UserMapper;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.List;
    
    @SpringBootTest
    class DemomptestApplicationTests {
    
        @Autowired
        private UserMapper userMapper;
    
    
        @Test
        public void findAll() {
            System.out.println(userMapper.selectList(null));
    
        }
    
    }
    
  9. 查看sql输出日志

    #mybatis日志
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    

    控制台输出

3.mp实现添加 修改

添加

    @Test
    public void testAdd(){
        User user = new User();
        user.setName("Lucy");
        user.setAge(20);
        user.setEmail("09876@qq.com");
        //返回影响行数
        int insert = userMapper.insert(user);
        System.out.println(insert);


    }

修改

    //修改
    @Test
    public void testUpdate(){

        User user = new User();
        user.setId(1585808430935887874L);
        user.setName("Mary");
        int count = userMapper.updateById(user);
        System.out.println(count);
    }

4.组件策略

1、插入操作

//添加
@Test
public void testAdd() {
    User user = new User();
    user.setName("lucy");
    user.setAge(20);
    user.setEmail("1243@qq.com");
    int insert = userMapper.insert(user);
    System.out.println(insert);
}

注意:数据库插入id值默认为:全局唯一id

1585808430935887874

2、MP的主键策略

2.1 ASSIGN_ID

MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)

@TableId(type = IdType.ASSIGN_ID)``private String id;

雪花算法:分布式ID生成器

雪花算法是由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性。

核心思想:

长度共64bit(一个long型)。

首先是一个符号位,1bit标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0。

41bit时间截(毫秒级),存储的是时间截的差值(当前时间截 - 开始时间截),结果约等于69.73年。

10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID,可以部署在1024个节点)。

12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID)。

优点:整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高。

2.2 AUTO 自增策略

需要在创建数据表的时候设置主键自增

实体字段中配置 @TableId(type = IdType.AUTO)

@TableId(type = IdType.AUTO)
private Long id;

要想影响所有实体的配置,可以设置全局主键配置

#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto

5.mp自动填充 乐观锁

使用相同的方式填充

自动填充

  1. 准备工作

    • 在表中添加两个字段

      添加datatime类型的新的字段,create_time,update_time

    • 在表对应实体类添加对应的属性

  2. 实体类修改

    自动填充属性添加注解

        @TableField(fill = FieldFill.INSERT)
    	//添加的时候设置值
        private Date createTime;
        
        @TableField(fill = FieldFill.INSERT_UPDATE)
    	//添加的时候设置值,修改的时候不设置值
        private Date updateTime;
    
  3. 创建实体类实现接口,实现接口两个方法

    一个方法添加执行,一个方法修改执行

    设置添加什么值

    注意:不要忘记添加 @Component 注解

    package com.mj.demomptest.handler;
    
    import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
    import org.apache.ibatis.reflection.MetaObject;
    import org.springframework.stereotype.Component;
    
    import java.util.Date;
    
    @Component
    public class MyMetaObjectHandler implements MetaObjectHandler {
        
        //mp执行添加操作时
        @Override
        public void insertFill(MetaObject metaObject) {
            //属性名称,设置的值(当前时间),metaObject对象  ;当前时间 set createTime中去
            this.setFieldValByName("createTime",new Date(),metaObject);
            this.setFieldValByName("updateTime",new Date(),metaObject);
            
        }
        
        //mp执行修改时
        @Override
        public void updateFill(MetaObject metaObject) {
            this.setFieldValByName("updateTime",new Date(),metaObject);
    
        }
    }
    

乐观锁

多线程操作中或并发操作中,多人更改同一条数据,最后提交的事务,把之前的事务覆盖,丢失更新问题

  1. 取出记录时,获取当前的版本号 version
  2. 更新时,带上当前version
  3. 执行更新时, set version = newVersion where version = oldVersion 比较当前修改数据版本和数据库版本是否一样
  4. 如果 version 不对 ,就更新失败
实现
  1. 修改实体类

    在表添加字段作为版本号,在表对应实体类添加版本号属性

        @Version
        private Integer version;
    
  2. 创建配置文件 注册乐观锁插件

    创建包config,创建文件MybatisPlusConfig.java

    此时可以删除主类中的 @MapperScan 扫描注解

    package com.mj.demomptest.config;
    
    import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    @Configuration
    @MapperScan("com.mj.demomptest.mapper")
    public class MpConfig {
    
        //乐观锁插件
        @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor() {
            return new OptimisticLockerInterceptor();
        }
    
    
    }
    

6.查询

1,查询

  1. 通过多个id批量查询

        //多个id批量查询
        @Test
        public void testSelect1(){
    
            List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
            System.out.println(users);
        }
    
  2. 简单的条件查询

        @Test
        public void testSelect2(){
    
            Map<String,Object> columnMap = new HashMap<>();
            columnMap.put("name","Jone");
            columnMap.put("age",20);
            List<User> users = userMapper.selectByMap(columnMap);
            System.out.println(users);
        }
    

2,分页

  1. 配置分页查询插件

        //分页查询插件
        @Bean
        public PaginationInterceptor paginationInterceptor() {
            return new PaginationInterceptor();
        }
    
  2. 编写分页代码

    • 插件Page对象,传入两个参数

      当前页

      每页显示数

    • 调用mp的方法实现分页

          //分页查询
          @Test
          public void testSelectPage(){
              Page<User> page = new Page(1,3);
              //new 的对象,条件
              Page<User> userPage = userMapper.selectPage(page, null);
              //返回对象得到分页所有数据
              long pages = userPage.getPages();//总页数
              long current = userPage.getCurrent();//当前页
              List<User> records = userPage.getRecords();//查询数据集合
              long total = userPage.getTotal();//总记录数
              boolean hasNext = userPage.hasNext();//现在当前页是否有下一页
              boolean hasPrevious = userPage.hasPrevious();//现在当前页是否有上一页
      
          }
      

7.删除与逻辑删除

1,删除

  1. 根据Id删除

        //id删除
        @Test
        public void testDeleteId(){
            int rows = userMapper.deleteById(1);
            System.out.println(rows);
        }
    
  2. 批量删除

    @Test
    public void testDeleteBatchIds() {
        int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));
        system.out.println(result);
    }
    
    
  3. 简单条件删除

    @Test
    public void testDeleteByMap() {
    	HashMap<String, Object> map = new HashMap<>();
    	map.put("name", "Helen");
    	map.put("age", 18);
    	int result = userMapper.deleteByMap(map);
    	system.out.println(result);
    }
    
    

2,逻辑删除

  1. 物理删除和逻辑删除

    物理删除:表中数据不存在了

    逻辑删除:表中数据还存在,但在查询时,查不出来

    ​ 在表添加字段,作为逻辑删除标志,每次删除时,修改标志位

  2. 逻辑删除实现流程

    • 数据库修改

      添加delete字段 作为逻辑删除的标志

    • 实体类修改

      添加deleted 字段,并加上 @TableLogic 注解

          @TableLogic
          @TableField(fill = FieldFill.INSERT)
          private Integer deleted; //逻辑删除标志
      

      MyMetaObjectHandler.java

      this.setFieldValByName("deleted",0,metaObject);
      
    • 配置(可选)

      0 - - -不删除

      1 - - - 删除

    • 测试

      注意:被删除前,数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作

          @Test
          public void testLogicDelete() {
              int result = userMapper.deleteById(1585882038232223746L);
              System.out.println(result);
          }
      

      数据库中的数据并没有被删除,只是修改了 deleted的值 为1

    • 测试逻辑后的删除查询

8.条件构造器和常用接口

1,wapper介绍

Wrapper : 条件构造抽象类,最顶端父类

AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件

QueryWrapper : 查询条件封装

UpdateWrapper : Update 条件封装

AbstractLambdaWrapper : 使用Lambda 语法

LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper

LambdaUpdateWrapper : Lambda 更新封装Wrapper

2,测试用例

  1. ge 、gt、le、lt、isNull、isNotNull

    @Test
    public void testSel(){
        //ge,gt,le,lt
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //表中的字段名字,值   age 大于等于21的
        queryWrapper.ge("age",21);//大于等于
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);
    }
    
  2. eq(等于)、ne(不等于)

    注意:seletOne()返回的是一条实体记录,当出现多条时会报错

        //eq ne
        @Test
        public void testSelectOne(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("name","Tom");
            List<User> users = userMapper.selectList(queryWrapper);
            System.out.println(users);
        }
    

  3. between、notBetween

    包含大小边界

    //between,notbetween
    @Test
    public void testSelectA(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //字段,开始值,结束值   age [22,28]
        queryWrapper.between("age",22,28);
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);
    }
    

  4. like、notlike、likeLeft、likeRight(%的右边)

    update user set name like '%张'
    

    selectMap()返回Map集合列表,通常配合select()使用

        @Test
        public void testSelectB(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            //
            queryWrapper.like("name","J");
            List<User> users = userMapper.selectList(queryWrapper);
            System.out.println(users);
        }
    

  5. orderBy、orderByDesc、orderByAsc 排序

        @Test
        public void testSelectC(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            //
            queryWrapper.orderByDesc("id");
            List<User> users = userMapper.selectList(queryWrapper);
            System.out.println(users);
        }
    

3,查询方式

查询方式 说明
setSqlSelect 设置 SELECT 查询字段
where WHERE 语句,拼接 + WHERE 条件
and AND 语句,拼接 + AND 字段=值
andNew AND 语句,拼接 + AND (字段=值)
or OR 语句,拼接 + OR 字段=值
orNew OR 语句,拼接 + OR (字段=值)
eq 等于=
allEq 基于 map 内容等于=
ne 不等于<>
gt 大于>
ge 大于等于>=
lt 小于<
le 小于等于<=
like 模糊查询 LIKE
notLike 模糊查询 NOT LIKE
in IN 查询
notIn NOT IN 查询
isNull NULL 值查询
isNotNull IS NOT NULL
groupBy 分组 GROUP BY
having HAVING 关键词
orderBy 排序 ORDER BY
orderAsc ASC 排序 ORDER BY
orderDesc DESC 排序 ORDER BY
exists EXISTS 条件语句
notExists NOT EXISTS 条件语句
between BETWEEN 条件语句
notBetween NOT BETWEEN 条件语句
addFilter 自由拼接 SQL
last 拼接在最后,例如:last(“LIMIT 1”)

有关02-MyBatis-Plus的更多相关文章

  1. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  2. 牛客网专项练习30天Pytnon篇第02天 - 2

    1.在Python3中,下列关于数学运算结果正确的是:(B)a=10b=3print(a//b)print(a%b)print(a/b)A.3,3,3.3333...B.3,1,3.3333...C.3.3333...,3.3333...,3D.3.3333...,1,3.3333...解析:    在Python中,//表示地板除(向下取整),%表示取余,/表示除(Python2向下取整返回3)2.如下程序Python2会打印多少个数:(D)k=1000whilek>1:    print(k)k=k/2A.1000 B.10C.11D.9解析:    按照题意每次循环K/2,直到K值小于等

  3. PLUS模型和InVEST模型生态系统服务多情景模拟预测、ArcGIS空间数据处理、空间分析与制图、土地利用时空变化 - 2

    查看原文>>>基于”PLUS模型+“生态系统服务多情景模拟预测实践技术应用目录第一章、理论基础与软件讲解第二章、数据获取与制备第三章、土地利用格局模拟第四章、生态系统服务评估第五章、时空变化及驱动机制分析第六章、论文撰写技巧及案例分析基于ArcGISPro、Python、USLE、INVEST模型等多技术融合的生态系统服务构建生态安全格局基于生态系统服务(InVEST模型)的人类活动、重大工程生态成效评估、论文写作等具体应用基于ArcGISPro、R、INVEST等多技术融合下生态系统服务权衡与协同动态分析实践应用    本文从数据、方法、实践三方面对生态系统服务多情景预测进行讲解。内容涵盖多

  4. Ruby:为什么 1.025.round(2) 四舍五入为 1.02? - 2

    据我了解.round()-ruby中的功能将小数向上舍入,最后一个有效数字是5?例如1.5.round(0)#=>2(OK)但为什么1.025.round(2)#=>1.02而不是我期望的1.03?irb(main):037:0>1.025.round(2)=>1.02我该怎么做才能解决这个问题? 最佳答案 这与最后一位数字为5无关,与将十进制值转换为double浮点值有关。http://en.wikipedia.org/wiki/Double_precision_floating-point_format基本上,十进制数必须以有限

  5. Elasticsearch--02.Kibana8.1.0安装 - 2

    1.下载安装概述:Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana,可以通过各种图表进行高级数据分析及展示。下载地址:Kibana8.1.0|Elastic解压到指定目录:tar-xzvfkibana-8.1.0-linux-x86_64.tar.gz-C/opt/module/2.Kibana生成证书文件在es服务器中生成证书、直接回车cd/opt/module/elasticsearch-8.1.0/bin/elasticsearch-certutilcsr-namekibana-dns

  6. ruby-on-rails - rails : Plus sign in GET-Request replaced by space - 2

    在Rails3(Ruby1.9.2)中我发送一个请求StartedGET"/controller/action?path=/41_+"但是参数列表是这样的:{"path"=>"/41_","controller"=>"controller","action"=>"action"}这里出了什么问题?-、*或.符号工作正常,只是+将被空格替换。 最佳答案 这是正常的URL编码,theplussignisashorthandforaspace:Withinthequerystring,theplussignisreservedasshor

  7. 【愚公系列】2023年02月 微信小程序-Flex布局详解 - 2

    文章目录一、Flex布局详解1.Flex布局的概念1.1传统布局1.2Flex布局1.3Flex布局声明2.Flex布局的容器属性2.1flex-direction属性2.2flex-wrap属性2.3flex-flow属性2.4justify-content属性2.5align-items属性2.6align-content属性3.Flex布局的项目属性3.1order属性3.2flex-grow属性3.3flex-shrink属性3.4flex-basis属性3.5flex属性3.6align-self属性总结一、Flex布局详解1.Flex布局的概念1.1传统布局盒子模型:我们知道当并列

  8. 华为OD机试 - 删除最少字符(Python) | 机试题算法思路 【2023-02】 - 2

    最近更新的博客华为OD机试-数组合并(Python),真题含思路华为OD机试-最近的医院(Python),简单直白疑问搞懂,python中文词频统计,让你真能学会华为OD机试-最小传递延迟(Python)|代码编写思路+核心知识点字体反爬,一种来自字体设计师的跨行反爬案例|案例282023新华为OD机试题-事件推送(JavaScript)|刷完必过使用说明参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。华为OD清单查看地址:blog.csdn.net/hihell/category_12199275.html华为O

  9. 嵌入式UI框架 LVGL 学习笔记 02 页面管理和主题定制 - 2

    LVGL页面切换LVGL中没有明确的页面切换方案,参考(2.6#lvgl-多页面(screen)设定/切换)根据实际可用API,可以考虑两种方案:通过FLAG(LV_OBJ_FLAG_HIDDEN)隐藏或者显示lv_obj_add_flag/lv_obj_clear_flag根UI控件通过管理child节点的对象来实现lv_obj_set_parent/lv_obj_get_child通过屏幕显示obj切换lv_scr_load/lv_scr_load_anim与参考文章不同的是,这里更建议使用1和2两种方式进行管理。具体场景如下:如果是简单页面,没有标题,页脚,侧边栏等复杂元素,建议使用3。

  10. 02 openEuler操作系统的安装 - 2

    文章目录02openEuler操作系统的安装2.1openEuler操作系统的安装流程2.2openEuler操作系统的安装详细步骤2.2.1下载地址2.2.2创建虚拟机2.2.2.1方法一:典型配置2.2.2.2方法二:自定义配置2.2.3安装过程02openEuler操作系统的安装2.1openEuler操作系统的安装流程2.2openEuler操作系统的安装详细步骤本次介绍openEuler22.03-LTS基于X86架构的安装。2.2.1下载地址官网下载地址:https://www.openeuler.org/zh/download/根据你的实际需求选择适合架构平台的ISO系统镜像下载

随机推荐