mybatis-plus学习及使用

什么是Mybatis-Plus

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

Mybatis-Plus的特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

官方网站

https://mybatis.plus/

快速起步

版本说明

本文档使用的是MyBatis-Plus v3.4.2

准备数据库

1、创建数据库 mybatis-plus

2、导入如下脚本

DROP TABLE IF EXISTS USER;

CREATE TABLE USER
(
    id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
) DEFAULT CHARSET=UTF8;

DELETE FROM USER;

INSERT INTO USER (id, NAME, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

创建SpringBoot项目

image-20210214194324839

image-20210214204244593

image-20210214204330075

image-20210214204402731

image-20210214204506930

导入依赖

修改 pom.xml 文件

<!-- MySql数据库相关依赖 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- MyBatis-Plus相关依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>

配置数据源

1、修改配置文件类型

将 src/main/resources/application.properties 更改为 src/main/resources/application.yml

2、添加如下配置

server:
  port: 8080

spring:
  datasource:
    username: root
    password: ok
    url: jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    driver-class-name: com.mysql.cj.jdbc.Driver

配置启动类

修改 com.yacon.mybatisplus.MybatisPlusApplication 类

package com.yacon.mybatisplus;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
 @MapperScan("com.yacon.mybatisplus.mapper")
public class MybatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);
    }

}

创建POJO类

创建 com.yacon.mybatisplus.pojo.User 类

package com.yacon.mybatisplus.pojo;

import lombok.Data;

@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

创建Mapper类

创建 com.yacon.mybatisplus.mapper.UserMapper 接口

package com.yacon.mybatisplus.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yacon.mybatisplus.pojo.User;

public interface UserMapper extends BaseMapper<User> { }

编写测试方法

1、修改 src/test/java/com/yacon/mybatisplus/MybatisPlusApplicationTests.java文件

package com.yacon.mybatisplus;

import com.yacon.mybatisplus.mapper.UserMapper;
import com.yacon.mybatisplus.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.util.List;

@SpringBootTest
class MybatisPlusApplicationTests {

    @Resource
    private UserMapper userMapper;

    /**
     * 查询所有用户列表
     */
    @Test
    public void testSelect(){
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

2、运行测试

image-20210214212054858

日志输出

1、修改 src/main/resources/application.yml 配置文件,添加日志配置

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

2、运行测试

image-20210214213849307

基础CRUD

SELECT

根据ID查询

1、添加测试方法

/**
 * 查询用户信息
 */
@Test
public void testGetUserById(){
    User user = userMapper.selectById(5);
    if(null == user) {
        System.out.println("查询失败");
        return;
    }
    System.out.println(user.getId());
    System.out.println(user.getName());
    System.out.println(user.getAge());
    System.out.println(user.getEmail());
}

2、运行测试

image-20210214225751263

查询总条目数

1、编写测试方法

/**
 * 查询总条目数
 */
@Test
public void testGetUserCount(){
    Integer count = userMapper.selectCount(null);
    System.out.println(count);
}

2、运行测试

image-20210214230110223

条件查询

1、编写测试方法

/**
 * 查询年龄大于20岁的用户
 */
@Test
public void testWhere(){
    QueryWrapper queryWrapper = new QueryWrapper();
    queryWrapper.gt("age",20);

    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

2、运行测试

image-20210214230709005

模糊查询

1、编写测试方法

/**
 * 查询姓名包含 a 的用户
 */
@Test
public void testLike(){
    QueryWrapper queryWrapper = new QueryWrapper();
    queryWrapper.like("name",'a');

    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

2、运行测试

image-20210214231113125

排序查询

1、添加测试方法

/**
 * 查询用户列表,并按年龄逆序
 */
@Test
public void testOrder() {
    QueryWrapper queryWrapper = new QueryWrapper();
    queryWrapper.orderByDesc("age");

    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

2、运行测试

image-20210214231344660

INSERT

配置主键生成策略

1、确保数据表的主键列为自增列

image-20210214221910994

2、修改 com.yacon.mybatisplus.pojo.User 类

@Data
public class User {
   @TableId(type= IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

编写测试方法

1、添加测试方法

/**
 * 插入用户
 */
@Test
public void testInsert(){
    User user = new User();
    user.setName("张三");
    user.setAge(20);
    user.setEmail("zhangsan@mail.com");

    int result = userMapper.insert(user);
    System.out.println(result > 0 ? "插入成功" : "插入失败");
    System.out.println("ID="+user.getId());
}

2、运行测试

image-20210214223925253

image-20210214222918418

UPDATE

1、添加测试方法

/**
 * 更新用户
 */
@Test
public void testUpdate(){
    User user = new User();
    user.setId(6L);
    user.setName("zhangsan");

    int result = userMapper.updateById(user);
    System.out.println(result > 0 ? "修改成功" : "修改失败");
}

2、运行测试

image-20210214224423638

image-20210214224442123

DELETE

1、添加测试方法

/**
 * 删除用户
 */
@Test
public void testDelete(){
    int result = userMapper.deleteById(6);
    System.out.println(result > 0 ? "删除成功" : "删除失败");
}

2、运行测试

image-20210214225126087

高级扩展

逻辑删除

逻辑删除 是指,在删除表中的某条数据时并不是真正的删除,而是更改某个表字段的值来表示该条数据已被删除

修改数据表

给 User 添加字段 deleted,并设置默认值为 0

ALTER TABLE `mybatis_plus`.`user` ADD COLUMN `deleted` INT(1) DEFAULT 0 NOT NULL AFTER `email`;

修改实体类

修改 com.yacon.mybatisplus.pojo.User 类

@Data
public class User {
    @TableId(type= IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
   @TableLogic
   private Integer deleted;
}

添加配置

修改 src/main/resources/application.yml 文件

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
 global-config:
   db-config:
     logic-delete-field: deleted # 全局逻辑删除的实体字段名
     logic-delete-value: 1 # 逻辑已删除的值
     logic-not-delete-value: 0 # 逻辑未删除的值

运行测试

1、运行 删除用户 测试方法

image-20210214233300558

image-20210214233319035

2、运行 查询所有用户列表 测试方法

image-20210214233453679

自动填充字段

修改数据表

给 user 表添加两个字段 gmt-create 和 gmt-modified

ALTER TABLE `mybatis_plus`.`user`   
  ADD COLUMN `gmt_create` DATETIME NULL  COMMENT '创建时间' AFTER `deleted`,
  ADD COLUMN `gmt_modified` DATETIME NULL  COMMENT '更新时间' AFTER `gmt_create`;

image-20210215000407833

修改实体类

修改 com.yacon.mybatisplus.pojo.User 类

@Data
public class User {
    @TableId(type= IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    @TableLogic
    private Integer deleted;
   @TableField(fill = FieldFill.INSERT)
   private Date gmtCreate;
   @TableField(fill = FieldFill.INSERT_UPDATE)
   private Date gmtModified;
}

编写填充处理器

创建 com.yacon.mybatisplus.handle.MyMetaObjectHandler 类

package com.yacon.mybatisplus.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Date;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("gmtCreate",new Date(), metaObject);
        this.setFieldValByName("gmtModified",new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("gmtModified",new Date(), metaObject);
    }
}

运行测试

1、运行 插入用户 测试方法

image-20210215001926063

image-20210215001943222

2、运行 更新用户 测试方法

image-20210215002145083

image-20210215002200304

常用插件

乐观锁

在高并发的情况下,可能存在多个用户同时修改一条数据的情况,为了让某一用户在修改数据时不被被人更新,这时就需要用乐观锁将数据进行锁定

乐观锁实现方式

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

修改数据表

给 user 表添加 version 字段 b

ALTER TABLE `mybatis_plus`.`user`   
  ADD COLUMN `version` INT DEFAULT 1  NULL  COMMENT '乐观锁' AFTER `email`;

image-20210215003720837

修改实体类

修改 com.yacon.mybatisplus.pojo.User 类

@Data
public class User {
    @TableId(type= IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    @TableLogic
    private Integer deleted;
    @TableField(fill = FieldFill.INSERT)
    private Date gmtCreate;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmtModified;
   @Version
   private Integer version;
}

注册插件

1、创建 com.yacon.mybatisplus.config.MyBatisPlusConfig 类

package com.yacon.mybatisplus.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@MapperScan("com.yacon.mybatisplus.mapper")
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 注册乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

2、修改 om.yacon.mybatisplus.MybatisPlusApplication 启动类

@SpringBootApplication
 @MapperScan("com.yacon.mybatisplus.mapper")
public class MybatisPlusApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);
    }
}

运行测试

1、添加测试方法

/**
 * 乐观锁测试
 */
@Test
public void testLocker() {
    // 模拟线程1
    User user1 = userMapper.selectById(7L);
    user1.setName("张三");

    // 模拟线程2插队
    User user2 = userMapper.selectById(7L);
    user2.setName("李四");
    userMapper.updateById(user2);

    userMapper.updateById(user1);
}

2、运行测试

image-20210215010903772

image-20210215010922409

分页查询

注册分页插件

修改 com.yacon.mybatisplus.config.MyBatisPlusConfig 类

注意注册插件的顺序,要先注册 分页插件,再注册 乐观锁插件

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

   // 注册分页插件
   interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

    // 注册乐观锁插件
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

    return interceptor;
}

添加测试方法

修改 com.yacon.mybatisplus.MybatisPlusApplicationTests 测试类

/**
 * 分页查询
 */
@Test
public void testPage(){
    long current = 1; // 当前页码
    long size = 2; // 每页显示条目数
    Page<User> page = new Page<>(current,size);

    userMapper.selectPage(page, null);

    List<User> users = page.getRecords(); // 获取数据列表
    users.forEach(System.out::println);
}

运行测试

image-20210215101147219

性能分析

SQL性能校验

注册插件

修改 com.yacon.mybatisplus.config.MyBatisPlusConfig 类

性能分析插件 要放在 分页插件 和 乐观锁插件 之后

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

    // 注册分页插件
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

    // 注册乐观锁插件
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

   // 注册性能分析插件
   interceptor.addInnerInterceptor(new IllegalSQLInnerInterceptor());
    return interceptor;
}

运行测试

1、运行 查询所有用户列表 测试方法

由于我们开启了 逻辑删除,所以在查询时需要使用 deleted 为查询条件进行查询,但我们没有给 deleted 字段添加索引,所以这里报了一个 未使用索引的错误

image-20210215112019573

2、修改数据库,给 deleted 字段添加索引

注意:添加组合索引时,deleted 一定要放在第一个,否则,使用单个deleted 作为条件查询时无法触发索引

ALTER TABLE `mybatis_plus`.`user`
  ADD  UNIQUE INDEX `id_deleted_unique` (`deleted`, `id`);

image-20210215113112299

3、重新运行 查询所有用户列表 测试方法

image-20210215113143807

SQL性能分析

该功能有性能损耗,不建议生产环境使用

添加依赖

修改 pom.xml

<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.9.1</version>
</dependency>

修改数据源

修改 src/main/resources/application.yml

spring:
  datasource:
    username: root
    password: ok
   url: jdbc:p6spy:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
   driver-class-name: com.p6spy.engine.spy.P6SpyDriver
   url: jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
   driver-class-name: com.mysql.cj.jdbc.Driver

配置p6spy

创建 src/main/resources/spy.properties

modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2

运行测试

执行 查询用户信息 测试方法

image-20210215142948150

代码生成器

创建SpringBoot项目

新建一个SpringBoot项目

导入依赖

修改 pom.xml 文件

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.0.5</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.2</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>

编写代码生成器

创建 MyBatisPlusAutoCode 类

package com.yacon.mybatisplus;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;

/**
 * 代码生成器
 */
public class MyBatisPlusAutoCode {
    public static void main(String[] args) {
        AutoGenerator mpg = new AutoGenerator();

        /* 全局配置 */
        GlobalConfig gc = new GlobalConfig();
        //生成文件的输出目录
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        // 是否打开输出目录
        gc.setOpen(false);
        // 是否覆盖已有文件
        gc.setFileOverride(true);
        // 开发人员
        gc.setAuthor("Yacon");
        // 是否生成swagger2注解
        gc.setSwagger2(true);
        // 时间类型对应策略
        gc.setDateType(DateType.TIME_PACK);
        // mapper 命名方式
        gc.setMapperName("%sDao");
        // Mapper xml 命名方式
        gc.setXmlName("%sDao");
        // service 命名方式
        gc.setServiceName("%sService");
        // service impl 命名方式
        gc.setServiceImplName("%sServiceImpl");
        // controller 命名方式
        gc.setControllerName("%sController");
        // 指定生成的主键的ID类型
        gc.setIdType(IdType.AUTO);
        // 设置全局配置
        mpg.setGlobalConfig(gc);

        /* 数据源配置 */
        DataSourceConfig dsc = new DataSourceConfig();
        // 数据库类型
        dsc.setDbType(DbType.MYSQL);
        // 驱动连接的URL
        dsc.setUrl("jdbc:mysql://localhost:3306/cvs_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2B8");
        // 驱动名称
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        // 数据库账号
        dsc.setUsername("root");
        // 数据库密码
        dsc.setPassword("ok");
        // 设置数据库配置
        mpg.setDataSource(dsc);

        /* 包配置 */
        PackageConfig pc = new PackageConfig();
        // 父包模块名
        pc.setModuleName("api");
        // 父包名
        pc.setParent("com.yacon.mybatisplus");
        // Entity包名
        pc.setEntity("pojo");
        // Service包名
        pc.setService("service");
        // Service Impl包名
        pc.setServiceImpl("service");
        // Mapper包名
        pc.setMapper("dao");
        // Mapper XML包名
        pc.setXml("dao");
        // Controller包名
        pc.setController("controller");
        // 设置包配置
        mpg.setPackageInfo(pc);

        /* 策略配置 */
        StrategyConfig strategy = new StrategyConfig();
        // 需要包含的表名
        strategy.setInclude("t_address","t_storage_record","t_supplier","t_sys_role","t_sys_user");
        // 表前缀
        strategy.setTablePrefix("t_");
        // 数据库表映射到实体的命名策略
        strategy.setNaming(NamingStrategy.underline_to_camel);
        // 数据库表字段映射到实体的命名策略
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        // 是否为lombok模型
        strategy.setEntityLombokModel(true);
        // Boolean类型字段是否移除is前缀
        strategy.setEntityBooleanColumnRemoveIsPrefix(true);
        // 生成 @RestController 控制器
        strategy.setRestControllerStyle(true);
        // 驼峰转连字符
        strategy.setControllerMappingHyphenStyle(true);
        // 乐观锁属性名称
        strategy.setVersionFieldName("version");
        // 逻辑删除属性名称
        strategy.setLogicDeleteFieldName("deleted");
        // 表填充字段
        TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
        TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(gmtCreate);
        tableFills.add(gmtModified);
        strategy.setTableFillList(tableFills);
        // 设置策略配置
        mpg.setStrategy(strategy);

        // 执行
        mpg.execute();
    }
}

运行代码生成器

image-20210215234739275

posted @ 2021-06-09 12:25  编码小高  阅读(159)  评论(0编辑  收藏  举报