1 目录结构
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─hikktn
│ │ │ ├─common
│ │ │ │ ├─base
│ │ │ │ ├─enums
│ │ │ │ ├─exception
│ │ │ │ ├─rest
│ │ │ │ └─validator
│ │ │ ├─content
│ │ │ │ ├─controller
│ │ │ │ ├─dao
│ │ │ │ ├─entity
│ │ │ │ └─service
│ │ │ │ └─impl
│ │ │ └─generator
│ │ └─resources
│ │ ├─mapper
│ │ └─templates
2 示例
2.1 依赖引入
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<dependencies>
<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>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.29</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
</dependencies>
2.2 控制器 - controller.java.vm
package ${package.Controller};
import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
import com.hikktn.common.base.PageDto;
import com.hikktn.common.exception.RestException;
import com.hikktn.common.rest.RestResponse;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
#if(${superControllerClassPackage})
import $!{superControllerClassPackage};
#end
#set($entityName = ${entity.substring(0,1).toLowerCase()}+${entity.substring(1)})
@RestController
@RequestMapping(value = {"#if(${controllerMappingHyphenStyle})/api/${controllerMappingHyphen}#else /api/${table.entityPath}#end"},
produces = MediaType.APPLICATION_JSON_VALUE)
@Api(value = "${table.controllerName}", description = "$!{table.comment}", produces = MediaType.APPLICATION_JSON_VALUE)
public class ${table.controllerName} extends ${superControllerClass} {
@Autowired
private ${table.serviceName} ${entityName}Service;
@ResponseBody
@ApiOperation(value = "$!{table.comment}-分页查询", notes = "$!{table.comment}-分页查询")
@RequestMapping(value = "/_search", method = RequestMethod.POST)
public RestResponse search(@RequestBody PageDto<${entity}> page){
return RestResponse.success();
}
@ResponseBody
@ApiOperation(value = "$!{table.comment}-保存", notes = "$!{table.comment}-保存")
@RequestMapping(value = "", method = RequestMethod.POST)
public RestResponse<String> save(@RequestBody ${entity} $entityName){
${entityName}Service.save($entityName);
return RestResponse.success();
}
@ResponseBody
@ApiOperation(value = "$!{table.comment}-更新", notes = "$!{table.comment}-更新")
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public RestResponse<String> update(@PathVariable String id, @RequestBody ${entity} $entityName){
if (StringUtils.isEmpty(id)){
throw new RestException("ID不能为空");
}
${entityName}Service.updateById($entityName);
return RestResponse.success();
}
@ResponseBody
@ApiOperation(value = "$!{table.comment}-删除", notes = "$!{table.comment}-删除")
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public RestResponse<String> delete(@PathVariable String id){
${entityName}Service.removeById(id);
return RestResponse.success();
}
}
2.3 领域对象 - entity.java.vm
package ${package.Entity};
#foreach($pkg in ${table.importPackages})
import ${pkg};
#end
#if(${entityLombokModel})
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
#end
#if(${swagger2})
import io.swagger.annotations.ApiModelProperty;
#end
## 表备注,作者,日期
#if(${entityLombokModel})
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
#end
@TableName("${table.name}")
#if(${superEntityClass})
public class ${entity} extends ${superEntityClass}#if(${activeRecord})<${entity}>#end {
#elseif(${activeRecord})
public class ${entity} extends Model<${entity}> {
#else
public class ${entity} implements Serializable {
#end
private static final long serialVersionUID = 1L;
## ---------- BEGIN 字段循环遍历 ----------
## ---------- START 字段循环遍历 ----------
#foreach($field in ${table.fields})
#if(${field.keyFlag})
#set($keyPropertyName=${field.propertyName})
#end
#if("$!field.comment" != "")
#if(${swagger2})
@ApiModelProperty(value = "${field.comment}")
#else
#end
#end
## 主键
#if(${field.keyFlag})
#if(${field.keyIdentityFlag})
@TableId(value = "${field.name}", type = IdType.AUTO)
#elseif(!$null.isNull(${idType}) && "$!idType" != "")
@TableId(value = "${field.name}", type = IdType.${idType})
#elseif(${field.convert})
@TableId("${field.name}")
#end
## 普通字段
#if(${field.fill})
## ----- 存在字段填充设置 -----
#if(${field.convert})
@TableField(value = "${field.name}", fill = FieldFill.${field.fill})
#else
@TableField(fill = FieldFill.${field.fill})
#end
#elseif(${field.convert})
@TableField("${field.name}")
#end
#end
## 时间类型
#if(${field.name} == ${cfg.createTime})
@TableField(fill = FieldFill.INSERT)
#elseif(${field.name} == ${cfg.updateTime})
@TableField(fill = FieldFill.INSERT_UPDATE)
#end
## 逻辑删除注解
#if(${cfg.logicDeleteFieldName}==${field.name})
@TableLogic
#end
private ${field.propertyType} ${field.propertyName};
#end
## ---------- END 字段循环遍历 ----------
#if(!${entityLombokModel})
#foreach($field in ${table.fields})
#if(${field.propertyType.equals("boolean")})
#set($getprefix="is")
#else
#set($getprefix="get")
#end
public ${field.propertyType} ${getprefix}${field.capitalName}() {
return ${field.propertyName};
}
#if(${entityBuilderModel})
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
#else
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
#end
this.${field.propertyName} = ${field.propertyName};
#if(${entityBuilderModel})
return this;
#end
}
#end
## --foreach end---
#end
## --end of
#if(${entityColumnConstant})
#foreach($field in ${table.fields})
public static final String ${field.name.toUpperCase()} = "${field.name}";
#end
#end
#if(${activeRecord})
@Override
protected Serializable pkVal() {
#if(${keyPropertyName})
return this.${keyPropertyName};
#else
return this.id;
#end
}
#end
#if(!${entityLombokModel})
@Override
public String toString() {
return "${entity}{" +
#foreach($field in ${table.fields})
#if($!{velocityCount}==1)
"${field.propertyName}=" + ${field.propertyName} +
#else
", ${field.propertyName}=" + ${field.propertyName} +
#end
#end
"}";
}
#end
}
2.4 Mapper接口 - mapper.java.vm
package ${package.Mapper};
import ${package.Entity}.${entity};
import ${superMapperClassPackage};
import org.springframework.stereotype.Repository;
@Repository
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
}
2.5 Mapper-XML - 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}">
#if(${enableCache})
<!-- 开启二级缓存 -->
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
#end
#if(${baseResultMap})
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${package.Entity}.${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>
#end
#if(${baseColumnList})
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
#foreach($field in ${table.commonFields})
#if(${field.name} == ${field.propertyName})${field.name}#else${field.name} AS ${field.propertyName}#end,
#end
${table.fieldNames}
</sql>
#end
</mapper>
2.6 业务层 - service.java.vm
package ${package.Service};
import com.hikktn.common.base.PageDto;
import ${package.Entity}.${entity};
import ${superServiceClassPackage};
#set($entityName = ${entity.substring(0,1).toLowerCase()}+${entity.substring(1)})
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
@Override
boolean save(${entity} $entityName);
PageDto<${entity}> page(PageDto<${entity}> pageDto);
}
2.7 业务实现层 - serviceImpl.java.vm
package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import com.hikktn.common.base.PageDto;
import org.springframework.stereotype.Service;
import com.hikktn.common.validator.ValidatorUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
#set($entityName = ${entity.substring(0,1).toLowerCase()}+${entity.substring(1)})
@Service
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} {
@Override
public boolean save(${entity} $entityName) {
ValidatorUtils.validateEntity($entityName);
return this.save($entityName);
}
@Override
public PageDto<${entity}> page(PageDto<${entity}> pageDto) {
QueryWrapper<${entity}> ew = new QueryWrapper<>();
return new PageDto<>(super.page(pageDto.getDbPage(), ew));
}
}
2.8 appliaction.yml
spring:
application:
name: mybatis-plus-demo
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/my_mybatis_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
username: root
password: 123456
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
2.9 生成类
package com.hikktn.generator;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import java.util.*;
public class MyGenerator {
private static final String SERVICE_NAME = "content";
private static final StringBuilder FINAL_PATH = new StringBuilder();
private static final String[] TABLE_NAMES = new String[]{"tb_user", "t_area"};
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help);
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
String[] tableName = scanner("表名,多个英文逗号分割").split(",");
generateByTables(tableName);
}
private static void generateByTables(String... tableNames) {
AutoGenerator mpg = new AutoGenerator();
mpg.setTemplateEngine(new VelocityTemplateEngine());
GlobalConfig gc = globalGenerate();
PackageConfig pc = packageGenerate();
List<FileOutConfig> foc = fileOutGenerate(pc);
InjectionConfig cfg = injectionGenerate(foc);
DataSourceConfig dsc = dataSourceGenerate();
TemplateConfig tc = templateGenerate();
StrategyConfig strategy = strategyGenerate(tableNames);
mpg.setGlobalConfig(gc);
mpg.setDataSource(dsc);
mpg.setPackageInfo(pc);
mpg.setCfg(cfg);
mpg.setTemplate(tc);
mpg.setStrategy(strategy);
mpg.execute();
}
private static DataSourceConfig dataSourceGenerate() {
YamlPropertiesFactoryBean yamlMapFactoryBean = new YamlPropertiesFactoryBean();
yamlMapFactoryBean.setResources(new ClassPathResource("application.yml"));
Properties properties = yamlMapFactoryBean.getObject();
String url = properties.getProperty("spring.datasource.url");
String driver = properties.getProperty("spring.datasource.driver-class-name");
String username = properties.getProperty("spring.datasource.username");
String password = properties.getProperty("spring.datasource.password");
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setUrl(url);
dsc.setDriverName(driver);
dsc.setUsername(username);
dsc.setPassword(password);
return dsc;
}
private static GlobalConfig globalGenerate() {
GlobalConfig gc = new GlobalConfig();
gc.setFileOverride(true);
String projectPath = System.getProperty("user.dir");
String path = MyGenerator.class.getClassLoader().getResource("").getPath();
String levelPath = path.substring(0, path.indexOf("target") - 1);
if (!projectPath.equals(levelPath)) {
FINAL_PATH.append(levelPath);
} else {
FINAL_PATH.append(projectPath);
}
gc.setOutputDir(FINAL_PATH + "/src/main/java");
gc.setAuthor("hikktn");
gc.setOpen(false);
gc.setEnableCache(false);
gc.setSwagger2(true);
gc.setControllerName("%sController");
gc.setServiceName("%sService");
gc.setServiceImplName("%sServiceImpl");
gc.setMapperName("%sMapper");
gc.setXmlName("%sMapper");
gc.setBaseResultMap(true);
gc.setBaseColumnList(true);
gc.setIdType(IdType.ID_WORKER);
return gc;
}
private static StrategyConfig strategyGenerate(String[] tableName) {
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setCapitalMode(false);
strategy.setEntityLombokModel(false);
strategy.setRestControllerStyle(true);
strategy.setSuperControllerClass("com.hikktn.common.base.BaseController");
strategy.setInclude(tableName);
strategy.setTablePrefix("tb_");
strategy.setEntityBooleanColumnRemoveIsPrefix(true);
strategy.setControllerMappingHyphenStyle(true);
strategy.setEntityBuilderModel(true);
return strategy;
}
private static TemplateConfig templateGenerate() {
TemplateConfig tc = new TemplateConfig();
tc.setController("templates/controller.java.vm")
.setEntity("templates/entity.java.vm")
.setService("templates/service.java.vm")
.setServiceImpl("templates/serviceImpl.java.vm")
.setMapper("templates/mapper.java.vm")
.setXml(null);
return tc;
}
private static List<FileOutConfig> fileOutGenerate(PackageConfig pc) {
String templatePath = "/templates/mapper.xml.vm";
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
return FINAL_PATH + "/src/main/resources/mapper/"
+ tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
return focList;
}
private static InjectionConfig injectionGenerate(List<FileOutConfig> focList) {
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = new HashMap<>(10);
map.put("version", "1.0");
map.put("logicDeleteFieldName","is_deleted");
map.put("createTime","create_time");
map.put("updateTime","update_time");
this.setMap(map);
}
};
cfg.setFileOutConfigList(focList);
return cfg;
}
private static PackageConfig packageGenerate() {
PackageConfig pc = new PackageConfig();
pc.setModuleName(SERVICE_NAME);
pc.setParent("com.hikktn");
pc.setEntity("entity");
pc.setService("service");
pc.setServiceImpl("service.impl");
pc.setMapper("dao");
pc.setXml(null);
return pc;
}
}