Mybatis-plus的学习


前言

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


1.mybatis-plu概述

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

我们的愿景是成为 MyBatis 最好的搭档,就像魂斗罗中的1P、2P,基友搭配,效率翻倍。

1.2、特性
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

1.3、pom.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>mybatis-plus-Demo1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mybatis-plus</name>
    <description>mybatis-plus-Demo1</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>3.0.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
<!--        代码自动生成器-->
        <!-- mp 代码生成器 依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
        <!-- 导入swagger -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.5.20</version>
        </dependency>
        <!-- 添加模板引擎,thymeleaf 还有freemarker都是模板引擎 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.代码生成器(重点)

package com.example;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class Demo3 {
    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }

    public static void main(String[] args) {
        // 代码生成器
        //构建一个代码自动生成器对象
        AutoGenerator mpg = new AutoGenerator();

        // 1、创建全局配置类的对象
        GlobalConfig gc = new GlobalConfig();
        //获取当前项目路径
        String projectPath = System.getProperty("user.dir");
        System.out.println("projectPath = " + projectPath);
        //自动生成代码存放的路径
        gc.setOutputDir(projectPath + "/src/main/java");
        //设置 --作者注释
        gc.setAuthor("LiZuFu");
        //是否打开文件夹
        gc.setOpen(false);
        //是否覆盖已有文件
        gc.setFileOverride(false);
        //各层文件名称方式,例如: %sAction 生成 UserAction  %s占位符
        gc.setServiceName("%sService");
        //设置日期策略  date类型
        gc.setDateType(DateType.ONLY_DATE);
        //设置主键策略 雪花算法
        gc.setIdType(IdType.ASSIGN_ID);
        //设置开启 swagger2 模式
        gc.setSwagger2(true);
        //把全局配置放入代码生成器
        mpg.setGlobalConfig(gc);

        // 2、数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/eshop?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc); //把数据源配置加入到代码生成器

        // 3、包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.example.eshop");
        pc.setEntity("entity");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("controller");
        // ...  有默认值,点击查看源码
        mpg.setPackageInfo(pc);//包加入代码生成器

        // 4、策略配置
        StrategyConfig strategy = new StrategyConfig();
        //下划线转驼峰命名  表
        strategy.setNaming(NamingStrategy.underline_to_camel);
        // 下划线转驼峰命名字段
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        //实体类是否加上lombok注解
        strategy.setEntityLombokModel(true);
        //控制层采用RestControllerStyle注解
        strategy.setRestControllerStyle(true);
        // RequestMapping中 驼峰转连字符 -
        strategy.setControllerMappingHyphenStyle(true);
        //要映射的数据库表名  (重点)
        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
        //添加表名前缀
        //strategy.setTablePrefix("m_"); //自动拼接上m_
        //逻辑删除字段名
        strategy.setLogicDeleteFieldName("deleted");
        //乐观锁字段名
        strategy.setVersionFieldName("version");
        // -------自动填充策略
        ArrayList<TableFill> fillList = new ArrayList<>();
        fillList.add(new TableFill("createTime", FieldFill.INSERT));
        fillList.add(new TableFill("updateTime",FieldFill.INSERT_UPDATE));
        // 参数是 List<TableFill> 的链表
        strategy.setTableFillList(fillList);
        mpg.setStrategy(strategy);

        //---------------------------------
        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            //输出了 静态资源下的 Mapper
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });

        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        //        FreemarkerTemplateEngine模板引擎
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
}

3.基于mapper层CRUD

说明:

  • 通用 CRUD 封装BaseMapper (opens new window)接口,为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器
  • 泛型 T 为任意实体对象
  • 参数 Serializable 为任意类型主键 Mybatis-Plus 不推荐使用复合主键约定每一张表都有自己的唯一 id 主键
  • 对象 Wrapper条件构造器

1.insert

// 插入一条记录
int insert(T entity);

参数说明

类型参数名描述
Tentity实体对象
主键生成策略

因为在最开始建表的sql语句中就指明了,id是数据库的主键,主键不能唯一,

常见的数据库中主键自动设置方法有(uuid、自增id、雪花算法、redis生成、zookeeper生成)

雪花算法

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看https://github.com/twitter/snowflake。雪花算法支持的TPS可以达到419万左右(2^22*1000),几乎保证全球唯一。

雪花算法在工程实现上有单机版本和分布式版本。单机版本如下,分布式版本可以参看美团leaf算法:https://github.com/Meituan-Dianping/Leaf

设置主键id

@TableId(value = "goodID", type = IdType.ASSIGN_ID)//枚举注解,使用ID_WORKER策略,全局唯一ID,数据库设置自增也没用
private Long goodid;

查看这个注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})  //枚举注解
public @interface TableId {
    //可以设置以下两个参数
    String value() default "";
    IdType type() default IdType.NONE; //ID策略
}

主键自增策略

@TableId(value = "id", type = IdType.AUTO)//自增
private Integer id;

其他策略

/**
*数据库自曾ID
该类型要确保数据库设置了自曾,否则无效
*/
AUTO(0),
/**
*该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
*/
NONE(1),
/**
*用户输入ID
*该类型可以通过自己注册自动填充id
*/
INPUT(2),
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。
*分配ID (主键类型为number或string),
*/
ASSIGN_ID(3),
**
* 分配UUID (主键类型为 string)
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))
*/
ASSIGN_UUID(4),
@Deprecated
ID_WORKER(3),
/** @deprecated */
@Deprecated
ID_WORKER_STR(3),
/** @deprecated */
@Deprecated
UUID(4);
自动填充
  1. 数据库新增字段

    在这里插入图片描述

  2. 在实体类的时间数据上添加@TableField

    //   LocalDateTime类型线程安全
        /**
         * 默认
         *    DEFAULT
         *     INSERT,
         *     新增时
         *     UPDATE,
         *     修改时
         *     INSERT_UPDATE;
         *     新增修改是
         */
        @TableField(fill = FieldFill.INSERT,value = "create_time")
        private LocalDateTime createTime;
        @TableField(fill = FieldFill.INSERT_UPDATE,value = "update_time")
        private LocalDateTime updateTime;
       // FieldFill fill() default FieldFill.DEFAULT; file默认为FieldFill.DEFAULT
    
  3. 编辑处理器

    package com.example.config;
    import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.reflection.MetaObject;
    import org.springframework.stereotype.Component;
    import java.time.LocalDateTime;
    @Slf4j //日志
    @Component//以组件的形式把这个处理器注册到IOC容器中
    public class MyMetaObjectHandler implements MetaObjectHandler {
        //插入时启动  第三个参数 LocalDateTime 一定要和 createTime成员变量的值的类型一致,不然是null 如果是date就都设置date
        @Override
        public void insertFill(MetaObject metaObject) {
            this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
            this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
        }
        //更新时候启动
        @Override
        public void updateFill(MetaObject metaObject) {
            this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
        }
    
    }
    
  4. 接下来的代码执行插入、更新时都会自动设置时间

    Long id=Long.parseLong("01605601184784535554");
    TbTypes tbTypes=goodTypes.selectById(id);
    tbTypes.setTypename("ipa");
    tbTypes.setUpdateTime(null);
    System.err.println(tbTypes.toString());
    int result=goodTypes.updateById(tbTypes);
    //通过id查询 需要把跟新时间设置为null才会更新否则还是原来修改时间  tbTypes.setUpdateTime(null);
    

2.delete

// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

参数说明

类型参数名描述
Wrapperwrapper实体对象封装操作类(可以为 null)
Collection<? extends Serializable>idList主键 ID 列表(不能为 null 以及 empty)
Serializableid主键 ID
Map<String, Object>columnMap表字段 map 对象
逻辑删除
  1. 数据库添加deleted字段

在这里插入图片描述

  1. 同步实体类

    @ApiModelProperty(value = "逻辑删除")
    @TableLogic
    private Integer deleted;
    
  2. 在配置文件yml中配置

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/shop?characterEncoding=utf-8&servertimeZone=UTC
        password: 123456
        username: root
        driver-class-name: com.mysql.cj.jdbc.Driver
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      global-config:
        db-config:
          logic-delete-field: deleted   #全局逻辑删除的实体字段名(since 3.3.0,配置可以不需要加注解2的注解)
          logic-delete-value: 1  #逻辑已删除值(默认为1)
          logic-not-delete-value: 0  #逻辑未删除值(默认为0)
    
  3. 测试

在这里插入图片描述

@Test
public void deleteTest(){
    int result=goodTypes.deleteById(1);
    System.out.println(result);
}

如果我们去查询typeID=1的用户,查不到,mybatis-plus会自动拼接了deleted在where中判断

在这里插入图片描述

3.update

// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);

参数说明

类型参数名描述
Tentity实体对象 (set 条件值,可为 null)
WrapperupdateWrapper实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
乐观锁
  1. 乐观锁机制

    OptimisticLockerInnerInterceptor

    当要更新一条记录的时候,希望这条记录没有被别人更新
    乐观锁实现方式:

    • 取出记录时,获取当前 version
    • 更新时,带上这个 version
    • 执行更新时, set version = newVersion where version = oldVersion
    • 如果 version 不对,就更新失败
  2. 在数据库添加字段

在这里插入图片描述
3. 乐观锁配置需要两步

  1. springboot注解方式
package com.example.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement//开启事务
@Configuration//配置类注解
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        //实现乐观锁
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//乐观锁插件拦截器OptimisticLockerInnerInterceptor
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//插件分页拦截器
       return mybatisPlusInterceptor;
    }
}
  1. 在实体类的字段上加上@version注解

    @Version
    private Integer version;
    

    说明:

    支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime

    整数类型下 newVersion = oldVersion + 1

    newVersion 会回写到 entity

    仅支持 updateById(id)update(entity, wrapper) 方法

    update(entity, wrapper) 方法下, wrapper 不能复用!!!

  2. 测试

        @Test
        public void updateTest(){
            Long id=Long.parseLong("1605601235107835906");
            TbTypes tbTypes=goodTypes.selectById(id);
            tbTypes.setTypename("ipa");
            tbTypes.setUpdateTime(null);
            System.err.println(tbTypes.toString());
            TbTypes tbTypes2=goodTypes.selectById(id);
            tbTypes2.setTypename("ipa");
            tbTypes2.setUpdateTime(null);
            System.err.println(tbTypes2.toString());
            int result=goodTypes.updateById(tbTypes);
            int result2=goodTypes.updateById(tbTypes2);
            System.out.println(result);
            System.out.println(result2);
        }
    

在这里插入图片描述

4.select

// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

参数说明

类型参数名描述
Serializableid主键 ID
WrapperqueryWrapper实体对象封装操作类(可以为 null)
Collection<? extends Serializable>idList主键 ID 列表(不能为 null 以及 empty)
Map<String, Object>columnMap表字段 map 对象
IPagepage分页查询条件(可以为 RowBounds.DEFAULT)
分页查询
  1. 配置拦截器

    package com.example.config;
    
    import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    @EnableTransactionManagement//开启事务
    @Configuration//配置类注解
    public class MybatisPlusConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            //实现乐观锁
            MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
            mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//乐观锁插件拦截器OptimisticLockerInnerInterceptor
            mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//插件分页拦截器
           return mybatisPlusInterceptor;
        }
    }
    
  2. page类
    Page

    该类继承了 IPage 类,实现了 简单分页模型 如果你要实现自己的分页模型可以继承 Page 类或者实现 IPage

    属性名类型默认值描述
    recordsListemptyList查询数据列表
    totalLong0查询列表总记录数
    sizeLong10每页显示条数,默认 10
    currentLong1当前页
    ordersListemptyList排序字段信息,允许前端传入的时候,注意 SQL 注入问题,可以使用 SqlInjectionUtils.check(...) 检查文本
    optimizeCountSqlbooleantrue自动优化 COUNT SQL 如果遇到 jSqlParser 无法解析情况,设置该参数为 false
    optimizeJoinOfCountSqlbooleantrue自动优化 COUNT SQL 是否把 join 查询部分移除
    searchCountbooleantrue是否进行 count 查询,如果指向查询到列表不要查询总记录数,设置该参数为 false
    maxLimitLong单页分页条数限制
    countIdStringxml 自定义 count 查询的 statementId
  3. 使用page对象

    public void PageTest(){
     /**源码
     * 分页构造函数
     * @param current 当前页
     * @param size    每页显示条数
     */
     		Page<TbGoods> tbGoodsPage=new Page<>(1,2);
            userMapper.selectPage(tbGoodsPage,null);
            tbGoodsPage.getRecords().forEach(System.out::println);
            System.out.println("获取记录总行数:"+tbGoodsPage.getTotal());
    }
    

在这里插入图片描述

4.wrapper(重点)

条件构造器

说明:

  • 以下出现的第一个入参boolean condition表示该条件是否加入最后生成的sql中,例如:query.like(StringUtils.isNotBlank(name), Entity::getName, name) .eq(age!=null && age >= 0, Entity::getAge, age)
  • 以下代码块内的多个方法均为从上往下补全个别boolean类型的入参,默认为true
  • 以下出现的泛型Param均为Wrapper的子类实例(均具有AbstractWrapper的所有方法)
  • 以下方法在入参中出现的R为泛型,在普通wrapper中是String,在LambdaWrapper中是函数(例:Entity::getId,Entity为实体类,getId为字段idgetter Method)
  • 以下方法入参中的R column均表示数据库字段,当R具体类型为String时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹!)!而不是实体类数据字段名!!!,另当R具体类型为SFunction时项目runtime不支持eclipse自家的编译器!!!
  • 以下举例均为使用普通wrapper,入参为MapList的均以json形式表现!
  • 使用中如果入参的Map或者List,则不会加入最后生成的sql中!!!

警告:

不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输

  1. wrapper 很重
  2. 传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)
  3. 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
  4. 我们拒绝接受任何关于 RPC 传输 Wrapper 报错相关的 issue 甚至 pr

AbstractWrapper

说明:

QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为

/**
     * wrapper的使用
     */
    public void WrapperTest(){
        QueryWrapper<TbGoods> wrapper=new QueryWrapper<>();
        //链式编程 添加查询条件
        wrapper.isNotNull("goodName").gt("price","6000");
        List<TbGoods> TbGoods=userMapper.selectList(wrapper);
        TbGoods.forEach(System.out::println);
        //        eq相等   ne不相等,   gt大于,    lt小于         ge大于等于       le 小于等于
        //        equal/ not equal/ greater than/ less than/ less than or equal/ great than or equal/
    }
    /**
     * 区间查询与计算
     */

    public void WrapperTest2(){
        QueryWrapper<TbGoods> wrapper=new QueryWrapper<>();
        wrapper.between("price","20","26");
        int count=userMapper.selectCount(wrapper);
        System.out.println(count);
        TbGoods tbGoods=new TbGoods();
        tbGoods.setGoodname("苹果14");
        tbGoods.setNum(10);
        tbGoods.setPrice(BigDecimal.valueOf(6999));
        tbGoods.setTypeid(3);
        tbGoods.setImg("001.png");
        int resul=userMapper.insert(tbGoods);
        System.out.println(resul);
        TbTypes tbTypes=new TbTypes();
        tbTypes.setTypename("耳机");
        int resut2=goodTypes.insert(tbTypes);
        System.out.println(resut2);
    }

    /**
     * 模糊查询
     */
    public void WrapperTest3(){
        QueryWrapper<TbGoods> wrapper=new QueryWrapper<>();
        wrapper.like("goodName","苹果");
        wrapper.notLike("goodName","14");
        wrapper.likeRight("goodName","苹果");//苹果%
        wrapper.likeLeft("goodName","9");//%9
        userMapper.selectList(wrapper).forEach(System.out::println);
    }

    /**
     * 子查询
     */
    public void WrapperTest4(){
        QueryWrapper<TbGoods> wrapper=new QueryWrapper<>();
        wrapper.inSql("typeID","select typeID from tb_types where typeID<3");
        userMapper.selectList(wrapper).forEach(System.out::println);
    }

    /**
     * 排序
     */
    public void  WrapperTest5(){
        //排序
        QueryWrapper<TbGoods> wrapper=new QueryWrapper<>();
//        wrapper.orderByAsc("goodId");//升序
        wrapper.orderByDesc("goodId");//降序
        userMapper.selectList(wrapper).forEach(System.out::println);
    }
    /**
     * 分组,条件
     */
    public void WrapperTest6(){
        QueryWrapper<TbTypes> wrapper=new QueryWrapper<>();
        wrapper.groupBy("version").having("version=2");
        goodTypes.selectList(wrapper).forEach(System.out::println);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heibas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值