乐趣区

关于后端:优雅详细的mybatisplus代码生成器生成代码

代码生成器

1、导入依赖
<!-- 导入 mybatisplus 依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

<!--        代码生成器 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.1</version>
        </dependency>
<!--        freemarker 模板 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
            <version>2.6.7</version>
        </dependency>

<!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.12</version>
        </dependency>
2、application.yaml 配置及对应配置类
spring:
  # 数据库配置
  datasource:
    url: jdbc:mysql://localhost:3306/walker_shiro?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimeZone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

# 代码生成器相干配置
code-generator:
  parent: com.walker.shiro # 父包
  author: walker # 作者名称
  moduleName: business # 模块名称
  controllerName: domain.controller # controller 的地位
  serviceName: domain.service #service 的地位
  serviceImplName: domain.service.impl # service 实现类地位
  entityName: domain.model # 数据库实体类地位
  mapperName: domain.mapper # mapper 地位
  formatEntity: "%s" # entity 的名称
  formatService: "%sService" # service 名称
  formatServiceImpl: "%sServiceImpl" # service 实现类名称
  enableSwagger: false # 是否开启 swagger

CodeGeneratorProperties 类
这个用于代码生成器的相干配置

package com.walker.shiro.common.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "code-generator")
public class CodeGeneratorProperties {
    private String parent;
    private String author;
    private String moduleName;
    private String controllerName;
    private String serviceName;
    private String serviceImplName;
    private String entityName;
    private String mapperName;
    private String formatEntity;
    private String formatService;
    private String formatServiceImpl;
    private Boolean enableSwagger;
}

DatasourceProperties
用于获取数据库配置

package com.walker.shiro.common.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


/**
* spring:
 *   application:
 *     name: walker-dianping
 *   datasource:
 *     driver-class-name: com.mysql.cj.jdbc.Driver
 *     url: jdbc:mysql://114.132.164.230:3306/walker-dianping?serverTimezone=UTC
 *     username: root
 *     password: walker123
*/
@Component
@Data
@ConfigurationProperties(prefix = "spring.datasource")
public class DatasourceProperties {
    private String driverClassName;
    private String url;
    private String username;
    private String password;

}
3、工具类封装

次要分为:

  • 全局配置,留神,如果要开启 swagger 的话,记得导入 swagger 的依赖,或者导入 knife4j
  • 包配置,次要用于配置包的门路,文件的门路
  • 策略配置
  • 应用模板:个别有两种,一种是 freemarker,一种是 velocity,咱们这里应用的是 freemarker,所以记得导入对应的依赖,否则会产生报错

    package com.walker.shiro.common.utils;
    
    import com.baomidou.mybatisplus.generator.FastAutoGenerator;
    import com.baomidou.mybatisplus.generator.config.OutputFile;
    import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
    import com.walker.shiro.common.properties.CodeGeneratorProperties;
    import com.walker.shiro.common.properties.DatasourceProperties;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.Collections;
    
    @Service
    public class MyCodeGenerator {
    
    
      @Resource
      private DatasourceProperties datasourceProperties;
      @Autowired
      private CodeGeneratorProperties codeGeneratorProperties;
    
    
      /**
      * 能够先应用 show tables 查询数据库所有的表,而后复制到该办法进行执行,* 应用 \n 进行分隔,不须要手动去将字符串转为逗号隔开的模式
      */
      public void generate(String tables) {String[] tablenames = tables.split("\n");
          generateCode(tablenames);
      }
    
      /**
       * 依据表名生成对应的实体类
       * tableName: 表的名称
       */
      public void generateCode(String... tableName) {
          //xml 生成的地位
          String xmlPath = this.getClass().getResource("/").getPath();
          // 输入地址,这里是生成在 target 中
          String outputUrl = this.getClass().getResource("/").getPath();
          FastAutoGenerator.create(datasourceProperties.getUrl(),
                  datasourceProperties.getUsername(),
                  datasourceProperties.getPassword())
    //    全局根底配置
                  .globalConfig(builder -> {builder.author(codeGeneratorProperties.getAuthor()) // 设置作者
    
                              .fileOverride() // 笼罩已生成文件
                              .outputDir(outputUrl); // 指定输入目录
    
                      // 开启 swagger 模式
                      if (codeGeneratorProperties.getEnableSwagger()) {builder.enableSwagger();
                      }
    
                  })
    //  包配置
                  .packageConfig(builder -> {builder.parent(codeGeneratorProperties.getParent()) // 设置父包名
                              .moduleName(codeGeneratorProperties.getModuleName()) // 设置父包模块名
                              .controller(codeGeneratorProperties.getControllerName())
                              .service(codeGeneratorProperties.getServiceName())
                              .serviceImpl(codeGeneratorProperties.getServiceImplName())
                              .mapper(codeGeneratorProperties.getMapperName())
                              .entity(codeGeneratorProperties.getEntityName())
                              .pathInfo(Collections.singletonMap(OutputFile.mapperXml,
                                      xmlPath)); // 设置 mapperXml 生成门路
                  })
    //                策略配置
                  .strategyConfig(builder -> {builder.addInclude(tableName)
                              .entityBuilder()
                              .formatFileName(codeGeneratorProperties.getFormatEntity())
                              .enableLombok() // 开启 lombok
                              .controllerBuilder()
                              .enableRestStyle()
                              .serviceBuilder()
                              .formatServiceFileName(codeGeneratorProperties.getFormatService())
                              .formatServiceImplFileName(codeGeneratorProperties.getFormatServiceImpl())
    
                      ;
                      // 设置须要生成的表名
    //               addTablePrefix("t_", "c_"); // 设置过滤表前缀
                  })
    
    
                  .templateEngine(new FreemarkerTemplateEngine()) // 应用 Freemarker 引擎模板,默认的是 Velocity 引擎模板
    //                .templateEngine(new VelocityTemplateEngine())
                  .execute();}
    
    
    }
    
4、测试代码生成
  • 首先是创立数据库,而后建表,这里提供我的 sql 作为案例进行测试

    CREATE TABLE sys_user(
                           id INT NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
                           name VARCHAR(32)    COMMENT '姓名' ,
                           username VARCHAR(32)    COMMENT '用户名' ,
                           password VARCHAR(32)    COMMENT '明码' ,
                           create_by VARCHAR(32)    COMMENT '创建人' ,
                           create_time DATETIME    COMMENT '创立工夫' ,
                           update_by VARCHAR(32)    COMMENT '更新人' ,
                           update_time DATETIME    COMMENT '更新工夫' ,
                           PRIMARY KEY (id)
    ) COMMENT = '用户表';/*SQL@Run*/
    ALTER TABLE sys_user COMMENT '用户表';/*SQL@Run*/
    CREATE TABLE sys_role(
                           id INT NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
                           name VARCHAR(32)    COMMENT '名称' ,
                           create_by VARCHAR(32)    COMMENT '创建人' ,
                           create_time DATETIME    COMMENT '创立工夫' ,
                           update_by VARCHAR(32)    COMMENT '更新人' ,
                           update_time DATETIME    COMMENT '更新工夫' ,
                           PRIMARY KEY (id)
    ) COMMENT = '角色表';/*SQL@Run*/
    ALTER TABLE sys_role COMMENT '角色表';/*SQL@Run*/
    CREATE TABLE sys_user_role(
                                id INT NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
                                user_id VARCHAR(32)    COMMENT '用户 id' ,
                                role_id VARCHAR(32)    COMMENT '角色 id' ,
                                create_by VARCHAR(32)    COMMENT '创建人' ,
                                create_time DATETIME    COMMENT '创立工夫' ,
                                update_by VARCHAR(32)    COMMENT '更新人' ,
                                update_time DATETIME    COMMENT '更新工夫' ,
                                PRIMARY KEY (id)
    ) COMMENT = '用户 - 角色关联表';/*SQL@Run*/
    ALTER TABLE sys_user_role COMMENT '用户 - 角色关联表';/*SQL@Run*/
    CREATE TABLE sys_menu(
                           id INT NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
                           name VARCHAR(32)    COMMENT '名称' ,
                           path VARCHAR(32)    COMMENT '门路' ,
                           perm VARCHAR(32)    COMMENT '权限' ,
                           create_by VARCHAR(32)    COMMENT '创建人' ,
                           create_time DATETIME    COMMENT '创立工夫' ,
                           update_by VARCHAR(32)    COMMENT '更新人' ,
                           update_time DATETIME    COMMENT '更新工夫' ,
                           PRIMARY KEY (id)
    ) COMMENT = '菜单';/*SQL@Run*/
    ALTER TABLE sys_menu COMMENT '菜单';/*SQL@Run*/
    CREATE TABLE sys_role_menu(
                                id INT NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
                                role_id VARCHAR(32)    COMMENT '角色 id' ,
                                menu_id VARCHAR(32)    COMMENT '菜单 id' ,
                                create_by VARCHAR(32)    COMMENT '创建人' ,
                                create_time DATETIME    COMMENT '创立工夫' ,
                                update_by VARCHAR(32)    COMMENT '更新人' ,
                                update_time DATETIME    COMMENT '更新工夫' ,
                                PRIMARY KEY (id)
    ) COMMENT = '角色 - 菜单 - 关联表';/*SQL@Run*/
    ALTER TABLE sys_role_menu COMMENT '角色 - 菜单 - 关联表';/*SQL@Run*/
    
  • 获取须要生成代码的表的名称,进行复制,如果是第一次生成代码,须要生成全副的代码,能够应用 sql 指令 show tables将全副的表名进行复制,而后将该复制的表明放到上面的测试方法中

    sys_menu
    sys_role
    sys_role_menu
    sys_user
    sys_user_role
  • 编写测试类

记得须要要在 test/java 中进行编写

package com.walker.shiro;

import com.walker.shiro.common.utils.MyCodeGenerator;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class CodeGenerateTest {

    @Autowired
    private MyCodeGenerator myCodeGenerator;

    @Test
    void generatorCode() {
        // 该办法应用 \n 进行宰割
        myCodeGenerator.generate("sys_menu\n" +
                "sys_role\n" +
                "sys_role_menu\n" +
                "sys_user\n" +
                "sys_user_role");
    }
}
  • 查看后果

执行办法之后,能够发现在 /target/test-classes 下依照咱们配置的门路就会生成代码了

之后将代码复制到咱们想到的门路下就 ok 了

将文件生成之后放在 test-classes 中的目标,就是为了避免新生成代码间接将原来的代码间接笼罩了,这样是挺危险的,所以还是学生成在 test-classes 之后再进行复制会绝对平安一些。

5、测试执行 mybatisplus 是否可行

先新增一条数据,而后再查问该数据

package com.walker.shiro;

import com.alibaba.fastjson.JSON;
import com.walker.shiro.domain.model.SysUser;
import com.walker.shiro.domain.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@Slf4j
@SpringBootTest
public class MybatisplusTest {

    @Autowired
    private SysUserService sysUserService;

    @Test
    void test(){SysUser sysUser = new SysUser();
        sysUser.setName("walker");
        sysUser.setUsername("walker");
        sysUserService.save(sysUser);

        SysUser user = sysUserService.getById(sysUser.getId());
        log.info("返回用户信息 {}", JSON.toJSONString(user));
    }
}
  • 返回后果

    返回用户信息 {"id":1,"name":"walker","username":"walker"}

    有返回对应的后果,是没有问题的

本文由 mdnice 多平台公布

退出移动版