mybatis-plus-generator代码生成器

一、前言

在阿里巴巴Java开发手册中对工程结构进行如下分层

1.1 应用分层

在这里插入图片描述

  • 开放接口层:可直接封装 Service 方法暴露成 RPC 接口;通过 Web 封装成 http 接口;进行网关安全控制、流量控制等
  • 终端显示层:各个端的模板渲染并执行显示的层。当前主要是 velocity 渲染,JS 渲染,JSP 渲染,移动端展示等。
  • Web 层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。
  • Service 层:相对具体的业务逻辑服务层。
  • Manager 层:通用业务处理层,它有如下特征:
    1) 对第三方平台封装的层,预处理返回结果及转化异常信息;
    2) 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理;
    3) 与 DAO 层交互,对多个 DAO 的组合复用。
  • DAO 层:数据访问层,与底层 MySQL、Oracle、Hbase 等进行数据交互。
  • 外部接口或第三方平台:包括其它部门 RPC 开放接口,基础平台,其它公司的 HTTP 接口。

1.2 分层领域模型规约

  • DO(Data Object):与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
  • DTO(Data Transfer Object):数据传输对象,Service 或 Manager 向外传输的对象。
  • BO(Business Object):业务对象。由 Service 层输出的封装业务逻辑的对象。
  • VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
  • Query:数据查询对象,各层接收上层的查询请求。注意超过 2 个参数的查询封装,禁止使用 Map 类来传输。

二、代码生成器

我们新建一个springboot项目,版本为2.7.15(一开始使用2.3.2版本发现存在兼容性问题),使用的mybatis-plus-generator的版本为3.5.3.2,使用velocity模板引擎

2.1 pom文件

<?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.15</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.2.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>jsqlparser</artifactId>
                    <groupId>com.github.jsqlparser</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--swagger相关依赖-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
            <exclusions>
                <exclusion>
                    <groupId>io.swagger</groupId>
                    <artifactId>swagger-annotations</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.swagger</groupId>
                    <artifactId>swagger-models</artifactId>
                </exclusion>
                <exclusion>
                    <artifactId>error_prone_annotations</artifactId>
                    <groupId>com.google.errorprone</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>checker-qual</artifactId>
                    <groupId>org.checkerframework</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.5.21</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>1.5.21</version>
        </dependency>
        <!--swagger页面-->
        <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>swagger-bootstrap-ui</artifactId>
        <version>1.9.6</version>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</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-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

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

</project>

2.2 application.yml文件

如果项目中有引入swagger且在启动的时候报错注意配置请求路径的匹配策略spring.mvc.pathmatch.matchingstrategy=ant_path_matcher

server:
  port: 8088
spring:
  application:
    name: demo
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: admin
    password: root123
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
mybatis-plus:
  mapper-locations: classpath:/mapper/*Mapper.xml
  typeAliasesPackage: com.example.generator.pojo
logging:
  level:
    com.example.generator.mapper: debug

2.3 配置文件和工具类

mybatis-plus配置类,因为我在项目中使用了mybatis的分页插件,不配置无法正常分页

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.github.pagehelper.PageInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

/**
 * @Author 
 * @Date 2023/10/9 17:57
 * @Description pageHelper分页插件&&mybatisPlus分页插件
 **/
@Configuration
public class MybatisPlusConfiguration {

    /**
     * 配置分页插件
     * 包括PageHelper和MyBatis-Plus的分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        // 添加PaginationInnerInterceptor内部拦截器,用于支持MyBatis-Plus的分页功能
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }

    /**
     * 配置MyBatis-Plus的分页插件
     */
    @Bean
    public PaginationInnerInterceptor paginationInterceptor() {
        return new PaginationInnerInterceptor();
    }

    /**
     * 配置PageHelper的分页插件
     */
    @Bean
    PageInterceptor pageInterceptor() {
        PageInterceptor pageInterceptor = new PageInterceptor();
        // 配置属性helperDialect为"mysql",表示使用MySQL数据库
        Properties properties = new Properties();
        properties.setProperty("helperDialect", "mysql");
        pageInterceptor.setProperties(properties);
        return pageInterceptor;
    }
}

数据库类型枚举类

import com.baomidou.mybatisplus.generator.config.rules.IColumnType;

/**
 * @Author 
 * @Date 2023/8/30 15:32
 * @Description
 **/
public enum MyDbColumnType implements IColumnType{

    TINYINT("tinyint", (String)null);

    private final String type;
    private final String pkg;

    MyDbColumnType(final String type, final String pkg) {
        this.type = type;
        this.pkg = pkg;
    }

    @Override
    public String getType() {
        return this.type;
    }

    @Override
    public String getPkg() {
        return this.pkg;
    }
}

swagger配置类

import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;

/**
 * @Author 
 * @Date 2022/9/21 20:11
 * @Description 如果启动失败配置 spring.mvc.pathmatch.matching-strategy=ant_path_matcher
 **/
@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket createRestApi() {
        Contact contact = new Contact("XXX","","XXXX@qq.com");
        ApiInfo apiInfo=new ApiInfo(
                "XXX系统接口",
                "包含系统内所有可用接口说明",
                "v1.0",
                "",
                contact,
                "",
                "",
                new ArrayList<>()
        );

        return this.createRestApi(apiInfo);
    }

    public Docket createRestApi(ApiInfo apiInfo) {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo)
                .select()
                //这里采用包含注解的方式来确定要显示的接口(建议使用这种)
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build();
    }

}

工具类,主要用来复制对象属性

import java.util.function.Supplier;

/**
 * @Author 
 * @Date 2023/9/1 10:54
 * @Description
 **/
public class BeanUtils {
    public BeanUtils() {
    }

    public static <S, T> T copyProperties(S source, Supplier<T> targetSupplier) {
        if (null != source && null != targetSupplier) {
            T t = targetSupplier.get();
            org.springframework.beans.BeanUtils.copyProperties(source, t);
            return t;
        } else {
            return null;
        }
    }
}

2.4 模板文件

在resources文件夹下新建templates文件夹,将我们自定义的模板文件放在templates文件夹下
在这里插入图片描述

2.4.1 do.java.vm

package $!{package.Parent}.pojo;

import lombok.Data;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableField;
#foreach($pkg in ${table.importPackages})
import ${pkg};
#end

/**
 *
 * $!{table.comment} ($!{table.name})数据源对象
 *
 * @author ${author}
 * @since ${date}
 */
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@TableName("${schemaName}${table.name}")
public class ${entity} implements Serializable {

    #set($serialVersionUID = $table.name.getBytes("UTF-8").hashCode() + "L")
    private static final long serialVersionUID = $serialVersionUID;

#foreach($field in ${table.fields})
  #if("$!field.comment" != "")
    /**
     * ${field.comment}
     */
  #end
  #if(${field.keyFlag})
    #set($keyPropertyName=${field.propertyName})
  #end
  #if(${field.keyFlag})
   #if(${field.keyIdentityFlag})
    @TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
   #elseif(!$null.isNull(${idType}) && "$!idType" != "")
    @TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
   #elseif(${field.convert})
    @TableId("${field.annotationColumnName}")
   #end
   #else
    @TableField("${field.annotationColumnName}")
  #end
    private ${field.propertyType} ${field.propertyName};

    #end
}

2.4.2 bo.java.vm

package $!{package.Parent}.bo;

import lombok.Data;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
#foreach($pkg in ${table.importPackages})
import ${pkg};
#end

/**
 *
 * $!{table.comment} ($!{table.name})业务对象
 *
 * @author ${author}
 * @since ${date}
 */
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ${entity}BO implements Serializable {

    #set($serialVersionUID = $table.name.getBytes("UTF-8").hashCode() + "L")
    private static final long serialVersionUID = $serialVersionUID;

#foreach($field in ${table.fields})
  #if("$!field.comment" != "")
    /**
     * ${field.comment}
     */
  #end
    private ${field.propertyType} ${field.propertyName};

#end
}

2.4.3 dto.java.vm

package $!{package.Parent}.dto;

import lombok.Data;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.experimental.Accessors;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
#foreach($pkg in ${table.importPackages})
import ${pkg};
#end

/**
 *
 * $!{table.comment} ($!{table.name})数据传输对象
 *
 * @author ${author}
 * @since ${date}
 */
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ${entity}DTO implements Serializable {

    #set($serialVersionUID = $table.name.getBytes("UTF-8").hashCode() + "L")
    private static final long serialVersionUID = $serialVersionUID;

#foreach($field in ${table.fields})
  #if("$!field.comment" != "")
    /**
     * ${field.comment}
     */
  #end
    private ${field.propertyType} ${field.propertyName};

#end
}

2.4.4 vo.java.vm

package $!{package.Parent}.vo;

import lombok.Data;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.experimental.Accessors;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
#foreach($pkg in ${table.importPackages})
import ${pkg};
#end

/**
 *
 * $!{table.comment} ($!{table.name})显示层对象
 *
 * @author ${author}
 * @since ${date}
 */
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "$!{entity}VO", description = "$!{table.comment}显示层对象")
public class ${entity}VO implements Serializable {

    #set($serialVersionUID = $table.name.getBytes("UTF-8").hashCode() + "L")
    private static final long serialVersionUID = $serialVersionUID;

#foreach($field in ${table.fields})
  #if("$!field.comment" != "")
    /**
     * ${field.comment}
     */
  #end
    @ApiModelProperty(name = "$!{field.propertyName}", value = "${field.comment}")
    private ${field.propertyType} ${field.propertyName};

#end
}

2.4.5 query.java.vm

package $!{package.Parent}.query;

import lombok.Data;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.experimental.Accessors;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
#foreach($pkg in ${table.importPackages})
import ${pkg};
#end

/**
 *
 * $!{table.comment} ($!{table.name})数据查询对象
 *
 * @author ${author}
 * @since ${date}
 */
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "$!{entity}Query", description = "$!{table.comment}数据查询对象")
public class ${entity}Query implements Serializable {

    #set($serialVersionUID = $table.name.getBytes("UTF-8").hashCode() + "L")
    private static final long serialVersionUID = $serialVersionUID;

#foreach($field in ${table.fields})
  #if("$!field.comment" != "")
    /**
     * ${field.comment}
     */
  #end
    @ApiModelProperty(name = "$!{field.propertyName}", value = "${field.comment}")
    private ${field.propertyType} ${field.propertyName};

#end
}

2.4.6 mapper.xml.vm

<?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="${package.Mapper}.${table.mapperName}">
    #set($VOResultMap = ${entity}+"VO"+"Map")
    <!-- 开启二级缓存 -->
    <cache></cache>
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="${package.Parent}.pojo.${entity}">
    #foreach($field in ${table.fields})
      #if(${field.keyFlag})##生成主键排在第一位
       <id column="${field.name}" property="${field.propertyName}"/>
      #end
    #end
    #foreach($field in ${table.commonFields})##生成公共字段
       <result column="${field.name}" property="${field.propertyName}"/>
    #end
    #foreach($field in ${table.fields})
      #if(!${field.keyFlag})##生成普通字段
       <result column="${field.name}" property="${field.propertyName}"/>
      #end
    #end
    </resultMap>
    <!-- 显示层对象映射结果 -->
    <resultMap id="${VOResultMap}" type="${package.Parent}.vo.${entity}VO">
        #foreach($field in ${table.fields})
            #if(${field.keyFlag})##生成主键排在第一位
         <id column="${field.name}" property="${field.propertyName}"/>
            #end
        #end
        #foreach($field in ${table.commonFields})##生成公共字段
         <result column="${field.name}" property="${field.propertyName}"/>
        #end
        #foreach($field in ${table.fields})
            #if(!${field.keyFlag})##生成普通字段
         <result column="${field.name}" property="${field.propertyName}"/>
            #end
        #end
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
      #foreach($field in ${table.commonFields})
         ${field.columnName},
      #end
         ${table.fieldNames}
    </sql>
    <!--查询指定行数据-->
    <select id="findAll" resultMap="$!{VOResultMap}">
        select
        <include refid="Base_Column_List"/>
        from $!{table.name}
        <where>
            #foreach($field in $table.fields)
                <if test="${field.propertyName} != null#if($field.propertyType.equals("String")) and ${field.propertyName} != ''#end">
                    and ${field.name} = #{${field.propertyName}}
                </if>
            #end
        </where>
    </select>

</mapper>

2.4.7 mapper.java.vm

package ${package.Mapper};

import ${package.Parent}.pojo.${entity};
import ${package.Parent}.vo.${entity}VO;
import ${package.Parent}.query.${entity}Query;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import ${superMapperClassPackage};

## 首字母转小写 导包
#set($StringUtilsClass = $package.getClass().forName("org.apache.commons.lang3.StringUtils"))
#if(${mapperAnnotationClass})
import ${mapperAnnotationClass.name};
#end
#set($tableQuery = ${entity}+"Query")
/**
 * $!{table.comment} Mapper 接口
 *
 * @author ${author}
 * @since ${date}
 */
@Mapper
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {

    /**
     * 查询所有
     *
     * @param $StringUtilsClass.uncapitalize(${tableQuery}) 筛选条件
     * @return 对象列表
     * */
    List<${entity}VO> findAll($!{tableQuery} $StringUtilsClass.uncapitalize(${tableQuery}));

}

2.4.8 service.java.vm

package ${package.Service};

import ${package.Parent}.dto.${entity}DTO;
import ${package.Parent}.vo.${entity}VO;
import ${package.Parent}.query.${entity}Query;
import com.github.pagehelper.PageInfo;

#foreach($field in ${table.fields})
    #if(${field.keyFlag})
       #set($primaryKey=${field.propertyName})
       #set($primaryType=${field.propertyType})
    #end
#end
## 首字母转小写
#set($StringUtilsClass = $package.getClass().forName("org.apache.commons.lang3.StringUtils"))
#set($tableQuery = ${table.entityName}+"Query")
/**
 *
 * $!{table.comment} 服务类
 *
 * @author ${author}
 * @since ${date}
 */
#if(${kotlin})
interface ${table.serviceName} : ${superServiceClass}<${entity}>
#else
public interface ${table.serviceName} {

    /**
     * 通过${primaryKey}查询单条数据
     *
     * @param ${primaryKey} 主键
     * @return 实例对象
     */
    $!{entity}DTO selectByPrimaryKey(${primaryType} ${primaryKey});

    /**
     * 分页查询
     *
     * @param pageNum   当前页
     * @param pageSize  每页大小
     * @param $StringUtilsClass.uncapitalize(${tableQuery}) 筛选条件
     * @return 查询结果
     */
    PageInfo<$!{entity}VO> queryByPage(int pageNum, int pageSize, $!{entity}Query $StringUtilsClass.uncapitalize(${tableQuery}));

    /**
     * 新增数据
     *
     * @param $StringUtilsClass.uncapitalize(${tableQuery}) 数据传输对象
     * @return 成功新增的数量
     */
    int insertSelective($!{entity}Query $StringUtilsClass.uncapitalize(${tableQuery}));

    /**
     * 修改数据
     *
     * @param $StringUtilsClass.uncapitalize(${tableQuery}) 实例对象
     * @return 实例对象
     */
    $!{entity}DTO updateByPrimaryKeySelective($!{entity}Query $StringUtilsClass.uncapitalize(${tableQuery}));

    /**
     * 通过主键删除数据
     *
     * @param ${primaryKey} 主键
     * @return 删除的数据量
     */
    int deleteByPrimaryKey(${primaryType} ${primaryKey});

}
#end

2.4.9 serviceImpl.java.vm

package ${package.ServiceImpl};

##定义初始变量
#foreach($field in ${table.fields})
    #if(${field.keyFlag})
        #set($primaryKey=${field.propertyName})
        #set($primaryType=${field.propertyType})
    #end
#end
## 首字母转小写 导包
#set($StringUtilsClass = $package.getClass().forName("org.apache.commons.lang3.StringUtils"))

#set($tableNameImpl = ${entity}+"ServiceImpl")
#set($tableQuery = ${entity}+"Query")
#set($primaryKeyGet = $StringUtilsClass.uncapitalize(${entity})+".get"+$StringUtilsClass.capitalize(${primaryKey})+"()")

import ${package.Parent}.pojo.${entity};
import ${package.Parent}.dto.${entity}DTO;
import ${package.Parent}.vo.${entity}VO;
import ${package.Parent}.query.${entity}Query;
import ${package.Parent}.mapper.$!{entity}Mapper;
import ${package.Parent}.service.$!{entity}Service;
import ${package.Parent}.utils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import javax.annotation.Resource;

/**
 * $!{table.comment}($!{table.name})表服务实现类
 *
 * @author ${author}
 * @since ${date}
 */
@Service("$StringUtilsClass.uncapitalize(${tableNameImpl})")
public class $!{tableNameImpl} implements $!{entity}Service {

    private $!{entity}Mapper mapper;

    @Autowired
    public $!{tableNameImpl}($!{entity}Mapper mapper) {
        this.mapper = mapper;
    }

    /**
     * 通过${primaryKey}查询单条数据
     *
     * @param ${primaryKey} 主键
     * @return 实例对象
     */
    @Override
    public $!{entity}DTO selectByPrimaryKey(${primaryType} ${primaryKey}){
        $!{entity} $StringUtilsClass.uncapitalize(${entity}) =this.mapper.selectById($!primaryKey);
        $!{entity}DTO $StringUtilsClass.uncapitalize(${entity})DTO = BeanUtils.copyProperties($StringUtilsClass.uncapitalize(${entity}), $!{entity}DTO::new);
        return $StringUtilsClass.uncapitalize(${entity})DTO;
    }

    /**
     * 分页查询
     *
     * @param pageNum 当前页
     * @param pageSize 每页大小
     * @param $StringUtilsClass.uncapitalize(${tableQuery}) 筛选条件
     * @return 查询结果
     */
    @Override
    public PageInfo<$!{entity}VO> queryByPage(int pageNum,int pageSize, $!{tableQuery} $StringUtilsClass.uncapitalize(${tableQuery})){
        PageHelper.startPage(pageNum,pageSize);
        return new PageInfo<>(this.mapper.findAll($StringUtilsClass.uncapitalize(${tableQuery})));
    }

    /**
     * 新增数据
     *
     * @param $StringUtilsClass.uncapitalize(${tableQuery}) 实例对象
     * @return 实例对象
     */
    @Override
    public int insertSelective($!{tableQuery} $StringUtilsClass.uncapitalize(${tableQuery})){
        return this.mapper.insert(BeanUtils.copyProperties($StringUtilsClass.uncapitalize(${tableQuery}), ${entity}::new));
    }

    /**
     * 修改数据
     *
     * @param $StringUtilsClass.uncapitalize(${tableQuery}) 实例对象
     * @return 实例对象
     */
    @Override
    public $!{entity}DTO updateByPrimaryKeySelective($!{tableQuery} $StringUtilsClass.uncapitalize(${tableQuery})){
        $!{entity} $StringUtilsClass.uncapitalize(${entity}) = BeanUtils.copyProperties($StringUtilsClass.uncapitalize(${tableQuery}), ${entity}::new);
        int updateNum = this.mapper.updateById($StringUtilsClass.uncapitalize(${entity}));
        return this.selectByPrimaryKey(${primaryKeyGet});
    }

    /**
     * 通过主键删除数据
     *
     * @param ${primaryKey} 主键
     * @return 是否成功
     */
    @Override
    public int deleteByPrimaryKey(${primaryType} ${primaryKey}){
        return this.mapper.deleteById(${primaryKey});
    }
}

2.4.10 controller.java.vm

package ${package.Controller};

##定义初始变量
#foreach($field in ${table.fields})
    #if(${field.keyFlag})
        #set($primaryKey=${field.propertyName})
        #set($primaryType=${field.propertyType})
    #end
#end
## 首字母转小写 导包
#set($StringUtilsClass = $package.getClass().forName("org.apache.commons.lang3.StringUtils"))

#set($tableNameImpl = ${entity}+"ServiceImpl")
#set($tableQuery = ${entity}+"Query")
#set($primaryKeyGet = $StringUtilsClass.uncapitalize(${entity})+".get"+$StringUtilsClass.capitalize(${primaryKey})+"()")
#set($queryPage = "this."+$StringUtilsClass.uncapitalize(${table.serviceName})+".queryByPage(pageNum,pageSize,"+ $StringUtilsClass.uncapitalize(${tableQuery})+")")
#set($selectByPrimaryKey = "this."+$StringUtilsClass.uncapitalize(${table.serviceName})+".selectByPrimaryKey("+${primaryKey}+")")
#set($insertSelective = "this."+$StringUtilsClass.uncapitalize(${table.serviceName})+".insertSelective("+$StringUtilsClass.uncapitalize(${tableQuery})+")")
#set($updateByPrimaryKeySelective = "this."+$StringUtilsClass.uncapitalize(${table.serviceName})+".updateByPrimaryKeySelective("+$StringUtilsClass.uncapitalize(${tableQuery})+")")
#set($deleteByPrimaryKey = "this."+$StringUtilsClass.uncapitalize(${table.serviceName})+".deleteByPrimaryKey("+${primaryKey}+")")

import ${package.Parent}.dto.${entity}DTO;
import ${package.Parent}.vo.${entity}VO;
import ${package.Parent}.query.${entity}Query;
import ${package.Parent}.service.$!{entity}Service;
import com.personnel.common.utils.BeanUtils;
import com.personnel.common.bean.PageResult;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import javax.annotation.Resource;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import com.github.pagehelper.PageInfo;

/**
 * $!{table.comment}($!{table.name})表控制层
 *
 * @author $!author
 * @since ${date}
 */
@RestController
@RequestMapping("/$StringUtilsClass.uncapitalize(${table.entityName.replaceAll("_", "/")})")
@Api(tags = "$!{table.comment}($!{table.name})")
public class ${table.controllerName} {

    /**
     * 服务对象
     */
    @Resource(name = "$StringUtilsClass.uncapitalize(${tableNameImpl})")
    private ${table.serviceName} $StringUtilsClass.uncapitalize(${table.serviceName});

    /**
     * 分页查询$!{table.comment}数据
     *
     * @param pageNum   当前页
     * @param pageSize   每页大小
     * @param $StringUtilsClass.uncapitalize(${tableQuery})
     * @return 实例对象集合
     */
    @ApiOperation(value = "分页查询$!{table.comment}数据" )
    @GetMapping("/page/{pageNum}/{pageSize}")
    public PageResult<List<$!{entity}VO>> queryByPage(@ApiParam(name = "pageNum", value = "当前页") @PathVariable(name = "pageNum") int pageNum,@ApiParam(name = "pageSize", value = "每页条数") @PathVariable(name = "pageSize") int pageSize,@ApiParam(name = "$StringUtilsClass.uncapitalize(${tableQuery})", value = "$!{table.comment}数据查询对象") $!{tableQuery} $StringUtilsClass.uncapitalize(${tableQuery})){
        PageInfo<$!{entity}VO> pageInfo = ${queryPage};
        return new PageResult<>().success(pageInfo.getList(), pageInfo.getTotal());
    }

    /**
     * 通过主键查询单条$!{table.comment}数据
     *
     * @param ${primaryKey} 主键
     * @return 单条数据
     */
    @ApiOperation(value = "通过${primaryKey}主键查询单条$!{table.comment}数据" )
    @GetMapping("/{${primaryKey}}")
    public PageResult<$!{entity}VO> selectByPrimaryKey(@ApiParam(name = "${primaryKey}", value = "${primaryKey}主键") @PathVariable(name = "${primaryKey}") ${primaryType} ${primaryKey}){
        $!{entity}DTO $StringUtilsClass.uncapitalize(${entity})DTO = ${selectByPrimaryKey};
        $!{entity}VO $StringUtilsClass.uncapitalize(${entity})VO = BeanUtils.copyProperties($StringUtilsClass.uncapitalize(${entity})DTO, $!{entity}VO::new);
        return new PageResult<>().success($StringUtilsClass.uncapitalize(${entity})VO);
    }

    /**
     * 新增单条$!{table.comment}数据
     *
     * @param $StringUtilsClass.uncapitalize(${tableQuery}) 实体
     * @return 新增结果
     */
    @ApiOperation(value = "新增单条$!{table.comment}数据" )
    @PostMapping
    public PageResult<Integer> insertSelective(@ApiParam(name = "$StringUtilsClass.uncapitalize(${tableQuery})", value = "$!{tableInfo.comment}对象") @RequestBody $!{tableQuery} $StringUtilsClass.uncapitalize(${tableQuery})){
        return new PageResult<>().success(${insertSelective});
    }

    /**
     * 通过主键${primaryKey}修改单条$!{table.comment}数据
     *
     * @param $StringUtilsClass.uncapitalize(${tableQuery}) 实体
     * @return 修改结果
     */
    @ApiOperation(value = "通过主键${primaryKey}修改单条$!{table.comment}数据" )
    @PutMapping
    public PageResult<${entity}VO> updateByPrimaryKeySelective(@ApiParam(name = "$StringUtilsClass.uncapitalize(${tableQuery})", value = "$!{table.comment}") @RequestBody $!{tableQuery} $StringUtilsClass.uncapitalize(${tableQuery})){
        $!{entity}DTO $StringUtilsClass.uncapitalize(${entity})DTO = ${updateByPrimaryKeySelective};
        $!{entity}VO $StringUtilsClass.uncapitalize(${entity})VO = BeanUtils.copyProperties($StringUtilsClass.uncapitalize(${entity})DTO, $!{entity}VO::new);
        return new PageResult<>().success($StringUtilsClass.uncapitalize(${entity})VO);
    }

    /**
     * 通过${primaryKey}主键删除单条$!{table.comment}数据
     *
     * @param ${primaryKey} 主键
     * @return 删除结果数
     */
    @ApiOperation(value = "通过${primaryKey}主键删除单条$!{table.comment}数据" )
    @DeleteMapping("/{${primaryKey}}")
    public PageResult<Integer> deleteByPrimaryKey(@ApiParam(name = "${primaryKey}", value = "${primaryKey}主键") @PathVariable(name = "${primaryKey}") ${primaryType} ${primaryKey}){
        return new PageResult<>().success(${deleteByPrimaryKey});
    }

}

2.5 代码生成器配置

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.query.DefaultQuery;
import com.baomidou.mybatisplus.generator.type.TypeRegistry;
import com.example.generator.config.MyDbColumnType;
import org.springframework.util.StringUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Properties;

/**
 * @Author 
 * @Date 2023/8/29 15:32
 * @Description
 **/
public class Generator {

    /**
     * 生成文件的作者,可以不填
     */
    static String author="";

    /**
     * 生成的entity、controller、service等包所在的公共上一级包路径全限定名
     */
    final static String rootPackage="com.example.generator";

    static String dataSourceUrl = "";

    static String username = "";

    static String password = "";

    /**
     * 表名,多个使用,分隔
     */
    static String tableNames="t_user";

    /**
     * 要去除的表名前缀
     */
    static String tablePrefix="t_";

    /**
     * 生成的文件输出路径
     */
    static String outputDir = System.getProperty("user.dir")+"/src/main/java";

    static String xmlOutputDir = System.getProperty("user.dir")+"/src/main/resources/mapper";

    /**
     * 数据库连接信息为空则获取application.yml文件配置的信息
     */
    static String ymlDir = System.getProperty("user.dir")+"/src/main/resources/application.yml";

    static {
        boolean empty = StringUtils.hasLength(dataSourceUrl) && StringUtils.hasLength(username) && StringUtils.hasLength(password);
        if (!empty) {
            Properties properties = new Properties();
            try (FileInputStream fis = new FileInputStream(ymlDir)) {
                properties.load(fis);
            } catch (IOException e) {
                throw new RuntimeException("application.yml文件加载异常");
            }
            dataSourceUrl = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
        }
    }

    /**
     * 数据源配置
     */
    private static final DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig.Builder(dataSourceUrl, username, password)
            .typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> typeConvertHandler(globalConfig, typeRegistry, metaInfo))
            // 设置SQL查询方式,默认的是元数据查询方式
            .databaseQueryClass(DefaultQuery.class).build();

    /**
     * 策略配置
     */
    public static StrategyConfig strategyConfig() {
        // 设置需要生成的表名
        return new StrategyConfig.Builder().addInclude(tableNames).addTablePrefix(tablePrefix).serviceBuilder().formatServiceFileName("%sService").build();
    }

    /**
     * 模板配置
     */
    protected static TemplateConfig.Builder templateConfig() {
        return new TemplateConfig.Builder();
    }

    /**
     * 注入配置
     */
    protected static InjectionConfig.Builder injectionConfig() {
        // 测试自定义输出文件之前注入操作,该操作再执行生成代码前 debug 查看
        return new InjectionConfig.Builder().beforeOutputFile((tableInfo, objectMap) -> {
            System.out.println("tableInfo: " + tableInfo.getEntityName() + " objectMap: " + objectMap.size());
        });
    }

    /**
     * 全局配置
     */
    protected static GlobalConfig.Builder globalConfig() {
        return new GlobalConfig.Builder().author(author).disableOpenDir().outputDir(outputDir);
    }

    /**
     * 包配置
     */
    protected static PackageConfig.Builder packageConfig() {
        return new PackageConfig.Builder().parent(rootPackage).pathInfo(Collections.singletonMap(OutputFile.xml, xmlOutputDir));
    }

    /**
     * 自定义数据库类型转换
     * @param globalConfig
     * @param typeRegistry
     * @param metaInfo
     * @return
     */
    public static IColumnType typeConvertHandler(GlobalConfig globalConfig, TypeRegistry typeRegistry, TableField.MetaInfo metaInfo){
        // 包装类转基本数据类型
        IColumnType columnType = typeRegistry.getColumnType(metaInfo);
        if (MyDbColumnType.TINYINT.getType().equalsIgnoreCase(metaInfo.getTypeName())&&metaInfo.getLength()== 3) {
             return DbColumnType.INTEGER;
        }
        return columnType;
    }

    /**
     * 自定义模板(列表)
     */
    public static void testCustomFileByList() {
        // 设置自定义输出文件
        AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
        generator.strategy(strategyConfig());
        // 警用默认模板
        generator.template(templateConfig().disable(TemplateType.ENTITY
        ).build());
        // 需要生成的自定义文件模板路径
        generator.injection(injectionConfig().customFile(new ArrayList<CustomFile>() {{
            add(new CustomFile.Builder().fileName("DTO.java").templatePath("/templates/dto.java.vm").packageName("dto").build());
            add(new CustomFile.Builder().fileName("VO.java").templatePath("/templates/vo.java.vm").packageName("vo").build());
            add(new CustomFile.Builder().fileName("BO.java").templatePath("/templates/bo.java.vm").packageName("bo").build());
            add(new CustomFile.Builder().fileName("Query.java").templatePath("/templates/query.java.vm").packageName("query").build());
            add(new CustomFile.Builder().fileName(".java").templatePath("/templates/do.java.vm").packageName("entity").build());
        }}).build());
        generator.global(globalConfig().build());
        generator.packageInfo(packageConfig().build());
        generator.execute();
    }

    public static void main(String[] args) {
        // 代码生成
        testCustomFileByList();
    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值