【Mybatis-Plus】制作逆向工具
官方文档可参考:
https://baomidou.com/pages/779a6e/#快速入门
工具需要的依赖
<?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>cn.ymcd</groupId> <artifactId>comm-sample</artifactId> <version>1.0.0</version> </parent> <artifactId>comm-sample-mp-generator</artifactId> <name>comm-sample-mp-generator</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.1.1</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.1</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.28</version> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>11.1.0.7.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.ini4j</groupId> <artifactId>ini4j</artifactId> <version>0.5.4</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <!-- 主类的位置,例如上图文件,主类配置应为: --> <!-- <mainClass>top.nihilwater.App</mainClass> --> <mainClass>cn.ymcd.comm.sample.mp.generator.MainApplication</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
代码部分
代码部分只有一个主类:
package cn.ymcd.comm.sample.mp.generator; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.InjectionConfig; import com.baomidou.mybatisplus.generator.config.*; import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert; import com.baomidou.mybatisplus.generator.config.po.TableInfo; import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; import org.ini4j.Profile; import org.ini4j.Wini; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * @projectName: comm-sample-mp-generator - 副本 * @author: Cloud9 * @date: 2022年05月31日 13:48 * @version: 1.0 */ public class MainApplication { private static Wini windowsConfigIniFile; private final static String STATUS_TRUE = "true"; private final static String STATUS_FALSE = "false"; private static String commonPath = null; private static GlobalConfig globalConfig; private static DataSourceConfig dataSourceConfig; private static PackageConfig packageConfig; private static TemplateConfig templateConfig; private static StrategyConfig strategyConfig; static { try { windowsConfigIniFile = new Wini(new File("config.ini")); commonPath = windowsConfigIniFile .get("global-config") .get("output-directory", "C:\\Users\\Administrator\\Desktop\\Sample"); globalConfig = getGlobalConfig(); dataSourceConfig = getDataSourceConfig(); packageConfig = getPackageConfig(); templateConfig = getTemplateConfig(); strategyConfig = getStrategyConfig(); } catch (IOException e) { e.printStackTrace(); } } private static boolean getBooleanValue(String value) { return "true".equals(value); } private static DateType getDateTypeValue(String value) { DateType dateType = null; switch (value) { case "default": dateType = DateType.ONLY_DATE; break; case "sql-type": dateType = DateType.SQL_PACK; break; case "new-type": dateType = DateType.TIME_PACK; break; } return dateType; } private static IdType getIdTypeValue(String value) { IdType idType = null; switch (value) { case "0": idType = IdType.AUTO; break; case "1": idType = IdType.NONE; break; case "2": idType = IdType.INPUT; break; case "3": idType = IdType.ID_WORKER; break; case "4": idType = IdType.UUID; break; case "5": idType = IdType.ID_WORKER_STR; break; } return idType; } /** * 全局配置 * @param * @return com.baomidou.mybatisplus.generator.config.GlobalConfig * @author Cloud9 * @createTime 2022/5/31 14:33 * */ private static GlobalConfig getGlobalConfig() { Profile.Section section = windowsConfigIniFile.get("global-config"); GlobalConfig globalConfig = new GlobalConfig(); globalConfig.setOutputDir(commonPath + "/src/main/java"); globalConfig.setAuthor(section.get("author", "cloud9")); globalConfig.setOpen(getBooleanValue(section.get("open-after-complete", STATUS_FALSE))); globalConfig.setFileOverride(getBooleanValue(section.get("overwrite", STATUS_TRUE))); globalConfig.setActiveRecord(getBooleanValue(section.get("ar-mode", STATUS_FALSE))); globalConfig.setSwagger2(getBooleanValue(section.get("enable-swagger2", STATUS_FALSE))); globalConfig.setKotlin(getBooleanValue(section.get("kotlin-mode", STATUS_FALSE))); // 主键策略 globalConfig.setIdType(getIdTypeValue(section.get("id-type", "0"))); // 日期类型选择 globalConfig.setDateType(getDateTypeValue(section.get("date-type", "default"))); // 文件格式命名 globalConfig.setEntityName(section.get("entity-format", "%sDTO")); globalConfig.setMapperName(section.get("mapper-format", "%sDAO")); // globalConfig.setXmlName(section.get("xml-format", "%sMapper")); // globalConfig.setServiceName(section.get("service-format", "I%sService")); // globalConfig.setServiceImplName(section.get("service-impl-format", "%sServiceImpl")); // globalConfig.setControllerName(section.get("controller-format", "%sController")); return globalConfig; } /** * 获取库名 * @param * @return java.lang.String * @author Cloud9 * @createTime 2022/5/31 14:54 * */ private static String getSchemaValue() { Profile.Section section = windowsConfigIniFile.get("db-config"); String connectUrl = section.get("connectUrl"); int i1 = connectUrl.lastIndexOf("/") + 1; int i2 = connectUrl.lastIndexOf("?"); return connectUrl.substring(i1, i2 == -1 ? connectUrl.length() -1 : i2); } /** * 数据源配置 * @param * @return com.baomidou.mybatisplus.generator.config.DataSourceConfig * @author Cloud9 * @createTime 2022/5/31 14:33 * */ private static DataSourceConfig getDataSourceConfig() { Profile.Section section = windowsConfigIniFile.get("db-config"); DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl(section.get("connectUrl")); dsc.setSchemaName(getSchemaValue()); dsc.setDriverName(section.get("driverClass")); dsc.setUsername(section.get("username")); dsc.setPassword(section.get("password")); dsc.setDbQuery(new MySqlQuery()); dsc.setDbType(DbType.MYSQL); dsc.setTypeConvert(new MySqlTypeConvert()); return dsc; } /** * 包配置 * @param * @return com.baomidou.mybatisplus.generator.config.PackageConfig * @author Cloud9 * @createTime 2022/5/31 14:54 * */ private static PackageConfig getPackageConfig() { Profile.Section section = windowsConfigIniFile.get("package-config"); PackageConfig pkgConfig = new PackageConfig(); pkgConfig.setParent(section.get("parent")); pkgConfig.setModuleName(section.get("module", "test")); pkgConfig.setEntity(section.get("entity", "po")); pkgConfig.setXml(section.get("xml", "mapper")); pkgConfig.setMapper(section.get("mapper", "dao")); pkgConfig.setService(section.get("service", "service")); pkgConfig.setServiceImpl(section.get("service-impl", "service.impl")); pkgConfig.setController(section.get("controller", "controller")); return pkgConfig; } /** * 模板配置 * @param * @return com.baomidou.mybatisplus.generator.config.TemplateConfig * @author Cloud9 * @createTime 2022/5/31 14:53 * */ private static TemplateConfig getTemplateConfig() { // 配置模板 TemplateConfig templateConfig = new TemplateConfig(); // 配置自定义输出模板 // 指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别 // templateConfig.setEntity("templates/entity2.java"); // templateConfig.setService(); // templateConfig.setController(); templateConfig.setXml(null); templateConfig.setEntity("tpl/entity.java"); templateConfig.setController("tpl/controller.java"); templateConfig.setEntityKt("tpl/entity.kt"); templateConfig.setMapper("tpl/mapper.java"); templateConfig.setService("tpl/service.java"); templateConfig.setServiceImpl("tpl/serviceImpl.java"); return templateConfig; } /** * 注入配置 * @param * @return com.baomidou.mybatisplus.generator.InjectionConfig * @author Cloud9 * @createTime 2022/5/31 15:14 * */ private static InjectionConfig getInjectionConfig() { // 自定义配置 InjectionConfig cfg = new InjectionConfig() { @Override public void initMap() { // to do nothing } }; // 如果模板引擎是 freemarker String templatePath = "/tpl/mapper.xml.ftl"; // 如果模板引擎是 velocity // 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 commonPath + "/src/main/resources/mapper/" + packageConfig.getModuleName() + "/" + tableInfo.getMapperName() + StringPool.DOT_XML; } }); /* * cfg.setFileCreate(new IFileCreate() { * * @Override public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) { // * 判断自定义文件夹是否需要创建 checkDir("调用默认方法创建的目录"); return false; } }); */ cfg.setFileOutConfigList(focList); return cfg; } /** * 策略配置 * @param * @return com.baomidou.mybatisplus.generator.config.StrategyConfig * @author Cloud9 * @createTime 2022/5/31 15:14 * */ private static StrategyConfig getStrategyConfig() { Profile.Section section = windowsConfigIniFile.get("strategy-config"); StrategyConfig strategyConfig = new StrategyConfig(); strategyConfig.setNaming(NamingStrategy.underline_to_camel); strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel); //strategy.setSuperEntityClass("com.baomidou.ant.common.BaseEntity"); strategyConfig.setEntityLombokModel(getBooleanValue(section.get("lombok-model", STATUS_TRUE))); strategyConfig.setRestControllerStyle(getBooleanValue(section.get("rest-controller", STATUS_TRUE))); strategyConfig.setSuperControllerClass(section.get("super-controller", "cn.ymcd.comm.base.BaseController")); strategyConfig.setSuperServiceImplClass(section.get("super-service-impl", "com.baomidou.mybatisplus.extension.service.impl.ServiceImpl")); strategyConfig.setInclude(includesHandle((section.get("includes").split(",")))); //strategy.setSuperEntityColumns("id"); strategyConfig.setControllerMappingHyphenStyle(getBooleanValue(section.get("hyphen-style", STATUS_TRUE))); strategyConfig.setTablePrefix(packageConfig.getModuleName() + "_"); return strategyConfig; } private static String[] includesHandle(String[] includes) { for (int i = 0; i < includes.length; i++) includes[i] = includes[i].trim(); return includes; } private static AutoGenerator getAutoGenerator() { AutoGenerator mpg = new AutoGenerator(); mpg.setGlobalConfig(globalConfig); mpg.setDataSource(dataSourceConfig); mpg.setPackageInfo(packageConfig); mpg.setCfg(getInjectionConfig()); mpg.setStrategy(strategyConfig); mpg.setTemplate(templateConfig); mpg.setTemplateEngine(new FreemarkerTemplateEngine()); return mpg; } public static void main(String[] args) { getAutoGenerator().execute(); } }
还是走配置文件设置参数:
config.ini 放在项目的目录下面,不是src里面
[global-config] # 输出目录 output-directory = C:\Users\Administrator\Desktop\AISW-TEST # 创建者 author = dzz # 完成后打开目录 open-after-complete = true # 覆写输出 overwrite = true # 开启Swagger2注解 enable-swagger2 = false # ActiveRecord 模式 ar-mode = false # 转换科特林代码 kotlin-mode = false # 生成的时间类型,(default, sql-type, new-type) date-type = default # 主键生成策略 (0 1 2 3 4 5) id-type = 0 # 实体类文件命名格式 entity-format = %sDTO # 映射接口文件命名格式 mapper-format = %sDAO # 映射接口文件命名格式 xml-format = %sMapper # 服务接口文件命名格式 service-format = I%sService # 服务实现文件命名格式 service-impl-format = %sServiceImpl # 控制器文件命名格式 controller-format = %sController [db-config] # 连接配置参数 connectUrl = jdbc:mysql://192.168.209.11:3306/ymcd_aisw?useSSL=false&serverTimeZone=GMT driverClass = com.mysql.jdbc.Driver username = root password = 123456 [package-config] # 包名配置 parent = cn.cloud9.sample module = test entity = po mapper = dao xml = mapper service = service service-impl = service.impl controller = controller [strategy-config] # 开启Lombok注解? lombok-model = true # 是否@RestController rest-controller = true # 指定生成的表名,多个用逗号进行分隔 includes = aisw_netplace, aisw_netplace_sync_log # 继承的控制器类名 super-controller = cn.ymcd.comm.base.BaseController # 继承的服务实现类名 super-service-impl = cn.ymcd.comm.base.BaseService # 接口地址 驼峰转至连字符 hyphen-style = true
模板部分
因为设置模板文件路径,所以是采用自定义模板来输出
templateConfig.setXml(null); templateConfig.setEntity("tpl/entity.java"); templateConfig.setController("tpl/controller.java"); templateConfig.setEntityKt("tpl/entity.kt"); templateConfig.setMapper("tpl/mapper.java"); templateConfig.setService("tpl/service.java"); templateConfig.setServiceImpl("tpl/serviceImpl.java");
Controller.java.ftl
package ${package.Controller}; import org.springframework.web.bind.annotation.RequestMapping; <#if restControllerStyle> import org.springframework.web.bind.annotation.RestController; <#else> import org.springframework.stereotype.Controller; </#if> <#if superControllerClassPackage??> import ${superControllerClassPackage}; </#if> /** * ${table.name!} ${table.comment!} 前端控制器 * * @projectName: * @author:${author} * @date:${date} * @version 1.0 */ <#if restControllerStyle> @RestController <#else> @Controller </#if> @RequestMapping("${r'${api.path}'}<#if package.ModuleName??>/${package.ModuleName}</#if>") <#if kotlin> class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if> <#else> <#if superControllerClass??> public class ${table.controllerName} extends ${superControllerClass} { <#else> public class ${table.controllerName} { </#if> } </#if>
entity.java.ftl
package ${package.Entity}; <#list table.importPackages as pkg> import ${pkg}; </#list> <#if swagger2> import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; </#if> <#if entityLombokModel> import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; </#if> /** * ${table.name!} ${table.comment!} 实体类 * * @projectName: * @author:${author} * @date:${date} * @version 1.0 */ <#if entityLombokModel> @Data <#if superEntityClass??> @EqualsAndHashCode(callSuper = true) <#else> @EqualsAndHashCode(callSuper = false) </#if> @Accessors(chain = true) </#if> <#if table.convert> @TableName("${table.name}") </#if> <#if swagger2> @ApiModel(value="${entity}对象", description="${table.comment!}") </#if> <#if superEntityClass??> public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> { <#elseif activeRecord> public class ${entity} extends Model<${entity}> { <#else> public class ${entity} implements Serializable { </#if> <#if entitySerialVersionUID> private static final long serialVersionUID = 1L; </#if> <#-- ---------- BEGIN 字段循环遍历 ----------> <#list table.fields as field> <#if field.keyFlag> <#assign keyPropertyName="${field.propertyName}"/> </#if> <#if field.comment!?length gt 0> <#if swagger2> @ApiModelProperty(value = "${field.comment}") <#else> /** * ${field.comment} */ </#if> </#if> <#if field.keyFlag> <#-- 主键 --> <#if field.keyIdentityFlag> @TableId(value = "${field.name}", type = IdType.AUTO) <#elseif idType??> @TableId(value = "${field.name}", type = IdType.${idType}) <#elseif field.convert> @TableId("${field.name}") </#if> <#-- 普通字段 --> <#elseif field.fill??> <#-- ----- 存在字段填充设置 -----> <#if field.convert> @TableField(value = "${field.name}", fill = FieldFill.${field.fill}) <#else> @TableField(fill = FieldFill.${field.fill}) </#if> <#elseif field.convert> @TableField("${field.name}") </#if> <#-- 乐观锁注解 --> <#if (versionFieldName!"") == field.name> @Version </#if> <#-- 逻辑删除注解 --> <#if (logicDeleteFieldName!"") == field.name> @TableLogic </#if> private ${field.propertyType} ${field.propertyName}; </#list> <#------------ END 字段循环遍历 ----------> <#if !entityLombokModel> <#list table.fields as field> <#if field.propertyType == "boolean"> <#assign getprefix="is"/> <#else> <#assign getprefix="get"/> </#if> 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}) { </#if> this.${field.propertyName} = ${field.propertyName}; <#if entityBuilderModel> return this; </#if> } </#list> </#if> <#if entityColumnConstant> <#list table.fields as field> public static final String ${field.name?upper_case} = "${field.name}"; </#list> </#if> <#if activeRecord> @Override protected Serializable pkVal() { <#if keyPropertyName??> return this.${keyPropertyName}; <#else> return null; </#if> } </#if> <#if !entityLombokModel> @Override public String toString() { return "${entity}{" + <#list table.fields as field> <#if field_index==0> "${field.propertyName}=" + ${field.propertyName} + <#else> ", ${field.propertyName}=" + ${field.propertyName} + </#if> </#list> "}"; } </#if> }
mapper.java.ftl
package ${package.Mapper}; import ${package.Entity}.${entity}; import ${superMapperClassPackage}; /** * ${table.name!} ${table.comment!} Mapper 接口 * * @projectName: * @author:${author} * @date:${date} * @version 1.0 */ <#if kotlin> interface ${table.mapperName} : ${superMapperClass}<${entity}> <#else> public interface ${table.mapperName} extends ${superMapperClass}<${entity}> { } </#if>
service.java.ftl
package ${package.Service}; import ${package.Entity}.${entity}; import ${superServiceClassPackage}; /** * ${table.name!} ${table.comment!} 服务类 * * @projectName: * @author:${author} * @date:${date} * @version 1.0 */ <#if kotlin> interface ${table.serviceName} : ${superServiceClass}<${entity}> <#else> public interface ${table.serviceName} extends ${superServiceClass}<${entity}> { } </#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="org.mybatis.caches.ehcache.LoggingEhcache"/> </#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.name}, </#list> ${table.fieldNames} </sql> </#if> </mapper>
serviceImpl.java.ftl
package ${package.ServiceImpl}; import ${package.Entity}.${entity}; import ${package.Mapper}.${table.mapperName}; import ${package.Service}.${table.serviceName}; import ${superServiceImplClassPackage}; import org.springframework.stereotype.Service; /** * ${table.name!} ${table.comment!} 服务实现类 * * @projectName: * @author:${author} * @date:${date} * @version 1.0 */ @Service <#if kotlin> open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} { } <#else> public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} { } </#if>
打包之后,自己新建目录做一个工具包
Start.cmd 只是方便启动Jar包
java -jar comm-sample-mp-generator-1.0.0.jar
如果要保留执行日志可以
java -jar comm-sample-mp-generator-1.0.0.jar > excute.log
还需要有一个Java的环境变量存在