SpringBoot结合MyBatis Plus 自动生成代码
本来这一章要介绍Redis+AOP优化权限,可是发现还是需要先介绍一些MyBatis Plus自动生成代码
MyBatis Plus简介
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
MyBatis Plus特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
MyBatis Plus支持数据库
任何能使用 mybatis 进行 crud, 并且支持标准 sql 的数据库
框架结构
MyBatis Plus代码生成器
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
使用教程
添加 代码生成器 依赖
<!--lombok依赖--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--集成druid连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <!--Mysql数据库驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.10</version> </dependency> <!--MyBatis Plus 依赖--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.2</version> </dependency> <!--MyBatis Plus 代码生成器--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.3.2</version> </dependency> <!--Hutool Java工具包--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.5.7</version> </dependency> <!--Velocity模板引擎--> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.2</version> </dependency> <!--Swagger-UI API文档生产工具--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency>
添加 模板引擎 依赖
MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl,用户可以选择自己熟悉的模板引擎,如果都不满足您的要求,可以采用自定义模板引擎。本文使用默认依赖
<dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.2</version> </dependency>
编写配置
MyBatis-Plus 的代码生成器提供了大量的自定义参数供用户选择,能够满足绝大部分人的使用需求。
配置GlobalConfig
全局策略 globalConfig 配置
outputDir
- 生成文件的输出目录
- 默认值:D 盘根目录
fileOverride
- 是否覆盖已有文件
- 默认值:false
open
- 是否打开输出目录
- 默认值:true
enableCache
- 是否在xml中添加二级缓存配置
- 默认值:false
author
- 开发人员
- 默认值:null
kotlin
- 开启 Kotlin 模式
- 默认值:false
swagger2
- 开启 swagger2 模式
- 默认值:false
activeRecord
- 开启 ActiveRecord 模式
- 默认值:false
baseResultMap
- 开启 BaseResultMap
- 默认值:false
baseColumnList
- 开启 baseColumnList
- 默认值:false
dateType
- 时间类型对应策略
- 默认值:TIME_PACK
注意事项:
如下配置 %s 为占位符
entityName
实体命名方式
默认值:null 例如:%sEntity 生成 UserEntity
mapperName
mapper 命名方式
默认值:null 例如:%sDao 生成 UserDao
xmlName
Mapper xml 命名方式
默认值:null 例如:%sDao 生成 UserDao.xml
serviceName
service 命名方式
默认值:null 例如:%sBusiness 生成 UserBusiness
serviceImplName
service impl 命名方式
默认值:null 例如:%sBusinessImpl 生成 UserBusinessImpl
controllerName
controller 命名方式
默认值:null 例如:%sAction 生成 UserAction
————————————————idType
- 指定生成的主键的ID类型
- 默认值:null
/** * 全局配置 * @param projectPath * @return */ public static GlobalConfig initGlobal(String projectPath){ GlobalConfig gc = new GlobalConfig(); gc.setOutputDir(projectPath + "/src/main/java"); gc.setAuthor("zbb"); gc.setOpen(false); gc.setSwagger2(true); gc.setBaseResultMap(true); gc.setFileOverride(true); gc.setDateType(DateType.ONLY_DATE); gc.setEntityName("%s"); gc.setMapperName("%sMapper"); gc.setXmlName("%sMapper"); gc.setServiceName("%sService"); gc.setServiceImplName("%sServiceImpl"); gc.setControllerName("%sController"); return gc; }
配置 DataSourceConfig
dbQuery
数据库信息查询类
默认由 dbType 类型决定选择对应数据库内置实现实现 IDbQuery 接口自定义数据库查询 SQL 语句 定制化返回自己需要的内容
dbType
数据库类型
该类内置了常用的数据库类型【必须】
schemaName
数据库 schema name
例如 PostgreSQL 可指定为 public typeConvert
类型转换
默认由 dbType 类型决定选择对应数据库内置实现 实现 ITypeConvert 接口自定义数据库 字段类型 转换为自己需要的 java 类型,内置转换类型无法满足可实现 IColumnType 接口自定义
url
驱动连接的URL driverName
驱动名称 username
数据库连接用户名 password
数据库连接密码
/** * * 配置 DataSourceConfig * @return */ public static DataSourceConfig initDataSource(){ Props props = new Props("application.properties"); DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setUrl(props.getStr("dataSource.url")); dataSourceConfig.setDriverName(props.getStr("dataSource.driverName")); dataSourceConfig.setUsername(props.getStr("dataSource.username")); dataSourceConfig.setPassword(props.getStr("dataSource.password")); return dataSourceConfig; }
包配置包名配置
parent
父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
moduleName
父包模块名
entity
Entity包名
service
Service包名
serviceImpl
Service Impl包名
mapper
Mapper包名
xml
Mapper XML包名
controller
Controller包名
pathInfo
路径配置信息
/** * 包配置 * @param packname * @return */ public static PackageConfig initPackage(String packname){ Props props = new Props("application.properties"); PackageConfig packageConfig = new PackageConfig(); packageConfig.setModuleName(packname); packageConfig.setParent(props.getStr("package.base")); packageConfig.setEntity("model"); return packageConfig; }
模板配置 TemplateConfig
entity
Java 实体类模板
entityKt
Kotin 实体类模板
service
Service 类模板
serviceImpl
Service impl 实现类模板
mapper
mapper 模板
xml
mapper xml 模板
controller
controller 控制器模板
/** * 模板配置 * @return */ public static TemplateConfig initTemplate() { TemplateConfig templateConfig = new TemplateConfig(); //可以对controller、service、entity模板进行配置 templateConfig.setXml(null); return templateConfig; }
自定义属性注入 InjectionConfig
map
自定义返回配置 Map 对象
该对象可以传递到模板引擎通过 cfg.xxx 引用
fileOutConfigList
自定义输出文件
配置 FileOutConfig 指定模板文件、输出文件达到自定义文件生成目的
fileCreate
自定义判断是否创建文件
实现 IFileCreate 接口
该配置用于判断某个类是否需要覆盖创建,当然你可以自己实现差异算法 merge 文件
initMap
注入自定义 Map 对象(注意需要setMap放进去)
/** * 自定义属性注入 */ public static InjectionConfig initInjection(String projectPath, String moduleName) { // 自定义配置 InjectionConfig injectionConfig = new InjectionConfig() { @Override public void initMap() { // 可用于自定义属性 } }; // 模板引擎是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 + "/src/main/resources/mapper/" + moduleName + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; } }); injectionConfig.setFileOutConfigList(focList); return injectionConfig; }
策略配置StrategyConfig
/** * 策略配置 */ public static StrategyConfig initStrategy(String[] tableNames) { StrategyConfig strategyConfig = new StrategyConfig(); strategyConfig.setNaming(NamingStrategy.underline_to_camel); strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel); strategyConfig.setEntityLombokModel(true); strategyConfig.setRestControllerStyle(true); //当表名中带*号时可以启用通配符模式 if (tableNames.length == 1 && tableNames[0].contains("*")) { String[] likeStr = tableNames[0].split("_"); String likePrefix = likeStr[0] + "_"; strategyConfig.setLikeTable(new LikeTable(likePrefix)); } else { strategyConfig.setInclude(tableNames); } return strategyConfig; }
代码生成器
public static void main(String[] args) { String projectPath = System.getProperty("user.dir"); String moduleName = scanner("模块名"); String[] tableNames = scanner("表名,多个英文逗号分割").split(","); // 代码生成器 AutoGenerator autoGenerator = new AutoGenerator(); autoGenerator.setGlobalConfig(initGlobal(projectPath)); autoGenerator.setDataSource(initDataSource()); autoGenerator.setPackageInfo(initPackage(moduleName)); autoGenerator.setCfg(initInjection(projectPath, moduleName)); autoGenerator.setTemplate(initTemplate()); autoGenerator.setStrategy(initStrategy(tableNames)); autoGenerator.setTemplateEngine(new VelocityTemplateEngine()); autoGenerator.execute(); }
读取控制台内容
/** * <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 (StrUtil.isNotEmpty(ipt)) { return ipt; } } throw new MybatisPlusException("请输入正确的" + tip + "!"); }
配置application.properties
dataSource.url=jdbc:mysql://db:3306/mymes?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai dataSource.driverName=com.mysql.jdbc.Driver dataSource.username=reader dataSource.password=123456 package.base=com.springboot.mymes_demo.modules
运行代码
注:
在输入表明的时候输入xx_*表示xx前缀的所有表 若输入全名,则生成对于的表