代码生成器(使用Spring Boot + Mybatis-Plus+自定义模板)
结合网上资料自定义模板(FreeMarker),自动生成开发中经常使用到的代码块,直接添加业务逻辑即可,尽可能减少开发时间,提高工作效率。
话不多说,直接给各位大佬附上最终结果。
因为根据表结构生成后端代码,所以尽可能补全表及字段注释,命名也要规范(字段由多个单词组成的按下划线分隔)。
一. 导入jar
<-- 核心包 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<-- 其他包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.20</version>
</dependency>
<-- 使用 PostgreSQL 数据库 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<-- 校验数据(参数) -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
二. 主函数
public class Main {
public static void main(String[] args) {
//构建代码生成器对象
AutoGenerator mpg = new AutoGenerator();
//1、全局配置
GlobalConfig gc = new GlobalConfig();
String oPath = System.getProperty("user.dir");//得到当前项目的路径
String srcPath = oPath + "/src/main/java";//src 路径
gc.setOutputDir(oPath + "/src/main/java");//生成文件的输出目录
// 自定义路径(需修改)
String resourcesPath = oPath+ "/src/main/resources/"; //resources 路径
String codePackageName = "test"; //代码所在包名
String codePackageParentPath = "com.tangqd.generator"; // 代码所在包父包名
String codePackagePath = srcPath+"/com/tangqd/generator/"+codePackageName; //代码所在路径
gc.setAuthor("tangqd");//作者
gc.setOpen(false);//是否打开输出目录
gc.setFileOverride(false);//是否覆盖已有的文件
gc.setServiceName("%sService");//去除Service的I前缀
gc.setIdType(IdType.ID_WORKER);//主键生成策略
//ONLY_DATE 只使用 java.util.date 代替,SQL_PACK 使用 java.sql 包下的,TIME_PACK 使用 java.time 包下的 java8 新的时间类型
gc.setDateType(DateType.TIME_PACK);//数据库时间类型 到 实体类时间类型 对应策略
gc.setSwagger2(true);//开启swagger2模式
mpg.setGlobalConfig(gc);
//2、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
//dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSl=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC");
dsc.setUrl("jdbc:postgresql://127.0.0.1:5432/test?useSSL=true&allowMultiQueries=true");
dsc.setDriverName("org.postgresql.Driver");
dsc.setUsername("postgres");
dsc.setPassword("123456");
dsc.setDbType(DbType.POSTGRE_SQL);//数据库类型
mpg.setDataSource(dsc);
//3、包的配置
PackageConfig pc = new PackageConfig();
pc.setModuleName(codePackageName);//父包模块名
pc.setParent(codePackageParentPath);//父包名,如果为空,将下面子包名必须写全部, 否则就只需写子包名
pc.setEntity("pojo");
pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");
mpg.setPackageInfo(pc);
//4、策略配置
StrategyConfig sy = new StrategyConfig();
sy.setInclude("tbl_user_info");//设置要映射的表,可以设置多张
sy.setNaming(NamingStrategy.underline_to_camel);//从数据库表到文件的命名策略,下划线转驼峰命名
sy.setColumnNaming(NamingStrategy.underline_to_camel);//列的命名策略
sy.setEntityLombokModel(true);//开启lombok支持
sy.setLogicDeleteFieldName("deleted");//设置逻辑删除字段
sy.setVersionFieldName("version");//设置乐观锁
sy.setRestControllerStyle(true);//开启controller的restful命名
sy.setControllerMappingHyphenStyle(false);//开启controller中请求映射的连字符样式,如:localhost:8080/hello_id_1
sy.setEntityBooleanColumnRemoveIsPrefix(false);
sy.isEntityTableFieldAnnotationEnable();
sy.setTablePrefix("tbl_"); //过滤表前缀,生成实体类才不是TblUserInfo
//设置自动填充字段
/*TableFill create_time = new TableFill("create_time", FieldFill.INSERT);
TableFill update_time = new TableFill("update_time", FieldFill.INSERT_UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(create_time);
tableFills.add(update_time);*/
//创建模板
TemplateConfig templateConfig = new TemplateConfig();
//templateConfig.setController("templatespath/controller222.java");
templateConfig.setController(null);
templateConfig.setEntity(null);
templateConfig.setService(null);
templateConfig.setServiceImpl(null);
templateConfig.setMapper(null);
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
mpg.setStrategy(sy);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
}
};
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("templatesPath/controller.java.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
return codePackagePath+ "/controller/" + tableInfo.getControllerName() + StringPool.DOT_JAVA;
}
});
focList.add(new FileOutConfig("templatesPath/entity.java.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
return codePackagePath+"/pojo/" + tableInfo.getEntityName() + StringPool.DOT_JAVA;
}
});
focList.add(new FileOutConfig("templatesPath/service.java.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
return codePackagePath+"/service/" + tableInfo.getServiceName() + StringPool.DOT_JAVA;
}
});
focList.add(new FileOutConfig("templatesPath/serviceImpl.java.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
return codePackagePath+ "/service/impl/" + tableInfo.getServiceImplName() + StringPool.DOT_JAVA;
}
});
focList.add(new FileOutConfig("templatesPath/mapper.java.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
return codePackagePath+"/mapper/" + tableInfo.getMapperName() + StringPool.DOT_JAVA;
}
});
focList.add(new FileOutConfig("templatesPath/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
return resourcesPath + "/mapper/" + tableInfo.getMapperName() + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
//执行代码生成器
mpg.execute();
}
}
三. 自定义配置文件
3.1 entity.java.ftl
package ${package.Entity};
import lombok.Data;
import java.util.Date;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* ${table.comment} 实体类
* @author ${author}
* @date ${date}
*/
@Data
public class ${entity} implements Serializable {
private static final long serialVersionUID = 1L;
<#list table.fields as value>
<#if value_index == 0>
<#if value.comment!="">
/**
* ${value.comment}
*/
</#if>
@NotNull
private ${value.propertyType} ${value.capitalName};
<#else>
<#if value.comment!="">
/**
* ${value.comment}
*/
</#if>
private ${value.propertyType} ${value.capitalName};
</#if>
</#list>
}
3.2 controller.java.ftl
package ${package.Controller};
import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotBlank;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
<#if restControllerStyle>
<#else>
import org.springframework.stereotype.Controller;
</#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
/**
* ${table.comment} 控制类
* @author ${author}
* @date ${date}
*/
@Api(value = "${table.controllerName}",tags = "${table.comment}")
<#if restControllerStyle>
@RestController
<#else>
@Controller
</#if>
@RequestMapping("${table.serviceName?uncap_first}")
public class ${table.controllerName} {
@Autowired
private ${table.serviceName} ${table.serviceName?uncap_first};
@ApiOperation("新增_${table.comment}")
@PostMapping("/add<#if controllerMappingHyphenStyle??>${controllerMappingHyphen?cap_first}<#else>${table.entityPath?cap_first}</#if>")
public String add${table.entityName?cap_first}(@RequestBody ${table.entityName} ${table.entityName?uncap_first}) {
String massage = ${table.entityName?uncap_first}Service.add${table.entityName?cap_first}(${table.entityName?uncap_first});
return massage;
}
@ApiOperation("删除_${table.comment}(通过序列ID)")
@DeleteMapping(value = "/delete<#if controllerMappingHyphenStyle??>${controllerMappingHyphen?cap_first}<#else>${table.entityPath?cap_first}</#if>/{id}")
public String delete${table.entityName?cap_first}(@NotNull @PathVariable Integer id) {
String massage = ${table.entityName?uncap_first}Service.delete${table.entityName?cap_first}(id);
return massage;
}
@ApiOperation("修改_${table.comment}")
@PutMapping("update${table.entityName?cap_first}")
public String update${table.entityName?cap_first}(@Valid @RequestBody ${table.entityName} ${table.entityName?uncap_first}) {
String massage = ${table.entityName?uncap_first}Service.update${table.entityName?cap_first}(${table.entityName?uncap_first});
return massage;
}
@ApiOperation("查询列表_${table.comment}:{列表}")
@ApiImplicitParams({
<#list table.fields as field>
<#if field_index!=0>
@ApiImplicitParam(name = "${field.propertyName}", value = "${field.comment}", dataType = "${field.propertyType}"),
</#if>
</#list>
@ApiImplicitParam(name = "limit", value = "查询多少行", dataType = "Integer"),
@ApiImplicitParam(name = "offset", value = "起始查询位置", dataType = "Integer")
})
@GetMapping("get${table.entityName?cap_first}List")
public String get${table.entityName?cap_first}List(
<#list table.fields as field>
<#if field_index != 0>
@RequestParam(name="${field.propertyName}", required = false) ${field.propertyType} ${field.propertyName},
</#if>
</#list>
@RequestParam(name="limit",required = false)Integer limit,
@RequestParam(name="offset",required = false)Integer offset){
String massage = ${table.entityName?uncap_first}Service.get${table.entityName?cap_first}List(<#list table.fields as field><#if field_index != 0>${field.propertyName},</#if></#list>limit,offset);
return massage;
}
@ApiOperation("查询数量_${table.comment}:{数量}")
@ApiImplicitParams({
<#list table.fields as field>
<#if field_index!=0>
@ApiImplicitParam(name = "${field.propertyName}", value = "${field.comment}", dataType = "${field.propertyType}"),
</#if>
</#list>
})
@GetMapping("get${table.entityName?cap_first}Count")
public String get${table.entityName?cap_first}Count(
<#list table.fields as field>
<#if field_index == table.fields?size - 1>
@RequestParam(name = "${field.propertyName}", required = false) ${field.propertyType} ${field.propertyName}) {
<#elseif field_index != 0>
@RequestParam(name = "${field.propertyName}", required = false) ${field.propertyType} ${field.propertyName},
</#if>
</#list>
String massage = ${table.entityName?uncap_first}Service.get${table.entityName?cap_first}Count(<#list table.fields as field><#if field_index == table.fields?size - 1>${field.propertyName}<#elseif field_index != 0>${field.propertyName}, </#if></#list>);
return massage;
}
}
3.3 service.java.ftl
package ${package.Service};
import ${package.Entity}.${entity};
/**
* ${table.comment} 服务接口
* @author ${author}
* @date ${date}
*/
public interface ${table.serviceName}{
/**
* 新增
* @param ${table.entityName?uncap_first} ${table.comment}对象
* @return 新增结果
*/
String add${table.entityName}(${table.entityName} ${table.entityName?uncap_first});
/**
* 删除
* @param id 序列ID
* @return 删除结果
*/
String delete${table.entityName}(Integer id);
/**
* 更新
* @param ${table.entityName?uncap_first} ${table.comment}对象
* @return 更新结果
*/
String update${table.entityName}(${table.entityName} ${table.entityName?uncap_first});
/**
* 查询列表
<#list table.fields as field>
<#if field_index!=0>
* @param ${field.propertyName} ${field.comment}
</#if>
</#list>
* @param limit 查询多少行
* @param offset 起始查询位置
* @return 查询列表结果
*/
String get${table.entityName}List(<#list table.fields as field><#if field_index != 0>${field.propertyType} ${field.propertyName},</#if></#list>Integer limit, Integer offset);
/**
* 查询数量
<#list table.fields as field>
<#if field_index!=0>
* @param ${field.propertyName} ${field.comment}
</#if>
</#list>
* @return 查询数量结果
*/
String get${table.entityName}Count(<#list table.fields as field><#if field_index == table.fields?size - 1>${field.propertyType} ${field.propertyName}<#elseif field_index != 0>${field.propertyType} ${field.propertyName}, </#if></#list>);
}
3.4 serviceImpl.java.ftl
package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${package.Entity}.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.util.List;
/**
* ${table.comment} 服务实现类
* @author ${author}
* @date ${date}
*/
@Service
public class ${table.serviceImplName} implements ${table.serviceName} {
@Autowired
private ${table.mapperName} ${table.mapperName?uncap_first};
@Override
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
public String add${table.entityName}(${table.entityName} ${table.entityName?uncap_first}){
try {
Integer count = ${table.mapperName?uncap_first}.insert${table.entityName}(${table.entityName?uncap_first});
if (count != null && count > 0){
return new Result<>(true,"新增成功").toString();
}else {
return new Result<>(false,"新增失败").toString();
}
}catch (Exception e){
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return new Result<>(false,"新增异常").toString();
}
}
@Override
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
public String delete${table.entityName}(Integer id){
try {
Integer count = ${table.mapperName?uncap_first}.delete${table.entityName}(id);
if (count != null && count > 0){
return new Result<>(true,"删除成功").toString();
}else {
return new Result<>(false,"删除失败").toString();
}
}catch (Exception e){
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return new Result<>(false,"删除异常").toString();
}
}
@Override
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
public String update${table.entityName}(${table.entityName} ${table.entityName?uncap_first}){
try {
Integer count = ${table.mapperName?uncap_first}.update${table.entityName}(${table.entityName?uncap_first});
if (count != null && count > 0){
return new Result<>(true,"修改成功").toString();
}else {
return new Result<>(false,"修改失败").toString();
}
}catch (Exception e){
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return new Result<>(false,"修改异常").toString();
}
}
@Override
public String get${table.entityName}List(<#list table.fields as field><#if field_index != 0>${field.propertyType} ${field.propertyName},</#if></#list>Integer limit, Integer offset){
try {
List<${table.entityName}> ${table.entityName?uncap_first}List = ${table.mapperName?uncap_first}.get${table.entityName}List(<#list table.fields as field><#if field_index != 0>${field.propertyName},</#if></#list> limit, offset);
if (${table.entityName?uncap_first}List != null && ${table.entityName?uncap_first}List.size() > 0){
return new Result<>(true,"查询数据成功",${table.entityName?uncap_first}List).toString();
}else {
return new Result<>(true,"查询数据为空").toString();
}
}catch (Exception e){
e.printStackTrace();
return new Result<>(false,"查询异常").toString();
}
}
@Override
public String get${table.entityName}Count(<#list table.fields as field><#if field_index == table.fields?size - 1>${field.propertyType} ${field.propertyName}<#elseif field_index != 0>${field.propertyType} ${field.propertyName}, </#if></#list>){
try {
Integer count = ${table.mapperName?uncap_first}.get${table.entityName}Count(<#list table.fields as field><#if field_index == table.fields?size - 1>${field.propertyName}<#elseif field_index != 0>${field.propertyName}, </#if></#list>);
if (count != null && count > 0){
return new Result<>(true,"查询成功",count).toString();
}else {
return new Result<>(true,"查询数据为空",0).toString();
}
}catch (Exception e){
e.printStackTrace();
return new Result<>(false,"查询异常").toString();
}
}
}
3.5 mapper.java.ftl
package ${package.Mapper};
import ${package.Entity}.${entity};
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* ${table.comment} 数据映射接口
* @author ${author}
* @date ${date}
*/
@Repository
public interface ${table.mapperName}{
Integer insert${table.entityName}(@Param("${table.entityName?uncap_first}") ${table.entityName} ${table.entityName?uncap_first});
Integer delete${table.entityName}(@Param("id")Integer id);
Integer update${table.entityName}(@Param("${table.entityName?uncap_first}")${table.entityName} ${table.entityName?uncap_first});
List<${table.entityName}> get${table.entityName}List(<#list table.fields as field><#if field_index != 0>@Param("${field.propertyName}") ${field.propertyType} ${field.propertyName},</#if></#list>@Param("limit") Integer limit, @Param("offset") Integer offset);
Integer get${table.entityName}Count(<#list table.fields as field><#if field_index == table.fields?size - 1>@Param("${field.propertyName}") ${field.propertyType} ${field.propertyName}<#elseif field_index != 0>@Param("${field.propertyName}") ${field.propertyType} ${field.propertyName}, </#if></#list>);
}
3.6 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}">
<insert id="insert${table.entityName}" useGeneratedKeys="true" keyProperty="${table.entityName?uncap_first}.id">
insert into ${table.name}(<#list table.fields as field><#if field_index == table.fields?size - 1>${field.name}<#elseif field_index != 0>${field.name}, </#if></#list>)
values(<#list table.fields as field><#if field_index == table.fields?size - 1><#noparse>#</#noparse>{${table.entityName?uncap_first}.${field.propertyName}}<#elseif field_index != 0><#noparse>#</#noparse>{${table.entityName?uncap_first}.${field.propertyName}}, </#if></#list>)
</insert>
<delete id="delete${table.entityName}">
delete from ${table.name}
where id = <#noparse>#</#noparse>{id}
</delete>
<update id="update${table.entityName}">
update ${table.name}
<set>
<#list table.fields as field>
<#if field_index != 0>
<if test="${table.entityName?uncap_first}.${field.propertyName} != null">
,${field.name} = <#noparse>#</#noparse>{${table.entityName?uncap_first}.${field.propertyName}}
</if>
</#if>
</#list>
</set>
where id = <#noparse>#</#noparse>{${table.entityName?uncap_first}.id}
</update>
<resultMap id = "Basic${table.entityName}Map" type = "${package.Entity}.${table.entityName}">
<#list table.fields as field>
<#if field_index gte 0>
<result column="${field.name}" property="${field.propertyName}"/>
</#if>
</#list>
</resultMap>
<select id="get${table.entityName}List" resultMap="Basic${table.entityName}Map">
select <#list table.fields as field><#if field_index == table.fields?size - 1>${field.name}<#elseif field_index gte 0>${field.name}, </#if></#list>
from ${table.name}
<where>
<#list table.fields as field>
<#if field_index != 0>
<if test="${field.propertyName} != null">
,${field.name} = <#noparse>#</#noparse>{${field.propertyName}}
</if>
</#if>
</#list>
</where>
</select>
<select id="get${table.entityName}Count" resultType="java.lang.Integer">
select count(id)
from ${table.name}
<where>
<#list table.fields as field>
<#if field_index != 0>
<if test="${field.propertyName} != null">
,${field.name} = <#noparse>#</#noparse>{${field.propertyName}}
</if>
</#if>
</#list>
</where>
</select>
</mapper>