baseService.java
package com.example.gentest.base;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class BaseService<E extends JpaRepository<F, UUID>, F> {
protected final E baserepo;
@Autowired
public BaseService(Class<E> repositoryInterface, Class<F> entityClass, ApplicationContext context) {
Map<String, E> beansOfType = context.getBeansOfType(repositoryInterface);
if (beansOfType.size() == 1) {
this.baserepo = beansOfType.values().iterator().next();
} else {
throw new RuntimeException("Expected exactly one bean of type " + repositoryInterface);
}
}
public List<F> getList(){
return baserepo.findAll();
}
public Page<F> getPageList(int pageNumber, int pageSize) {
PageRequest pageRequest = PageRequest.of(pageNumber - 1, pageSize);
return baserepo.findAll(pageRequest);
}
public F getOneById(UUID id){
return baserepo.getById(id);
}
public void save(F f) {
baserepo.save(f);
}
public void removeByIds(List<UUID> ids){
baserepo.deleteAllByIdInBatch(ids);
}
}
CodeGenerator.java
package com.example.gentest;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.example.gentest.base.BaseService;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class CodeGenerator {
public static void main(String[] args) {
// 获取表名
List<String> tables = getTableNames();
// 数据库设置
FastAutoGenerator.create("jdbc:postgresql://localhost:5432",
"postgres", "password")
/**
* 全局配置
*/
.globalConfig(builder -> {
builder.author("Zxv") // 作者
.disableOpenDir() // 禁止打开输出目录
.outputDir(System.getProperty("user.dir") + "\\src\\main\\java") // 指定输出目录 /opt/baomidou/ 默认值: windows:D:// linux or mac : /tmp
.enableSwagger() // 开启 swagger 模式 默认值:false
.dateType(DateType.TIME_PACK) // 时间策略 DateType.ONLY_DATE 默认值: DateType.TIME_PACK
.commentDate("yyyy-MM-dd"); // 注释日期 默认值: yyyy-MM-dd
// .fileOverride(); // 覆盖已有文件(已迁移到策略配置中,3.5.4版本会删除此方法)
})
/**
* 包配置
*/
.packageConfig(builder -> builder.parent("com.example.gentest") // 父包名 默认值:com.baomidou
// .moduleName("com.qbb.security") // 父包模块名 默认值:无
.entity("entity") // Entity 包名 默认值:common
// .service("service") // Service 包名 默认值:service
.serviceImpl("service") // Service Impl 包名 默认值:service.impl
.controller("controller") // Controller 包名 默认值:controller
.mapper("repo") // Mapper 包名 默认值:mapper
.xml("mapper") // Mapper XML 包名 默认值:mapper.xml
.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "\\src\\main\\resources\\mapper"))) // xml的路径配置信息
/**
* 策略配置
*/
.strategyConfig(builder -> builder.addInclude(tables)// 增加表匹配(内存过滤) include 与 exclude 只能配置一项
// .enableCapitalMode() // 开启大写命名 默认值:false
// .enableSkipView() // 开启跳过视图 默认值:false
// .disableSqlFilter() // 禁用 sql 过滤 默认值:true,语法不能支持使用 sql 过滤表的话,可以考虑关闭此开关
// .enableSchema() // 启用 schema 默认值:false,多 schema 场景的时候打开
// .likeTable(LikeTable) // 模糊表匹配(sql 过滤) likeTable 与 notLikeTable 只能配置一项
// .notLikeTable(LikeTable) // 模糊表排除(sql 过滤) likeTable 与 notLikeTable 只能配置一项
// .addExclude() // 增加表排除匹配(内存过滤) include 与 exclude 只能配置一项
// .addTablePrefix("t_", "sys_", "tb_") //前缀过滤
// .addTableSuffix(String...) // 增加过滤表后缀
// .addFieldPrefix(String...) // 增加过滤字段前缀
// .addFieldSuffix(String...) // 增加过滤字段后缀
/**
* service 策略配置
*/
.serviceBuilder()
// .superServiceClass(IService.class) // 设置 service 接口父类 BaseService.class
// .superServiceClass(String) // 设置 service 接口父类 com.baomidou.global.BaseService
.superServiceImplClass(BaseService.class) // 设置 service 实现类父类 BaseServiceImpl.class
// .superServiceImplClass(String) // 设置 service 实现类父类 com.baomidou.global.BaseServiceImpl
// .convertServiceFileName(ConverterFileName) // 转换 service 接口文件名称
// .convertServiceImplFileName(ConverterFileName) // 转换 service 实现类文件名称
.formatServiceFileName("%sService(remove)") // 格式化 service 接口文件名称
.formatServiceImplFileName("%sService") // 格式化 service 实现类文件名称
/**
* 实体策略配置
*/
.entityBuilder()
// .nameConvert(INameConvert) // 名称转换实现
// .superClass(BaseEntity.class) // 设置父类 BaseEntity.class
// .superClass(String) // 设置父类 com.baomidou.global.BaseEntity
.disableSerialVersionUID() // 禁用生成 serialVersionUID 默认值:true
// .enableColumnConstant() // 开启生成字段常量 默认值:false
.enableChainModel() // 开启链式模型 默认值:false
.enableRemoveIsPrefix() // 开启 Boolean 类型字段移除 is 前缀 默认值:false
.enableTableFieldAnnotation() // 开启生成实体时生成字段注解 默认值:false
// .enableActiveRecord() // 开启 ActiveRecord 模型 默认值:false
// .versionColumnName("version") // 乐观锁字段名(数据库)
// .versionPropertyName(String) // 乐观锁属性名(实体)
// .logicDeleteColumnName("is_deleted") // 逻辑删除字段名(数据库)
// .logicDeletePropertyName(String) // 逻辑删除属性名(实体)
.naming(NamingStrategy.underline_to_camel) // 数据库表映射到实体的命名策略 默认下划线转驼峰命名:NamingStrategy.underline_to_camel
// .columnNaming(NamingStrategy.underline_to_camel) // 数据库表字段映射到实体的命名策略 默认为 null,未指定按照 naming 执行
// .addSuperEntityColumns("id", "createTime", "updateTime", "statu") // 添加父类公共字段
// .addIgnoreColumns(String...) // 添加忽略字段
// .addTableFills(new Column("create_time", FieldFill.INSERT)) // 添加表字段填充
// .addTableFills(new Property("updateTime", FieldFill.INSERT_UPDATE)) // 添加表字段填充
// .idType(IdType.AUTO) // 全局主键类型
// .convertFileName(ConverterFileName)// 转换文件名称
// .formatFileName(String) // 格式化文件名称
.enableLombok() // 开启 lombok 模型 默认值:false
/**
* controller 策略配置
*/
.controllerBuilder()
// .superClass(BaseController.class) // 设置父类 BaseController.class
// .superClass(String) // 设置父类 com.baomidou.global.BaseController
.enableHyphenStyle() // 开启驼峰转连字符 默认值:false
.enableRestStyle() // 开启生成@RestController 控制器 默认值:false
// .convertFileName(ConverterFileName) // 转换文件名称
.formatFileName("%sController")// 格式化文件名称
/**
* mapper 策略配置
*/
.mapperBuilder()
.superClass(JpaRepository.class) // 设置父类 BaseMapper.class
// .superClass(String) //设置父类 com.baomidou.global.BaseMapper
// .enableMapperAnnotation() //开启 @Mapper 注解 默认值:false WARN 因为现在mybatis-plus传递mybatis-spring依赖,这里是没问题的,但后面如果考虑脱离mybatis-spring的时候就需要把这里处理掉,建议使用mapperAnnotation方法来标记自己的注解。
// .mapperAnnotation(Mapper.class)
// .enableBaseResultMap() // 启用 BaseResultMap 生成 默认值:false
// .enableBaseColumnList() // 启用 BaseColumnList 默认值:false
// .cache(Class<? extends Cache>) //设置缓存实现类 MyMapperCache.class
// .convertMapperFileName(ConverterFileName) //转换 mapper 类文件名称
// .convertXmlFileName(ConverterFileName) //转换 xml 文件名称
.formatMapperFileName("%sRepo") // 格式化 mapper 文件名称
.formatXmlFileName("%sMapper") // 格式化 xml 实现类文件名称
)
/**
* 模板配置
*/
.templateConfig(builder -> {
// WARN : 使用我们自定义模板 需要注意虽然我们文件是以ftl结尾,但是这里不要加上ftl,不然会报模板引擎找不到文件
builder
// .disable(TemplateType.ENTITY,TemplateType.SERVICE...) // 禁用模板
// .disable() // 禁用所有模板
.entity("/templates/entity.java") // 自定义entity模板
.controller("/templates/controller.java") // 自定义controller模板
// .service("/templates/myService.java") // 自定义service模板
.serviceImpl("/templates/service.java") // 自定义servicei.mpl模板
.mapper("/templates/mapper.java") // 自定义mapper模板
.xml("/templates/mapper.xml"); // 自定义xml模板
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
/**
* 读取控制台内容,获取用户输入的表名
*/
public static List<String> getTableNames() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入表名(多个表名以逗号隔开):");
String tableNames = scanner.nextLine();
if (StringUtils.isNotBlank(tableNames)) {
return Arrays.asList(tableNames.split(","));
}
throw new RuntimeException("请按照格式输入正确的表名!");
}
}
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>com.example</groupId>
<artifactId>GenTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>GenTest</name>
<description>GenTest</description>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.example.gentest.GenTestApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
controller.java.ftl
package ${package.Controller};
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import ${package.ServiceImpl}.${table.serviceImplName};
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
/**
* <p>
* ${table.comment!} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
@Slf4j
@RestController
@RequestMapping("<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
public class ${table.controllerName} {
@Autowired
private ${table.serviceImplName} service;
}
entity.java.ftl
package ${package.Entity};
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
/**
* <p>
* ${table.comment!}
* </p>
*
* @author ${author}
* @since ${date}
*/
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name="${table.name}")
public class ${entity} implements Serializable {
private static final long serialVersionUID = 1L;
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}"/>
</#if>
<#if field.comment!?length gt 0>
/**
* ${field.comment}
*/
</#if>
<#if field.keyFlag>
<#-- 主键 -->
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
<#-- 普通字段 -->
<#else>
<#-- ----- 存在字段填充设置 ----->
@Column(name="${field.annotationColumnName}")
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
<#------------ END 字段循环遍历 ---------->
}
mapper.java.ftl
package ${package.Mapper};
import ${package.Entity}.${entity};
import ${superMapperClassPackage};
import java.util.UUID;
/**
* <p>
* ${table.comment!} Repo 接口
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if mapperAnnotationClass??>
@${mapperAnnotationClass.simpleName}
</#if>
<#if kotlin>
interface ${table.mapperName} : ${superMapperClass}<${entity}>
<#else>
public interface ${table.mapperName} extends ${superMapperClass}<${entity},UUID> {
}
</#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="${package.Mapper}.${table.mapperName}">
<#if enableCache>
<!-- 开启二级缓存 -->
<cache type="${cacheClassName}"/>
</#if>
<#if baseResultMap>
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${package.Entity}.${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.columnName},
</#list>
${table.fieldNames}
</sql>
</#if>
</mapper>
service.java.ftl
package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${superServiceImplClassPackage};
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.context.ApplicationContext;
/**
* <p>
* ${table.comment!} 服务类
* </p>
*
* @author ${author}
* @since ${date}
*/
@Slf4j
@Service
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}>{
private final ${table.mapperName} entityInfoRepo;
@Autowired
public ${table.serviceImplName}(${table.mapperName} repository, ApplicationContext context, ${table.mapperName} entityInfoRepo) {
super(${table.mapperName}.class, ${entity}.class, context);
this.entityInfoRepo = entityInfoRepo;
}
}
service(remove) mapper/*. xml 可以删除不用。