MyBatis-Plus (简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
github地址:https://github.com/baomidou/mybatis-plus
今天主要介绍他的代码生成功能。其实官方文档已经写得很清楚了,这里做了些简单的封装。官方代码生成器文档:https://mybatis.plus/guide/generator.html。
mybatis-plus-generator:根据数据源中的表,反向生成controller、entity、service和mapper。
项目是作为一个整个maven项目的一个模块,结构如下:
首先是依赖,我用的是freemarker的模板,所以引入了org.freemarker,依赖如下:
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
定义一个CodeGeneConfig类,里面是mybatis-plus-generator常用的配置属性,还有一个CodeGeneProps类,对应属性文件code.properties里面的key。分别如图:
@Data
public class CodeGeneConfig {
private String geneModule;
private String genePkgModule;
private String genePkgParent;
private String geneDsUrl;
private String geneDsUsername;
private String geneDsPassword;
private String geneTableNames;
private String geneTablePrefix;
private String geneBaseEntity;
private String geneBaseEntityFields;
private String geneBaseController;
private String geneEntityName;
private String geneAuthor;
}
public interface CodeGeneProps {
/**
* 项目子模块
*/
String GENE_MODULE = "gene.module";
/**
* 所在包
*/
String GENE_PKG_MODULE = "gene.pkg.module";
/**
* 所在包的父包
*/
String GENE_PKG_PARENT = "gene.pkg.parent";
/**
* 数据源url
*/
String GENE_DS_URL = "gene.ds.url";
/**
* 数据源账号
*/
String GENE_DS_USERNAME = "gene.ds.username";
/**
* 数据源密码
*/
String GENE_DS_PASSWORD = "gene.ds.password";
/**
* 全部表名,多个用逗号分隔
*/
String GENE_TABLE_NAMES = "gene.table.names";
/**
* 表前缀,生成@TableName注解里的表前缀
*/
String GENE_TABLE_PREFIX = "gene.table.prefix";
/**
* entity的父类
*/
String GENE_BASE_ENTITY = "gene.base.entity";
/**
* entity父类的字段,多个用逗号分隔
*/
String GENE_BASE_ENTITY_FIELDS = "gene.base.entity.fields";
/**
* controller的父类
*/
String GENE_BASE_CONTROLLER = "gene.base.controller";
/**
* entity的类名
*/
String GENE_ENTITY_NAME = "gene.entity.name";
/**
* 注释中的author
*/
String GENE_AUTHOR = "gene.author";
}
gene.module=easy-starter-app
gene.pkg.module=system
gene.pkg.parent=me.heys
gene.ds.url=jdbc:mysql://192.168.41.130:3306/trade?useUnicode=true&characterEncoding=utf-8
gene.ds.username=root
gene.ds.password=mysql
gene.table.names=t_user
gene.table.prefix=t_
gene.base.entity=me.heys.core.base.BaseEntity
gene.base.entity.fields=id,create_user,create_time,update_time
gene.base.controller=
gene.entity.name=%sEntity
gene.author=heys
最后就是CodeGenerator类,基本上是依照官方文档写的。CodeGeneConfig配置优先,如果没有配置,就读取code.properties里面的配置:
@Slf4j
public class CodeGenerator {
private CodeGeneConfig config;
public CodeGenerator(CodeGeneConfig config) {
this.config = mergeProps(config);
}
private CodeGeneConfig mergeProps(CodeGeneConfig config) {
if (null == config) {
config = new CodeGeneConfig();
}
Properties props = new Properties();
try {
props.load(CodeGenerator.class.getClassLoader().getResourceAsStream("code.properties"));
} catch (IOException e) {
log.error("CodeGenerator读取配置失败", e);
}
if (StringUtil.isBlank(config.getGeneModule())) {
config.setGeneModule(props.getProperty(CodeGeneProps.GENE_MODULE));
}
if (StringUtil.isBlank(config.getGenePkgModule())) {
config.setGenePkgModule(props.getProperty(CodeGeneProps.GENE_PKG_MODULE));
}
if (StringUtil.isBlank(config.getGenePkgParent())) {
config.setGenePkgParent(props.getProperty(CodeGeneProps.GENE_PKG_PARENT));
}
if (StringUtil.isBlank(config.getGeneDsUrl())) {
config.setGeneDsUrl(props.getProperty(CodeGeneProps.GENE_DS_URL));
}
if (StringUtil.isBlank(config.getGeneDsUsername())) {
config.setGeneDsUsername(props.getProperty(CodeGeneProps.GENE_DS_USERNAME));
}
if (StringUtil.isBlank(config.getGeneDsPassword())) {
config.setGeneDsPassword(props.getProperty(CodeGeneProps.GENE_DS_PASSWORD));
}
if (StringUtil.isBlank(config.getGeneTableNames())) {
config.setGeneTableNames(props.getProperty(CodeGeneProps.GENE_TABLE_NAMES));
}
if (StringUtil.isBlank(config.getGeneTablePrefix())) {
config.setGeneTablePrefix(props.getProperty(CodeGeneProps.GENE_TABLE_PREFIX));
}
if (StringUtil.isBlank(config.getGeneBaseEntity())) {
config.setGeneBaseEntity(props.getProperty(CodeGeneProps.GENE_BASE_ENTITY));
}
if (StringUtil.isBlank(config.getGeneBaseEntityFields())) {
config.setGeneBaseEntityFields(props.getProperty(CodeGeneProps.GENE_BASE_ENTITY_FIELDS));
}
if (StringUtil.isBlank(config.getGeneBaseController())) {
config.setGeneBaseController(props.getProperty(CodeGeneProps.GENE_BASE_CONTROLLER));
}
if (StringUtil.isBlank(config.getGeneEntityName())) {
config.setGeneEntityName(props.getProperty(CodeGeneProps.GENE_ENTITY_NAME));
}
if (StringUtil.isBlank(config.getGeneAuthor())) {
config.setGeneAuthor(props.getProperty(CodeGeneProps.GENE_AUTHOR));
}
return config;
}
public void execute() {
// 代码生成器
AutoGenerator generator = new AutoGenerator();
// 全局配置
GlobalConfig globalConfig = new GlobalConfig();
StringBuilder builder = new StringBuilder(System.getProperty("user.dir"));
if (StringUtil.isNotBlank(config.getGeneModule())) {
builder.append("/" + config.getGeneModule());
}
builder.append("/src/main/java");
globalConfig.setEntityName(config.getGeneEntityName());
globalConfig.setOutputDir(builder.toString());
globalConfig.setAuthor(config.getGeneAuthor());
globalConfig.setOpen(false);
generator.setGlobalConfig(globalConfig);
// 数据源配置
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setUrl(config.getGeneDsUrl());
dataSourceConfig.setSchemaName("public");
dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
dataSourceConfig.setUsername(config.getGeneDsUsername());
dataSourceConfig.setPassword(config.getGeneDsPassword());
generator.setDataSource(dataSourceConfig);
// 包配置
PackageConfig packageConfig = new PackageConfig();
packageConfig.setModuleName(config.getGenePkgModule());
packageConfig.setParent(config.getGenePkgParent());
generator.setPackageInfo(packageConfig);
// 模板配置
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setXml(null);
generator.setTemplate(templateConfig);
InjectionConfig injectionConfig = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = new HashMap<>();
// 用来作为类注释的时间,模板中通过${cfg.datetime}获取
map.put("datetime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
this.setMap(map);
}
};
generator.setCfg(injectionConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
if (StringUtil.isNotBlank(config.getGeneBaseEntity())) {
strategy.setSuperEntityClass(config.getGeneBaseEntity());
}
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
if (StringUtil.isNotBlank(config.getGeneBaseController())) {
strategy.setSuperControllerClass(config.getGeneBaseController());
}
strategy.setInclude(config.getGeneTableNames().split(","));
String superFields = config.getGeneBaseEntityFields();
if(StringUtil.isNotBlank(superFields)) {
strategy.setSuperEntityColumns(superFields.split(","));
}
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(config.getGeneTablePrefix());
generator.setStrategy(strategy);
generator.setTemplateEngine(new FreemarkerTemplateEngine());
generator.execute();
}
}
使用方式:
public class Generator {
public static void main(String[] args) {
CodeGeneConfig codeGeneConfig = new CodeGeneConfig();
codeGeneConfig.setGeneModule("easy-starter-app");
new CodeGenerator(codeGeneConfig).execute();
}
}
mybatis-plus-generator的templates目录下是模板,稍微修改了一下模板:修改了注释、加了@Slf4j注解。
只需要把模板复制到自己代码resources/templates目录下,会自动读取。
这个模块可以打成一个jar包,在不同地方单独使用。如下效果: