mybais-plus整合springboot自动代码生成。
mybais-plus整合springboot,自动代码生成。官方:https://mp.baomidou.com/guide/generator.html
官方演示效果图:
第一步:导包:mybatis-plus-generator包和freemarker包,本次案例使用freemarker模板。
<dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.29</version> </dependency> </dependencies>
第二步:代码生成类:
public class generate { /** * <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.toString()); if (scanner.hasNext()) { String ipt = scanner.next(); if (StringUtils.isNotEmpty(ipt)) { return ipt; } } throw new MybatisPlusException("请输入正确的" + tip + "!"); } public static void main(String[] args) { // 代码生成器 AutoGenerator mpg = new AutoGenerator(); // 全局配置 GlobalConfig gc = new GlobalConfig(); String projectPath = System.getProperty("user.dir");
//在哪一个路径下生成代码 gc.setOutputDir(projectPath + "/bootstudy/src/main/java");
//创建人 gc.setAuthor("yang"); gc.setOpen(false); // gc.setSwagger2(true); 实体属性 Swagger2 注解 mpg.setGlobalConfig(gc); // 数据源配置 DataSourceConfig dsc = new DataSourceConfig();
//设置数据库信息 dsc.setUrl("jdbc:mysql://localhost:3306/boot?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai"); // dsc.setSchemaName("public"); dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("123456"); mpg.setDataSource(dsc); // 包配置 PackageConfig pc = new PackageConfig();
//设置模块名 pc.setModuleName(scanner("模块名")); pc.setParent("com.springboot.modules"); pc.setEntity("model"); mpg.setPackageInfo(pc); // 自定义配置 InjectionConfig cfg = new InjectionConfig() { @Override public void initMap() { // to do nothing } }; // 如果模板引擎是 freemarker String templatePath = "/templates/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 projectPath + "/bootstudy/src/main/resources/mapper/" + pc.getModuleName() + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; } }); /* cfg.setFileCreate(new IFileCreate() { @Override public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) { // 判断自定义文件夹是否需要创建 checkDir("调用默认方法创建的目录"); return false; } }); */ cfg.setFileOutConfigList(focList); mpg.setCfg(cfg); // 配置模板 TemplateConfig templateConfig = new TemplateConfig(); // 配置自定义输出模板 //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别 // templateConfig.setEntity("templates/entity2.java"); // templateConfig.setService(); // templateConfig.setController(); templateConfig.setXml(null); mpg.setTemplate(templateConfig); // 策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); // strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!"); strategy.setEntityLombokModel(true); strategy.setRestControllerStyle(true); // 公共父类 // strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!"); // 写于父类中的公共字段 strategy.setSuperEntityColumns("id"); strategy.setInclude(scanner("表名,多个英文逗号分割").split(",")); strategy.setControllerMappingHyphenStyle(true); strategy.setTablePrefix(pc.getModuleName() + "_"); mpg.setStrategy(strategy); mpg.setTemplateEngine(new FreemarkerTemplateEngine()); mpg.execute(); } }
主要注意点就是这标红的几点了:设置数据库时我没有加上这个时报错&serverTimezone=Asia/Shanghai,设置mysql驱动名时,不加上cj会报过时警告,但不影响
更多属性的设置可以参考官方的:https://mp.baomidou.com/config/generator-config.html#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE
第三步,配置freemarker,也可以配置其他模板,以下是参考模板,对应自己的项目生成的模块可能会有一些错误。
controller.java.ftl
package ${package.Controller}; import cn.hutool.core.convert.Convert; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Arrays; import java.util.Map; import java.util.List; import ${package.Entity}.${entity}; import ${package.Service}.${table.serviceName}; /** * <p> * ${table.comment!} 前端控制器 * </p> * @author ${author} * @since ${date} */ @RestController @RequestMapping("/${package.ModuleName}/${entity?uncap_first}") @Slf4j <#if kotlin> class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if> <#else> <#if superControllerClass??> public class ${table.controllerName} extends ${superControllerClass} { <#else> public class ${table.controllerName} { </#if> @Autowired private I${entity}Service ${entity?uncap_first}Service; /** * 分页列表查询 * @param allParam * @return */ @ApiOperation(value="${entity}-分页查询") @PostMapping(value = "/list") public ResponseData queryPageList(@RequestBody Map allParam) { PageHelper.startPage(Convert.toInt(allParam.get("page")), Convert.toInt(allParam.get("limit"))); // 分页参考:默认生成使用单表查询分页,实际业务场景大部分是多表关联查询,需在mapper.xml写关联查询 List<${entity}> pageList = ${entity?uncap_first}Service.list(); PageInfo pageInfo = new PageInfo(pageList); return ResponseData.okData(pageInfo.getList(), pageInfo.getTotal()); } /** * 添加 * @param ${entity?uncap_first} * @return */ @ApiOperation(value="${entity}-添加") @PostMapping(value = "/add") public ResponseData add(@RequestBody ${entity} ${entity?uncap_first}) { ResponseData responseData = new ResponseData(); ${entity?uncap_first}Service.save(${entity?uncap_first}); return ResponseData.ok("添加成功!"); } /** * 编辑 * @param ${entity?uncap_first} * @return */ @ApiOperation(value="${entity}-编辑") @PostMapping(value = "/edit") public ResponseData edit(@RequestBody ${entity} ${entity?uncap_first}) { ResponseData responseData = new ResponseData(); ${entity} ${entity?uncap_first}Entity = ${entity?uncap_first}Service.getById(${entity?uncap_first}.getId()); if(${entity?uncap_first}Entity==null) { responseData = ResponseData.error("未找到对应实体"); }else { boolean ok = ${entity?uncap_first}Service.updateById(${entity?uncap_first}); if(ok) { responseData = ResponseData.ok("编辑成功"); } } return responseData; } /** * 通过id删除 * @param id * @return */ @ApiOperation(value="${entity}-通过id删除") @PostMapping(value = "/delete") public ResponseData delete(@RequestParam(name="id",required=true) String id) { ResponseData responseData = new ResponseData(); ${entity} ${entity?uncap_first} = ${entity?uncap_first}Service.getById(id); if(${entity?uncap_first}==null) { responseData = ResponseData.error("未找到对应实体"); }else { boolean ok = ${entity?uncap_first}Service.removeById(id); if(ok) { responseData = ResponseData.ok("删除成功!"); } } return responseData; } /** * 批量删除 * @param ids * @return */ @ApiOperation(value="${entity}-批量删除") @PostMapping(value = "/deleteBatch") public ResponseData deleteBatch(@RequestParam(name="ids",required=true) String ids) { ResponseData responseData = new ResponseData(); if(ids==null || "".equals(ids.trim())) { responseData = ResponseData.error("参数不识别!"); }else { this.${entity?uncap_first}Service.removeByIds(Arrays.asList(ids.split(","))); responseData = ResponseData.ok("删除成功!"); } return responseData; } /** * 通过id查询 * @param id * @return */ @ApiOperation(value="${entity}-id查询") @GetMapping(value = "/queryById") public ResponseData queryById(@RequestParam(name="id",required=true) String id) { ${entity} ${entity?uncap_first} = ${entity?uncap_first}Service.getById(id); if(${entity?uncap_first}==null) { return ResponseData.error("未找到对应实体"); } return ResponseData.okData("${entity?uncap_first}", ${entity?uncap_first}); } } </#if>
service.java.ftl
package ${package.Service}; import ${package.Entity}.${entity}; import ${superServiceClassPackage}; /** * <p> * ${table.comment!} 服务类 * </p> * * @author ${author} * @since ${date} */ <#if kotlin> interface ${table.serviceName} : ${superServiceClass}<${entity}> <#else> public interface ${table.serviceName} extends ${superServiceClass}<${entity}> { } </#if>
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; /** * <p> * ${table.comment!} 服务实现类 * </p> * * @author ${author} * @since ${date} */ @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>
mapper.java.ftl
package ${package.Mapper}; import ${package.Entity}.${entity}; import ${superMapperClassPackage}; import org.apache.ibatis.annotations.Mapper; /** * <p> * ${table.comment!} Mapper 接口 * </p> * * @author ${author} * @since ${date} */ <#if kotlin> @Mapper interface ${table.mapperName} : ${superMapperClass}<${entity}> <#else> @Mapper public interface ${table.mapperName} extends ${superMapperClass}<${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>
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> /** * <p> * ${table.comment!} * </p> * * @author ${author} * @since ${date} */ <#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> }
entity.kt.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> /** * <p> * ${table.comment} * </p> * * @author ${author} * @since ${date} */ <#if table.convert> @TableName("${table.name}") </#if> <#if swagger2> @ApiModel(value="${entity}对象", description="${table.comment!}") </#if> <#if superEntityClass??> class ${entity} : ${superEntityClass}<#if activeRecord><${entity}></#if> { <#elseif activeRecord> class ${entity} : Model<${entity}>() { <#else> class ${entity} : Serializable { </#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> <#if field.propertyType == "Integer"> var ${field.propertyName}: Int? = null <#else> var ${field.propertyName}: ${field.propertyType}? = null </#if> </#list> <#-- ---------- END 字段循环遍历 ----------> <#if entityColumnConstant> companion object { <#list table.fields as field> const val ${field.name.toUpperCase()} : String = "${field.name}" </#list> } </#if> <#if activeRecord> override fun pkVal(): Serializable? { <#if keyPropertyName??> return ${keyPropertyName} <#else> return null </#if> } </#if> override fun toString(): String { return "${entity}{" + <#list table.fields as field> <#if field_index==0> "${field.propertyName}=" + ${field.propertyName} + <#else> ", ${field.propertyName}=" + ${field.propertyName} + </#if> </#list> "}" } }
路径:
效果:
启动运行:
生成的相应的模块:
controller层里面的简单的增删改查
controller