【Random】五、springboot集成mybatis-plus,使用generator生成代码


​ 很早以前都是用原生的mybatis,在mapper.xml中写各种sql,后来用了tk-mybatis,简化了CRUD操作让开发变得更加高效。mybatis-plus之前没用过,不过最近比较火,准备用下看看和tkmybatis比怎么样。

​ mybatis-plus的官网是:https://baomidou.com ,里面有对配置的详细描述,包括对mybatis-plus generator的配置,好了废话不多说,让我们开始今天的内容吧。

1、引入mybatis-plus依赖

​ 在random的pom.xml文件中引入mybatis-plus的依赖,包括mybatis-plus-boot-starter、mybatis-plus-generator以及freemarker模板引擎,当然还需要mysql、druid,lombok和swagger是generator所需要的。

​ 请注意:引入 MyBatis-Plus 之后请不要再次引入 MyBatis 以及 MyBatis-Spring,以避免因版本差异导致的问题。

​ 算了我还是把完整的pom放在下面吧:(ps:网上找资料时,有的文章jar包不全还得自己去找,烦)

random的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>
	<groupId>top.plgxs</groupId>
	<artifactId>random</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>random</name>
	<packaging>pom</packaging>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<modules>
		<module>random-admin</module>
		<module>random-wx</module>
        <module>random-common</module>
		<module>random-mbg</module>
	</modules>

	<properties>
		<java.version>1.8</java.version>
		<pagehelper-starter.version>1.3.0</pagehelper-starter.version>
		<pagehelper.version>5.2.0</pagehelper.version>
		<mybatis-plus.version>3.4.0</mybatis-plus.version>
		<freemarker.version>2.3.30</freemarker.version>
		<mysql-connector.version>8.0.22</mysql-connector.version>
		<druid.version>1.1.23</druid.version>
		<hutool.version>5.4.0</hutool.version>
		<swagger2.version>2.9.2</swagger2.version>
		<swagger-models.version>1.6.0</swagger-models.version>
		<swagger-annotations.version>1.6.0</swagger-annotations.version>
		<logstash-logback.version>5.3</logstash-logback.version>
		<jackon-databind.version>2.11.0</jackon-databind.version>
		<fastjson.version>1.2.73</fastjson.version>
		<spring-data-commons.version>2.3.0.RELEASE</spring-data-commons.version>
		<jjwt.version>0.9.0</jjwt.version>
		<aliyun-oss.version>2.5.0</aliyun-oss.version>
		<junit.version>5.7.0</junit.version>
		<lombok.version>1.16.20</lombok.version>
		<commons-lang3.version>3.11</commons-lang3.version>
	</properties>

<dependencyManagement>
	<dependencies>
		<!-- pagehelper-springboot -->
		<dependency>
			<groupId>com.github.pagehelper</groupId>
			<artifactId>pagehelper-spring-boot-starter</artifactId>
			<version>${pagehelper-starter.version}</version>
		</dependency>
		<!-- pagehelper -->
		<dependency>
			<groupId>com.github.pagehelper</groupId>
			<artifactId>pagehelper</artifactId>
			<version>${pagehelper.version}</version>
		</dependency>
		<!-- mybatis-plus -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>${mybatis-plus.version}</version>
		</dependency>
		<!-- mybatis-plus generator -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-generator</artifactId>
			<version>${mybatis-plus.version}</version>
		</dependency>
		<!-- freemarker-模板引擎 -->
		<dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
			<version>${freemarker.version}</version>
		</dependency>
		<!--Mysql数据库驱动-->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql-connector.version}</version>
		</dependency>
		<!--集成druid连接池-->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>${druid.version}</version>
		</dependency>
		<!--Hutool Java工具包-->
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>${hutool.version}</version>
		</dependency>
		<!--Swagger-UI API文档生产工具-->
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>${swagger2.version}</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>${swagger2.version}</version>
		</dependency>
		<!--解决Swagger 2.9.2版本NumberFormatException-->
		<dependency>
			<groupId>io.swagger</groupId>
			<artifactId>swagger-models</artifactId>
			<version>${swagger-models.version}</version>
		</dependency>
		<dependency>
			<groupId>io.swagger</groupId>
			<artifactId>swagger-annotations</artifactId>
			<version>${swagger-annotations.version}</version>
		</dependency>
		<!--集成logstash-->
		<dependency>
			<groupId>net.logstash.logback</groupId>
			<artifactId>logstash-logback-encoder</artifactId>
			<version>${logstash-logback.version}</version>
		</dependency>
		<!-- jackson -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${jackon-databind.version}</version>
		</dependency>
		<!-- fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>${fastjson.version}</version>
		</dependency>
		<!--SpringData工具包-->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-commons</artifactId>
			<version>${spring-data-commons.version}</version>
		</dependency>
		<!--JWT(Json Web Token)登录支持-->
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>${jjwt.version}</version>
		</dependency>
		<!-- 阿里云OSS -->
		<dependency>
			<groupId>com.aliyun.oss</groupId>
			<artifactId>aliyun-sdk-oss</artifactId>
			<version>${aliyun-oss.version}</version>
		</dependency>
		<!-- junit -->
		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-api</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		<!-- 热更新 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>
		<!-- lombok -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>${lombok.version}</version>
		</dependency>
		<!-- commons-lang3 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>${commons-lang3.version}</version>
		</dependency>

	</dependencies>
</dependencyManagement>

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

</project>

random-common的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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>random</artifactId>
        <groupId>top.plgxs</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>random-common</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
        </dependency>
        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
    </dependencies>
</project>

random-mbg的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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>random</artifactId>
        <groupId>top.plgxs</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>random-mbg</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>top.plgxs</groupId>
            <artifactId>random-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>

    </dependencies>
</project>

random-admin的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">
	<parent>
		<artifactId>random</artifactId>
		<groupId>top.plgxs</groupId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<modelVersion>4.0.0</modelVersion>
	<artifactId>random-admin</artifactId>
	<packaging>jar</packaging>

	<name>random-admin</name>

	<dependencies>
		<dependency>
			<groupId>top.plgxs</groupId>
			<artifactId>random-mbg</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-api</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin><!--编译跳过测试文件检查的生命周期-->
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<configuration>
					<skip>true</skip>
				</configuration>
			</plugin>
		</plugins>

	</build>

</project>
2、mybatis-plus配置

​ 在random-admin模块的application.yml中添加mybatis-plus的配置,

server:
  servlet:
    context-path: /random
    session:
      timeout: 30m
  port: 8080

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/random?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    username: random
    password: random
    druid:
      initial-size: 5 #连接池初始化大小
      min-idle: 10 #最小空闲连接数
      max-active: 20 #最大连接数
      web-stat-filter:
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" #不统计这些请求数据
      stat-view-servlet: #访问监控网页的登录用户名和密码
        login-username: druid
        login-password: druid

#mybatis
mybatis-plus:
  mapper-locations: classpath*:mapper/**/*.xml
  #实体扫描,多个package用逗号或者分号分隔
  #typeAliasesPackage: top.plgxs.entity
  global-config:
    db-config:
      #主键类型
      #AUTO 数据库ID自增
      #INPUT 用户输入ID
      #ID_WORKER 全局唯一ID,Long类型的主键
      #ID_WORKER_STR 字符串全局唯一ID
      #UUID 全局唯一ID,UUID类型的主键
      #NONE 该类型为未设置主键类型
      id-type: ID_WORKER_STR
      #逻辑删除配置
      logic-delete-value: 1  #逻辑已删除值(默认为 1)
      logic-not-delete-value: 0  #逻辑未删除值(默认为 0)
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: false
    call-setters-on-nulls: true

# 日志
logging:
  level:
    root: warn
    top.plgxs.mbg.mapper: trace
  pattern:
    console: '%p%m%n'

3、配置mybatis-plus分页插件

​ 在random-admin下新建MybatisPlusConfig类,配置分页插件:

(ps:注意PaginationInterceptor的jar包路径,别引错了;另外这个文件之前放在mbg模块下但分页不好使,所以放在admin模块下了,应该是mbg没有引spring web依赖的问题)

package top.plgxs.admin.config;

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * <p>mybatis-plus配置</p>
 * @author Stranger。
 * @since 2020-12-22
 */
@Configuration
public class MybatisPlusConfig {

    /**
     * 分页插件
     *
     * @return PaginationInterceptor
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    /**
     * 乐观锁插件,秒杀业务使用
     *
     * @return
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

}

4、配置mybatis-plus generator

​ 相关的配置文件包括MybatisPlusGenerator和多个freemarker模板文件,在MybatisPlusGenerator中执行main方法就可以生成Controller、Service、Impl、mapper和xml。

​ 其中模板文件是根据我自己的项目进行配置的,controller.java.ftl中包含我自定义的通用返回对象,如果你不是用我的项目,请稍微改一下(包括:包名、通用返回对象等)。
在这里插入图片描述

MybatisPlusGenerator.java的内容如下:

package top.plgxs.mbg;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.HashMap;
import java.util.Map;

/**
 * mybatis-plus generator自动生成代码
 * @author Stranger。
 * @date 2020/12/22 
 */
public class MyBatisPlusGenerator {
    /**
     * 数据库类型
     */
    private DbType dbType = DbType.MYSQL;

    /**
     * 数据库连接信息
     */
    private String dbUrl = "jdbc:mysql://localhost:3306/random?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2b8";
    private String driver = "com.mysql.cj.jdbc.Driver";
    private String userName = "random";
    private String password = "random";

    /**
     * 指定生成的表名。如果想生成整个库的,这里设为null即可
     */
    /*private String[] tableNames = new String[]{
            "tb_resource",
            "t_order"
    };*/


    private String[] tableNames = new String[]{
    };

    /**
     * 输出路径(当前为项目根目录下)
     * 例如:F:\ideaProject\random
     */
    private String outputDir = System.getProperty("user.dir");

    /**
     * 公共包名
     */
    private String packageName = "top.plgxs";

    /**
     * 公共包名路径
     */
    private String packagePath = "/top/plgxs";

    /**
     * 实体分类存放,如以sys_开头的表统一放在sys包下
     */
    private String commonPackageName = "sys";

    /**
     * controller基础类
     */
    private String superControllerClass = packageName + ".common.BaseController";

    /**
     * entity基础类
     */
    private String superEntityClass = packageName + ".common.BaseEntity";

    /**
     * mbg模块包名
     */
    private String mbgPackageName = packageName + ".mbg";

    /**
     * mbg模块路径
     */
    private String mbgModulePath = "/random-mbg";

    /**
     * mbg模块的包名路径
     */
    private String mbgModulePackagePath = packagePath + "/mbg";

    /**
     * admin模块包名
     */
    private String adminPackageName = packageName + ".admin";

    /**
     * admin模块路径
     */
    private String adminModulePath = "/random-admin";

    /**
     * admin模块的包名路径
     */
    private String adminModulePackagePath = packagePath + "/admin";

    /**
     * 作者名
     */
    private String author = "Stranger";

    /**
     * 逻辑删除属性名称
     * 0-正常,1-逻辑删除
     */
    private String deleteFieldName = "status";

    /**
     * 生成代码的调用方法
     */
    public void generateCode() {
        generateByTables(tableNames);
    }

    /**
     * 根据表自动生成
     *
     * @param tableNames 表名
     */
    private void generateByTables(String... tableNames) {
        //配置数据源
        DataSourceConfig dataSourceConfig = getDataSourceConfig();
        // 策略配置
        StrategyConfig strategyConfig = getStrategyConfig(tableNames);
        //全局变量配置
        GlobalConfig globalConfig = getGlobalConfig();
        //包名配置
        PackageConfig packageConfig = getPackageConfig();
        //自主配置
        InjectionConfig injectionConfig = getInjectionConfig();
        //自动生成
        atuoGenerator(dataSourceConfig, strategyConfig, globalConfig, packageConfig,injectionConfig);
    }

    /**
     * 集成
     *
     * @param dataSourceConfig 配置数据源
     * @param strategyConfig   策略配置
     * @param config           全局变量配置
     * @param packageConfig    包名配置
     */
    private void atuoGenerator(DataSourceConfig dataSourceConfig, StrategyConfig strategyConfig,
                               GlobalConfig config, PackageConfig packageConfig, InjectionConfig injectionConfig) {
        TemplateConfig tc = new TemplateConfig();

        // 配置自定义输出模板
        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";
        //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        String templatePathController = "/templates/controller.java";
        String templatePathService = "/templates/service.java";
        String templatePathServiceImpl = "/templates/serviceImpl.java";
        String templatePathEntity = "/templates/entity.java";
        String templatePathMapper = "/templates/mapper.java";
        String templatePathMapperXML = "/templates/mapper.xml";

        tc.setController(templatePathController);
        tc.setService(templatePathService);
        tc.setServiceImpl(templatePathServiceImpl);
        tc.setEntity(templatePathEntity);
        tc.setMapper(templatePathMapper);
        tc.setXml(templatePathMapperXML);

        new AutoGenerator()
                .setGlobalConfig(config)
                .setDataSource(dataSourceConfig)
                .setStrategy(strategyConfig)
                .setPackageInfo(packageConfig)
                .setTemplateEngine(new FreemarkerTemplateEngine())
                //.setTemplateEngine(new VelocityTemplateEngine()).setTemplate(tc)
                .setCfg(injectionConfig)
                .execute();
    }

    /**
     * 设置包名
     *
     * @return PackageConfig 包名配置
     */
    private PackageConfig getPackageConfig() {
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(null); //模块名
        pc.setParent(null); //具体包,类似:top.plgxs
        //entity mapper层统一放在mbg模块下
        HashMap<String, String> pathMap = CollectionUtils.newHashMapWithExpectedSize(6);
        pathMap.put(ConstVal.ENTITY_PATH, outputDir + mbgModulePath + "/src/main/java" +
                mbgModulePackagePath + "/entity/" + commonPackageName);

        pathMap.put(ConstVal.MAPPER_PATH, outputDir + mbgModulePath + "/src/main/java" +
                mbgModulePackagePath + "/mapper/" + commonPackageName);

        pathMap.put(ConstVal.XML_PATH, outputDir + mbgModulePath + "/src/main/resources/mapper/"+commonPackageName);

        //controller service impl放在其他模块
        pathMap.put(ConstVal.CONTROLLER_PATH, outputDir + adminModulePath + "/src/main/java" +
                adminModulePackagePath + "/controller/" + commonPackageName);


        pathMap.put(ConstVal.SERVICE_PATH, outputDir + adminModulePath + "/src/main/java" +
                adminModulePackagePath + "/service/" + commonPackageName);

        pathMap.put(ConstVal.SERVICE_IMPL_PATH, outputDir + adminModulePath + "/src/main/java" +
                adminModulePackagePath + "/service/impl/" + commonPackageName);

        pc.setPathInfo(pathMap);
        return pc;
    }

    /**
     * 全局配置
     *
     * @return GlobalConfig
     */
    private GlobalConfig getGlobalConfig() {
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig
                // 开启swagger
                .setSwagger2(true)
                .setActiveRecord(true)
                .setBaseColumnList(true)
                .setBaseResultMap(true)
                //作者
                .setAuthor(author)
                //设置输出路径
                .setOutputDir(outputDir)
                //是否覆盖已有文件
                .setFileOverride(true);

        // 自定义命名方式
        globalConfig.setEntityName("%s");
        globalConfig.setMapperName("%sMapper");
        globalConfig.setXmlName("%sMapper");
        globalConfig.setServiceName("%sService");
        globalConfig.setServiceImplName("%sServiceImpl");
        globalConfig.setControllerName("%sController");

        return globalConfig;
    }

    /**
     * 策略配置
     *
     * @param tableNames 表名
     * @return StrategyConfig
     */
    private StrategyConfig getStrategyConfig(String... tableNames) {
        StrategyConfig strategy = new StrategyConfig();
        //从数据库表到文件的命名策略
        strategy.setNaming(NamingStrategy.underline_to_camel)
                // 表前缀
                .setTablePrefix(new String[] {"t_","T_"})
                // rest风格
                .setRestControllerStyle(false)
                // 字段注解
                .setEntityTableFieldAnnotationEnable(true)
                // 使用lombok
                .setEntityLombokModel(true)
                // 需要生成的的表名,多个表名传数组
                .setInclude(tableNames)
                // 生成序列号
                .setEntitySerialVersionUID(true)
                // 逻辑删除属性名称
                .setLogicDeleteFieldName(deleteFieldName)
                // 驼峰转连字符,用于controller的RequestMapping。例如: 表名sys_user,为true则转为sys-user,
                .setControllerMappingHyphenStyle(false);

        // 自定义实体父类
        // strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
        // 自定义实体,公共字段
        // strategy.setSuperEntityColumns(new String[] { "create_time", "create_username" });
        // 自定义 controller 父类
        // strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
        // 还有自定义service/mapper等
        return strategy;
    }

    /**
     * 配置数据源
     *
     * @return 数据源配置 DataSourceConfig
     */
    private DataSourceConfig getDataSourceConfig() {
        return new DataSourceConfig().setDbType(dbType)
                .setUrl(dbUrl)
                .setUsername(userName)
                .setPassword(password)
                .setDriverName(driver);
    }

    // 自定义配置
    private InjectionConfig getInjectionConfig(){
        InjectionConfig cfg = new InjectionConfig() {
            //自定义属性注入:abc
            //在.ftl(或者是.vm)模板中,通过${cfg.abc}获取属性
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<>();
                // 实体类的package
                map.put("customEntityPackage", mbgPackageName
                        + ".entity." + commonPackageName);
                // mapper的package
                map.put("customMapperPackage", mbgPackageName
                        + ".mapper." + commonPackageName);
                // controller的package
                map.put("customControllerPackage", adminPackageName
                        + ".controller." + commonPackageName);
                // service的package
                map.put("customServicePackage", adminPackageName
                        + ".service." + commonPackageName);
                // serviceimpl的package
                map.put("customServiceImplPackage", adminPackageName
                        + ".service.impl." + commonPackageName);

                this.setMap(map);
            }
        };
        return cfg;
    }


	// 执行main方法自动生成代码
    public static void main(String[] args) {
        new MyBatisPlusGenerator().generateCode();
    }
}

controller.java.ftl中添加了新增、修改、删除与分页查询,内容如下:

(ps:所有ftl文件中的${cfg.xxx}都是在MybatisPlusGenerator中的自定义配置部分进行设置的)

package ${cfg.customControllerPackage};

import javax.annotation.Resource;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import ${cfg.customServicePackage}.${table.serviceName};
import top.plgxs.common.api.ResultInfo;
import ${cfg.customEntityPackage}.${entity};
<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;
</#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>

/**
 * <p>
 * ${table.comment!} 前端控制器
 * </p>
 *
 * @author ${author}
 * @since ${date}
 * @version 1.0
 */
<#if restControllerStyle>
@RestController
<#else>
@Controller
</#if>
@RequestMapping("<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
<#if kotlin>
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if>
<#else>
<#if superControllerClass??>
public class ${table.controllerName} extends ${superControllerClass} {
<#else>
public class ${table.controllerName} {
</#if>
    @Resource
    private ${table.serviceName} ${table.serviceName ? uncap_first};

    /**
     * 分页查询列表
     * @param query 查询条件
     * @param pageNo 第几页
     * @param pageSize 每页几条
     * @return
     * @author ${author}
     * @since ${date}
     */
    @GetMapping("/list")
    @ResponseBody
    public ResultInfo<IPage<${entity}>> queryPageList(@RequestParam("query") String query, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                    @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize){
        QueryWrapper<${entity}> queryWrapper = new QueryWrapper<>();
        //TODO 查询条件
        Page<${entity}> page = new Page<>(pageNo, pageSize);
        IPage<${entity}> pageList = ${table.serviceName ? uncap_first}.page(page, queryWrapper);
        return ResultInfo.success(pageList);
    }

    /**
     * 插入一条数据
     * @param ${entity?uncap_first}
     * @return top.plgxs.common.api.ResultInfo<java.lang.Object>
     * @author ${author}
     * @since ${date}
     */
    @PostMapping("/insert")
    @ResponseBody
    public ResultInfo<Object> insert(@RequestBody ${entity} ${entity?uncap_first}){
        boolean result = ${table.serviceName ? uncap_first}.save(${entity?uncap_first});
        if(result){
            return ResultInfo.success();
        }else{
            return ResultInfo.failed();
        }
    }

    /**
     * 更新一条数据
     * @param ${entity?uncap_first}
     * @return top.plgxs.common.api.ResultInfo<java.lang.Object>
     * @author ${author}
     * @since ${date}
     */
    @PostMapping("/update")
    @ResponseBody
    public ResultInfo<Object> update(@RequestBody ${entity} ${entity?uncap_first}){
        if(${entity?uncap_first} == null || StringUtils.isBlank(${entity?uncap_first}.getId())){
            return ResultInfo.validateFailed();
        }
        boolean result = ${table.serviceName ? uncap_first}.updateById(${entity?uncap_first});
        if(result){
            return ResultInfo.success();
        }else{
            return ResultInfo.failed();
        }
    }

    /**
     * 逻辑删除一条数据
     * @param id 主键
     * @return top.plgxs.common.api.ResultInfo<java.lang.Object>
     * @author ${author}
     * @since ${date}
     */
    @GetMapping("/delete/{id}")
    @ResponseBody
    public ResultInfo<Object> delete(@PathVariable("id") String id){
        if(StringUtils.isBlank(id)){
            return ResultInfo.validateFailed();
        }
        boolean result = ${table.serviceName ? uncap_first}.removeById(id);
        if(result){
            return ResultInfo.success();
        }else{
            return ResultInfo.failed();
        }
    }
}
</#if>

entity.java.ftl中集成了lombok与swagger,内容如下:

package ${cfg.customEntityPackage};

<#list table.importPackages as pkg>
import ${pkg};
</#list>
<#if swagger2>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Data;
import lombok.EqualsAndHashCode;
    <#if chainModel>
import lombok.experimental.Accessors;
    </#if>
</#if>

/**
 * <p>
 * ${table.comment!}
 * </p>
 *
 * @author ${author}
 * @since ${date}
 * @version 1.0
 */
<#if entityLombokModel>
@Data
    <#if superEntityClass??>
@EqualsAndHashCode(callSuper = true)
    <#else>
@EqualsAndHashCode(callSuper = false)
    </#if>
    <#if chainModel>
@Accessors(chain = true)
    </#if>
</#if>
<#if table.convert>
@TableName("${table.name}")
</#if>
<#if swagger2>
@ApiModel(value="${entity}对象", description="${table.comment!}")
</#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#else>
public class ${entity} implements Serializable {
</#if>

<#if entitySerialVersionUID>
    private static final long serialVersionUID = 1L;
</#if>
<#-- ----------  BEGIN 字段循环遍历  ---------->
<#list table.fields as field>
    <#if field.keyFlag>
        <#assign keyPropertyName="${field.propertyName}"/>
    </#if>

    <#if field.comment!?length gt 0>
        <#if swagger2>
    @ApiModelProperty(value = "${field.comment}")
        <#else>
    /**
     * ${field.comment}
     */
        </#if>
    </#if>
    <#if field.keyFlag>
    <#-- 主键 -->
        <#if field.keyIdentityFlag>
    @TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
        <#elseif idType??>
    @TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
        <#elseif field.convert>
    @TableId("${field.annotationColumnName}")
        </#if>
    <#-- 普通字段 -->
    <#elseif field.fill??>
    <#-- -----   存在字段填充设置   ----->
        <#if field.convert>
    @TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill})
        <#else>
    @TableField(fill = FieldFill.${field.fill})
        </#if>
    <#elseif field.convert>
    @TableField("${field.annotationColumnName}")
    </#if>
<#-- 乐观锁注解 -->
    <#if (versionFieldName!"") == field.name>
    @Version
    </#if>
<#-- 逻辑删除注解 -->
    <#if (logicDeleteFieldName!"") == field.name>
    @TableLogic
    </#if>
    private ${field.propertyType} ${field.propertyName};
</#list>
<#------------  END 字段循环遍历  ---------->

<#if !entityLombokModel>
    <#list table.fields as field>
        <#if field.propertyType == "boolean">
            <#assign getprefix="is"/>
        <#else>
            <#assign getprefix="get"/>
        </#if>
    public ${field.propertyType} ${getprefix}${field.capitalName}() {
        return ${field.propertyName};
    }

        <#if chainModel>
    public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
        <#else>
    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
        </#if>
        this.${field.propertyName} = ${field.propertyName};
        <#if chainModel>
        return this;
        </#if>
    }
    </#list>
</#if>

<#if entityColumnConstant>
    <#list table.fields as field>
    public static final String ${field.name?upper_case} = "${field.name}";

    </#list>
</#if>
<#if activeRecord>
    @Override
    protected Serializable pkVal() {
    <#if keyPropertyName??>
        return this.${keyPropertyName};
    <#else>
        return null;
    </#if>
    }

</#if>
<#if !entityLombokModel>
    @Override
    public String toString() {
        return "${entity}{" +
    <#list table.fields as field>
        <#if field_index==0>
            "${field.propertyName}=" + ${field.propertyName} +
        <#else>
            ", ${field.propertyName}=" + ${field.propertyName} +
        </#if>
    </#list>
        "}";
    }
</#if>
}

mapper.java.ftl内容如下:

package ${cfg.customMapperPackage};

import ${cfg.customEntityPackage}.${entity};
import ${superMapperClassPackage};
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * <p>
 * ${table.comment!} Mapper 接口
 * </p>
 *
 * @author ${author}
 * @since ${date}
 * @version 1.0
 */
<#if kotlin>
interface ${table.mapperName} : ${superMapperClass}<${entity}>
<#else>
@Repository("${table.mapperName?uncap_first}")
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {

    /**
     * 分页数据查询
     * @param ${entity?uncap_first}
     * @return
     * @author ${author}
     * @date ${date}
     */
    List<${entity}> select${entity}List(${entity} ${entity?uncap_first});
}
</#if>

mapper.xml.ftl内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${cfg.customMapperPackage}.${table.mapperName}">

<#if enableCache>
    <!-- 开启二级缓存 -->
    <cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>

</#if>
<#if baseResultMap>
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="${cfg.customEntityPackage}.${entity}">
        <#list table.fields as field>
            <#if field.keyFlag><#--生成主键排在第一位-->
        <id column="${field.name}" property="${field.propertyName}" />
            </#if>
        </#list>
<#list table.commonFields as field><#--生成公共字段 -->
    <result column="${field.name}" property="${field.propertyName}" />
</#list>
<#list table.fields as field>
    <#if !field.keyFlag><#--生成普通字段 -->
        <result column="${field.name}" property="${field.propertyName}" />
    </#if>
</#list>
    </resultMap>

</#if>
<#if baseColumnList>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        <#list table.commonFields as field>
            ${field.name},
        </#list>
        ${table.fieldNames}
    </sql>

</#if>
    <select id="select${entity}List" parameterType="${cfg.customEntityPackage}.${entity}" resultType="${cfg.customEntityPackage}.${entity}">
        select <include refid="Base_Column_List"/>
        from ${table.name} t
        where 1 = 1
        <#list table.fields as field>
            <#if field.type?contains('char')>
            <if test="${field.propertyName} != null and ${field.propertyName} != ''">
                and t.${field.name} = ${r'#{'}${field.propertyName}}
            </if>
            <#elseif field.type?contains('text')>
            <if test="${field.propertyName} != null and ${field.propertyName} != ''">
                and t.${field.name} like concat('%',  ${r'#{'}${field.propertyName}}, '%')
            </if>
            <#else>
            <if test="${field.propertyName} != null">
                and t.${field.name} = ${r'#{'}${field.propertyName}}
            </if>
            </#if>
        </#list>
    </select>
</mapper>

service.java.ftl内容如下:

package ${cfg.customServicePackage};

import ${cfg.customEntityPackage}.${entity};
import ${superServiceClassPackage};

import java.util.List;

/**
 * <p>
 * ${table.comment!} 服务类
 * </p>
 *
 * @author ${author}
 * @since ${date}
 * @version 1.0
 */
<#if kotlin>
interface ${table.serviceName} : ${superServiceClass}<${entity}>
<#else>
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
    /**
     * 数据查询列表
     * @return
     * @author ${author}
     * @date ${date}
     */
    List<${entity}> get${entity}List();
}
</#if>

serviceImpl.java.ftl内容如下:

package ${cfg.customServiceImplPackage};

import ${cfg.customEntityPackage}.${entity};
import ${cfg.customMapperPackage}.${table.mapperName};
import ${cfg.customServicePackage}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * ${table.comment!} 服务实现类
 * </p>
 *
 * @author ${author}
 * @since ${date}
 * @version 1.0
 */
@Service
<#if kotlin>
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} {

}
<#else>
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} {
    @Resource
    private ${table.mapperName} ${table.mapperName?uncap_first};

    @Override
    public List<${entity}> get${entity}List() {
        return ${table.mapperName?uncap_first}.select${entity}List(null);
    }
}
</#if>

5、配置通用返回对象(可省略)

​ 如果你在controller.java.ftl中将ResultInfo相关的东西删掉,那么这部分就可以不用配置了,否则执行generator后生成的代码会报错。

​ 在random-common中新建通用返回对象ResultInfo和常用返回代码ResultCode。

ResultInfo.java

package top.plgxs.common.api;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;

/**
 * <p>通用返回对象</p>
 *
 * @author Stranger。
 * @since 2020/12/23 15:13
 * @version 1.0
 */
@Data
@ApiModel(value="通用返回对象", description="通用返回对象")
public class ResultInfo<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 成功标志
     */
    @ApiModelProperty(value = "成功标志")
    private boolean success = true;

    /**
     * 返回处理消息
     */
    @ApiModelProperty(value = "返回处理消息")
    private String message = "操作成功!";

    /**
     * 返回代码
     */
    @ApiModelProperty(value = "返回代码")
    private Integer code = 0;

    /**
     * 返回数据对象 data
     */
    @ApiModelProperty(value = "返回数据对象")
    private T data;

    /**
     * 时间戳
     */
    @ApiModelProperty(value = "时间戳")
    private long timestamp = System.currentTimeMillis();

    public ResultInfo() {

    }

    /**
     * 成功返回结果
     * @author Stranger。
     * @since 2020/12/23 16:05
     */
    public static <T> ResultInfo<T> success(){
        return success(ResultCode.SUCCESS.getMessage(),null);
    }

    /**
     * 成功返回结果
     * @param data 返回的数据
     * @author Stranger。
     * @since 2020/12/23 0023 16:06
     */
    public static<T> ResultInfo<T> success(T data) {
        return success(ResultCode.SUCCESS.getMessage(),data);
    }

    /**
     * 成功返回结果
     * @param msg 提示信息
     * @param data 返回的数据
     * @author Stranger。
     * @since 2020/12/23 16:09
     */
    public static<T> ResultInfo<T> success(String msg, T data) {
        ResultInfo<T> r = new ResultInfo<T>();
        r.setSuccess(true);
        r.setCode(ResultCode.SUCCESS.getCode());
        r.setMessage(msg);
        r.setData(data);
        return r;
    }

    /**
     * 失败返回结果
     * @author Stranger。
     * @since 2020/12/23 16:10
     */
    public static <T> ResultInfo<T> failed() {
        return failed(ResultCode.FAILED.getMessage());
    }

    /**
     * 失败返回结果
     * @param message 错误信息
     * @author Stranger。
     * @since 2020/12/23 16:10
     */
    public static<T> ResultInfo<T> failed(String message) {
        return failed(ResultCode.FAILED.getCode(), message);
    }

    /**
     * 失败返回结果
     * @param code 错误码
     * @param message 错误信息
     * @author Stranger。
     * @since 2020/12/23 16:10
     */
    public static<T> ResultInfo<T> failed(int code, String message) {
        ResultInfo<T> r = new ResultInfo<>();
        r.setCode(code);
        r.setMessage(message);
        r.setSuccess(false);
        return r;
    }

    /**
     * 参数验证失败返回结果
     * @author Stranger。
     * @since 2020/12/23 16:12
     */
    public static<T> ResultInfo<T> validateFailed() {
        return validateFailed(ResultCode.VALIDATE_FAILED.getMessage());
    }

    /**
     * 参数验证失败返回结果
     * @param message 错误信息
     * @author Stranger。
     * @since 2020/12/23 16:12
     */
    public static<T> ResultInfo<T> validateFailed(String message) {
        return failed(ResultCode.VALIDATE_FAILED.getCode(),message);
    }
    /**
     * 未登录返回结果
     * @author Stranger。
     * @since 2020/12/23 16:12
     */
    public static <T> ResultInfo<T> unauthorized() {
        return failed(ResultCode.UNAUTHORIZED.getCode(),ResultCode.UNAUTHORIZED.getMessage());
    }

    /**
     * 未授权返回结果
     * @author Stranger。
     * @since 2020/12/23 16:12
     */
    public static <T> ResultInfo<T> forbidden() {
        return failed(ResultCode.FORBIDDEN.getCode(),ResultCode.FORBIDDEN.getMessage());
    }

}

ResultCode.java

package top.plgxs.common.api;

/**
 * <p>常用API操作码</p>
 *
 * @author Stranger。
 * @since 2020/12/23 15:30
 * @version 1.0
 */
public enum ResultCode {

    SUCCESS(200, "操作成功"),
    FAILED(500, "操作失败"),
    VALIDATE_FAILED(404, "参数检验失败"),
    UNAUTHORIZED(401, "暂未登录或token已经过期"),
    FORBIDDEN(403, "没有相关权限,请联系管理员");

    private Integer code;
    private String message;

    ResultCode(Integer code, String message){
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

6、在启动器上配置扫描mapper

​ 在random-admin的启动类上加mapper扫描注解,启动后可以用postman测试一下。

package top.plgxs.admin;

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

@SpringBootApplication
@MapperScan("top.plgxs.mbg.mapper")
@EnableTransactionManagement
public class RandomAdminApplication {

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

}
7、展示下生成的项目结构

在这里插入图片描述
在这里插入图片描述

8、附赠用于generator的表结构
CREATE TABLE `t_sys_user` (
  `id` varchar(32) NOT NULL COMMENT '主键uuid',
  `username` varchar(50) DEFAULT NULL COMMENT '用户名',
  `password` varchar(255) DEFAULT NULL COMMENT '密码md5',
  `mobile` varchar(50) DEFAULT NULL COMMENT '手机号',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
  `gender` int(1) DEFAULT '0' COMMENT '性别,0-保密,1-男,2-女',
  `realname` varchar(50) DEFAULT NULL COMMENT '真实姓名',
  `id_number` varchar(255) DEFAULT NULL COMMENT '身份证号',
  `head_url` varchar(255) DEFAULT NULL COMMENT '头像url',
  `register_time` datetime DEFAULT NULL COMMENT '注册时间',
  `login_number` bigint(11) DEFAULT NULL COMMENT '登录次数',
  `last_login_time` datetime DEFAULT NULL COMMENT '最后登录时间',
  `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `status` varchar(1) DEFAULT '0' COMMENT '状态,1-冻结,0-正常',
  `mobile_verification_code` varchar(10) DEFAULT NULL COMMENT '手机验证码',
  `email_verification_code` varchar(10) DEFAULT NULL COMMENT '邮箱验证码',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户';

项目地址 https://gitee.com/lp1791803611/random

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Stranger。

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

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

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

打赏作者

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

抵扣说明:

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

余额充值