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>
<!--mybatis-plus的springboot支持-->
<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>
<!-- MP 核心库 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.1.0</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--简化代码的工具包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 模板引擎依赖Freemarker -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.29</version>
</dependency>
<!-- thymeleaf模板插件 -->
<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>
<!-- velocity -->
<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
/**
* <p>
* $!{tablement} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
* @version ${cfg.version}
*/
#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 = "$!{tablement}", produces = MediaType.APPLICATION_JSON_VALUE)
public class ${table.controllerName} extends ${superControllerClass} {
@Autowired
private ${table.serviceName} ${entityName}Service;
@ResponseBody
@ApiOperation(value = "$!{tablement}-分页查询", notes = "$!{tablement}-分页查询")
@RequestMapping(value = "/_search", method = RequestMethod.POST)
public RestResponse search(@RequestBody PageDto<${entity}> page){
return RestResponse.success();
}
@ResponseBody
@ApiOperation(value = "$!{tablement}-保存", notes = "$!{tablement}-保存")
@RequestMapping(value = "", method = RequestMethod.POST)
public RestResponse<String> save(@RequestBody ${entity} $entityName){
${entityName}Service.save($entityName);
return RestResponse.success();
}
@ResponseBody
@ApiOperation(value = "$!{tablement}-更新", notes = "$!{tablement}-更新")
@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 = "$!{tablement}-删除", notes = "$!{tablement}-删除")
@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
## 表备注,作者,日期
/**
* <p>
* $!{tablement}
* </p>
*
* @author ${author}
* @since ${date}
* @version ${cfg.version}
*/
#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("$!fieldment" != "")
#if(${swagger2})
/**
* ${fieldment}
*/
@ApiModelProperty(value = "${fieldment}")
#else
/**
* ${fieldment}
*/
#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;
/**
* <p>
* $!{tablement} Mapper 接口
* </p>
*
* @author ${author}
* @since ${date}
* @version ${cfg.version}
*/
@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//DTD Mapper 3.0//EN" "http://mybatis/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};
/**
* <p>
* $!{tablement} 服务类
* </p>
*
* @author ${author}
* @since ${date}
* @version ${cfg.version}
*/
#set($entityName = ${entity.substring(0,1).toLowerCase()}+${entity.substring(1)})
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
/**
* 添加
* @param $entityName
*/
@Override
boolean save(${entity} $entityName);
/**
* 分页查询
* @param pageDto 分页
* @return
*/
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;
/**
* <p>
* $!{tablement} 服务实现类
* </p>
*
* @author ${author}
* @since ${date}
* @version ${cfg.version}
*/
#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
#logging:
# level:
# root: debug
mybatis-plus:
# 读取mybatis配置文件
# config-location: classpath:mybatis/mybatis-config.xml
# 读取mapper文件
# mapper-locations: classpath*:mybatis/mapper/*Mapper.xml
# 别名配置,在mybatis.xml文件resultType属性可以不指定类的全路径
# type-aliases-package: com.hikktn.pojo
# 开启驼峰映射,注意:配置configuration.map-underscore-to-camel-case则不能配置config-location
# configuration:
# map-underscore-to-camel-case: true
# 日志
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 逻辑删除
global-config:
db-config:
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 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.*;
/**
* @ClassName MpGenerator
* @Description Mybatis-Plus代码生成器
* @Author lisonglin
* @Date 2021/5/30 15:09
* @Version 1.0
*/
public class MyGenerator {
// TODO 修改服务名以及数据表名
/**
* 顶层包名
*/
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"};
/**
* <p>
* 读取控制台内容
* </p>
*/
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) {
// 选择 freemarker 引擎,默认 Velocity
AutoGenerator mpg = new AutoGenerator();
// mpg.setTemplateEngine(new FreemarkerTemplateEngine());
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();
}
/**
* 数据库配置
*
* @return 数据源
*/
private static DataSourceConfig dataSourceGenerate() {
YamlPropertiesFactoryBean yamlMapFactoryBean = new YamlPropertiesFactoryBean();
yamlMapFactoryBean.setResources(new ClassPathResource("application.yml"));
//获取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;
}
/**
* 全局配置
*
* @return 全局配置
*/
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);
// XML 二级缓存
gc.setEnableCache(false);
//是否使用swagger2
gc.setSwagger2(true);
// 自定义文件命名,注意 %s 会自动填充表实体属性!
gc.setControllerName("%sController");
gc.setServiceName("%sService");
gc.setServiceImplName("%sServiceImpl");
gc.setMapperName("%sMapper");
gc.setXmlName("%sMapper");
//mapper.xml中生成基础resultMap
gc.setBaseResultMap(true);
//mapper.xml中生成基础columnList
gc.setBaseColumnList(true);
// 主键类型
gc.setIdType(IdType.ID_WORKER);
return gc;
}
/**
* 策略配置
* 主要的表字段映射
*
* @param tableName 表名
* @return 策略配置
*/
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);
//实体类使用lombok
strategy.setEntityLombokModel(false);
//controller使用rest接口模式
strategy.setRestControllerStyle(true);
// 继承顶层controller
strategy.setSuperControllerClass("com.hikktnmon.base.BaseController");
//设置表名
strategy.setInclude(tableName);
//strategy.setInclude(TABLE_NAMES);
//表名映射到实体名称去掉前缀
strategy.setTablePrefix("tb_");
// Boolean类型字段是否移除is前缀处理
strategy.setEntityBooleanColumnRemoveIsPrefix(true);
// 驼峰转连字符
strategy.setControllerMappingHyphenStyle(true);
// 建造者模式
strategy.setEntityBuilderModel(true);
return strategy;
}
/**
* 自定义模板
*
* @return 模板
*/
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")
// 不要源码包内的mapper
.setXml(null);
return tc;
}
/**
* 文件路径输出配置
*
* @param pc 包配置
* @return 文件路径输出配置
*/
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) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return FINAL_PATH + "/src/main/resources/mapper/"
+ tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
return focList;
}
/**
* 其他参数,在velocity使用的参数,格式:${cfg.version}
*
* @param focList 文件路径输出配置
* @return 其他参数
*/
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;
}
/**
* 包配置
*
* @return 包配置
*/
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;
}
}
更多推荐
Mybatis-Plus代码生成器Velocity模板
发布评论