目录
很早以前都是用原生的mybatis,在mapper.xml中写各种sql,后来用了tk-mybatis,简化了CRUD操作让开发变得更加高效。mybatis-plus之前没用过,不过最近比较火,准备用下看看和tkmybatis比怎么样。
mybatis-plus的官网是:https://baomidou.com ,里面有对配置的详细描述,包括对mybatis-plus generator的配置,好了废话不多说,让我们开始今天的内容吧。
1、引入mybatis-plus依赖
在random的pom.xml文件中引入mybatis-plus的依赖,包括mybatis-plus-boot-starter、mybatis-plus-generator以及freemarker模板引擎,当然还需要mysql、druid,lombok和swagger是generator所需要的。
请注意:引入 MyBatis-Plus
之后请不要再次引入 MyBatis
以及 MyBatis-Spring
,以避免因版本差异导致的问题。
算了我还是把完整的pom放在下面吧:(ps:网上找资料时,有的文章jar包不全还得自己去找,烦)
random的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>top.plgxs</groupId>
<artifactId>random</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>random</name>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modules>
<module>random-admin</module>
<module>random-wx</module>
<module>random-common</module>
<module>random-mbg</module>
</modules>
<properties>
<java.version>1.8</java.version>
<pagehelper-starter.version>1.3.0</pagehelper-starter.version>
<pagehelper.version>5.2.0</pagehelper.version>
<mybatis-plus.version>3.4.0</mybatis-plus.version>
<freemarker.version>2.3.30</freemarker.version>
<mysql-connector.version>8.0.22</mysql-connector.version>
<druid.version>1.1.23</druid.version>
<hutool.version>5.4.0</hutool.version>
<swagger2.version>2.9.2</swagger2.version>
<swagger-models.version>1.6.0</swagger-models.version>
<swagger-annotations.version>1.6.0</swagger-annotations.version>
<logstash-logback.version>5.3</logstash-logback.version>
<jackon-databind.version>2.11.0</jackon-databind.version>
<fastjson.version>1.2.73</fastjson.version>
<spring-data-commons.version>2.3.0.RELEASE</spring-data-commons.version>
<jjwt.version>0.9.0</jjwt.version>
<aliyun-oss.version>2.5.0</aliyun-oss.version>
<junit.version>5.7.0</junit.version>
<lombok.version>1.16.20</lombok.version>
<commons-lang3.version>3.11</commons-lang3.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- pagehelper-springboot -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper-starter.version}</version>
</dependency>
<!-- pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${pagehelper.version}</version>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- mybatis-plus generator -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- freemarker-模板引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
<!--Mysql数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>
<!--集成druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!--Hutool Java工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!--Swagger-UI API文档生产工具-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger2.version}</version>
</dependency>
<!--解决Swagger 2.9.2版本NumberFormatException-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>${swagger-models.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations.version}</version>
</dependency>
<!--集成logstash-->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>${logstash-logback.version}</version>
</dependency>
<!-- jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackon-databind.version}</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--SpringData工具包-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>${spring-data-commons.version}</version>
</dependency>
<!--JWT(Json Web Token)登录支持-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!-- 阿里云OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun-oss.version}</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- 热更新 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!-- commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
random-common的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>random</artifactId>
<groupId>top.plgxs</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>random-common</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
</project>
random-mbg的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>random</artifactId>
<groupId>top.plgxs</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>random-mbg</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>top.plgxs</groupId>
<artifactId>random-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
random-admin的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>random</artifactId>
<groupId>top.plgxs</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>random-admin</artifactId>
<packaging>jar</packaging>
<name>random-admin</name>
<dependencies>
<dependency>
<groupId>top.plgxs</groupId>
<artifactId>random-mbg</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin><!--编译跳过测试文件检查的生命周期-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
2、mybatis-plus配置
在random-admin模块的application.yml中添加mybatis-plus的配置,
server:
servlet:
context-path: /random
session:
timeout: 30m
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/random?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: random
password: random
druid:
initial-size: 5 #连接池初始化大小
min-idle: 10 #最小空闲连接数
max-active: 20 #最大连接数
web-stat-filter:
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" #不统计这些请求数据
stat-view-servlet: #访问监控网页的登录用户名和密码
login-username: druid
login-password: druid
#mybatis
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
#实体扫描,多个package用逗号或者分号分隔
#typeAliasesPackage: top.plgxs.entity
global-config:
db-config:
#主键类型
#AUTO 数据库ID自增
#INPUT 用户输入ID
#ID_WORKER 全局唯一ID,Long类型的主键
#ID_WORKER_STR 字符串全局唯一ID
#UUID 全局唯一ID,UUID类型的主键
#NONE 该类型为未设置主键类型
id-type: ID_WORKER_STR
#逻辑删除配置
logic-delete-value: 1 #逻辑已删除值(默认为 1)
logic-not-delete-value: 0 #逻辑未删除值(默认为 0)
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
call-setters-on-nulls: true
# 日志
logging:
level:
root: warn
top.plgxs.mbg.mapper: trace
pattern:
console: '%p%m%n'
3、配置mybatis-plus分页插件
在random-admin下新建MybatisPlusConfig类,配置分页插件:
(ps:注意PaginationInterceptor的jar包路径,别引错了;另外这个文件之前放在mbg模块下但分页不好使,所以放在admin模块下了,应该是mbg没有引spring web依赖的问题)
package top.plgxs.admin.config;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <p>mybatis-plus配置</p>
* @author Stranger。
* @since 2020-12-22
*/
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件
*
* @return PaginationInterceptor
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
/**
* 乐观锁插件,秒杀业务使用
*
* @return
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
4、配置mybatis-plus generator
相关的配置文件包括MybatisPlusGenerator和多个freemarker模板文件,在MybatisPlusGenerator中执行main方法就可以生成Controller、Service、Impl、mapper和xml。
其中模板文件是根据我自己的项目进行配置的,controller.java.ftl中包含我自定义的通用返回对象,如果你不是用我的项目,请稍微改一下(包括:包名、通用返回对象等)。
MybatisPlusGenerator.java的内容如下:
package top.plgxs.mbg;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.HashMap;
import java.util.Map;
/**
* mybatis-plus generator自动生成代码
* @author Stranger。
* @date 2020/12/22
*/
public class MyBatisPlusGenerator {
/**
* 数据库类型
*/
private DbType dbType = DbType.MYSQL;
/**
* 数据库连接信息
*/
private String dbUrl = "jdbc:mysql://localhost:3306/random?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2b8";
private String driver = "com.mysql.cj.jdbc.Driver";
private String userName = "random";
private String password = "random";
/**
* 指定生成的表名。如果想生成整个库的,这里设为null即可
*/
/*private String[] tableNames = new String[]{
"tb_resource",
"t_order"
};*/
private String[] tableNames = new String[]{
};
/**
* 输出路径(当前为项目根目录下)
* 例如:F:\ideaProject\random
*/
private String outputDir = System.getProperty("user.dir");
/**
* 公共包名
*/
private String packageName = "top.plgxs";
/**
* 公共包名路径
*/
private String packagePath = "/top/plgxs";
/**
* 实体分类存放,如以sys_开头的表统一放在sys包下
*/
private String commonPackageName = "sys";
/**
* controller基础类
*/
private String superControllerClass = packageName + ".common.BaseController";
/**
* entity基础类
*/
private String superEntityClass = packageName + ".common.BaseEntity";
/**
* mbg模块包名
*/
private String mbgPackageName = packageName + ".mbg";
/**
* mbg模块路径
*/
private String mbgModulePath = "/random-mbg";
/**
* mbg模块的包名路径
*/
private String mbgModulePackagePath = packagePath + "/mbg";
/**
* admin模块包名
*/
private String adminPackageName = packageName + ".admin";
/**
* admin模块路径
*/
private String adminModulePath = "/random-admin";
/**
* admin模块的包名路径
*/
private String adminModulePackagePath = packagePath + "/admin";
/**
* 作者名
*/
private String author = "Stranger";
/**
* 逻辑删除属性名称
* 0-正常,1-逻辑删除
*/
private String deleteFieldName = "status";
/**
* 生成代码的调用方法
*/
public void generateCode() {
generateByTables(tableNames);
}
/**
* 根据表自动生成
*
* @param tableNames 表名
*/
private void generateByTables(String... tableNames) {
//配置数据源
DataSourceConfig dataSourceConfig = getDataSourceConfig();
// 策略配置
StrategyConfig strategyConfig = getStrategyConfig(tableNames);
//全局变量配置
GlobalConfig globalConfig = getGlobalConfig();
//包名配置
PackageConfig packageConfig = getPackageConfig();
//自主配置
InjectionConfig injectionConfig = getInjectionConfig();
//自动生成
atuoGenerator(dataSourceConfig, strategyConfig, globalConfig, packageConfig,injectionConfig);
}
/**
* 集成
*
* @param dataSourceConfig 配置数据源
* @param strategyConfig 策略配置
* @param config 全局变量配置
* @param packageConfig 包名配置
*/
private void atuoGenerator(DataSourceConfig dataSourceConfig, StrategyConfig strategyConfig,
GlobalConfig config, PackageConfig packageConfig, InjectionConfig injectionConfig) {
TemplateConfig tc = new TemplateConfig();
// 配置自定义输出模板
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
String templatePathController = "/templates/controller.java";
String templatePathService = "/templates/service.java";
String templatePathServiceImpl = "/templates/serviceImpl.java";
String templatePathEntity = "/templates/entity.java";
String templatePathMapper = "/templates/mapper.java";
String templatePathMapperXML = "/templates/mapper.xml";
tc.setController(templatePathController);
tc.setService(templatePathService);
tc.setServiceImpl(templatePathServiceImpl);
tc.setEntity(templatePathEntity);
tc.setMapper(templatePathMapper);
tc.setXml(templatePathMapperXML);
new AutoGenerator()
.setGlobalConfig(config)
.setDataSource(dataSourceConfig)
.setStrategy(strategyConfig)
.setPackageInfo(packageConfig)
.setTemplateEngine(new FreemarkerTemplateEngine())
//.setTemplateEngine(new VelocityTemplateEngine()).setTemplate(tc)
.setCfg(injectionConfig)
.execute();
}
/**
* 设置包名
*
* @return PackageConfig 包名配置
*/
private PackageConfig getPackageConfig() {
PackageConfig pc = new PackageConfig();
pc.setModuleName(null); //模块名
pc.setParent(null); //具体包,类似:top.plgxs
//entity mapper层统一放在mbg模块下
HashMap<String, String> pathMap = CollectionUtils.newHashMapWithExpectedSize(6);
pathMap.put(ConstVal.ENTITY_PATH, outputDir + mbgModulePath + "/src/main/java" +
mbgModulePackagePath + "/entity/" + commonPackageName);
pathMap.put(ConstVal.MAPPER_PATH, outputDir + mbgModulePath + "/src/main/java" +
mbgModulePackagePath + "/mapper/" + commonPackageName);
pathMap.put(ConstVal.XML_PATH, outputDir + mbgModulePath + "/src/main/resources/mapper/"+commonPackageName);
//controller service impl放在其他模块
pathMap.put(ConstVal.CONTROLLER_PATH, outputDir + adminModulePath + "/src/main/java" +
adminModulePackagePath + "/controller/" + commonPackageName);
pathMap.put(ConstVal.SERVICE_PATH, outputDir + adminModulePath + "/src/main/java" +
adminModulePackagePath + "/service/" + commonPackageName);
pathMap.put(ConstVal.SERVICE_IMPL_PATH, outputDir + adminModulePath + "/src/main/java" +
adminModulePackagePath + "/service/impl/" + commonPackageName);
pc.setPathInfo(pathMap);
return pc;
}
/**
* 全局配置
*
* @return GlobalConfig
*/
private GlobalConfig getGlobalConfig() {
GlobalConfig globalConfig = new GlobalConfig();
globalConfig
// 开启swagger
.setSwagger2(true)
.setActiveRecord(true)
.setBaseColumnList(true)
.setBaseResultMap(true)
//作者
.setAuthor(author)
//设置输出路径
.setOutputDir(outputDir)
//是否覆盖已有文件
.setFileOverride(true);
// 自定义命名方式
globalConfig.setEntityName("%s");
globalConfig.setMapperName("%sMapper");
globalConfig.setXmlName("%sMapper");
globalConfig.setServiceName("%sService");
globalConfig.setServiceImplName("%sServiceImpl");
globalConfig.setControllerName("%sController");
return globalConfig;
}
/**
* 策略配置
*
* @param tableNames 表名
* @return StrategyConfig
*/
private StrategyConfig getStrategyConfig(String... tableNames) {
StrategyConfig strategy = new StrategyConfig();
//从数据库表到文件的命名策略
strategy.setNaming(NamingStrategy.underline_to_camel)
// 表前缀
.setTablePrefix(new String[] {"t_","T_"})
// rest风格
.setRestControllerStyle(false)
// 字段注解
.setEntityTableFieldAnnotationEnable(true)
// 使用lombok
.setEntityLombokModel(true)
// 需要生成的的表名,多个表名传数组
.setInclude(tableNames)
// 生成序列号
.setEntitySerialVersionUID(true)
// 逻辑删除属性名称
.setLogicDeleteFieldName(deleteFieldName)
// 驼峰转连字符,用于controller的RequestMapping。例如: 表名sys_user,为true则转为sys-user,
.setControllerMappingHyphenStyle(false);
// 自定义实体父类
// strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
// 自定义实体,公共字段
// strategy.setSuperEntityColumns(new String[] { "create_time", "create_username" });
// 自定义 controller 父类
// strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
// 还有自定义service/mapper等
return strategy;
}
/**
* 配置数据源
*
* @return 数据源配置 DataSourceConfig
*/
private DataSourceConfig getDataSourceConfig() {
return new DataSourceConfig().setDbType(dbType)
.setUrl(dbUrl)
.setUsername(userName)
.setPassword(password)
.setDriverName(driver);
}
// 自定义配置
private InjectionConfig getInjectionConfig(){
InjectionConfig cfg = new InjectionConfig() {
//自定义属性注入:abc
//在.ftl(或者是.vm)模板中,通过${cfg.abc}获取属性
@Override
public void initMap() {
Map<String, Object> map = new HashMap<>();
// 实体类的package
map.put("customEntityPackage", mbgPackageName
+ ".entity." + commonPackageName);
// mapper的package
map.put("customMapperPackage", mbgPackageName
+ ".mapper." + commonPackageName);
// controller的package
map.put("customControllerPackage", adminPackageName
+ ".controller." + commonPackageName);
// service的package
map.put("customServicePackage", adminPackageName
+ ".service." + commonPackageName);
// serviceimpl的package
map.put("customServiceImplPackage", adminPackageName
+ ".service.impl." + commonPackageName);
this.setMap(map);
}
};
return cfg;
}
// 执行main方法自动生成代码
public static void main(String[] args) {
new MyBatisPlusGenerator().generateCode();
}
}
controller.java.ftl中添加了新增、修改、删除与分页查询,内容如下:
(ps:所有ftl文件中的${cfg.xxx}都是在MybatisPlusGenerator中的自定义配置部分进行设置的)
package ${cfg.customControllerPackage};
import javax.annotation.Resource;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import ${cfg.customServicePackage}.${table.serviceName};
import top.plgxs.common.api.ResultInfo;
import ${cfg.customEntityPackage}.${entity};
<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;
</#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
/**
* <p>
* ${table.comment!} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
* @version 1.0
*/
<#if restControllerStyle>
@RestController
<#else>
@Controller
</#if>
@RequestMapping("<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#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>
@Resource
private ${table.serviceName} ${table.serviceName ? uncap_first};
/**
* 分页查询列表
* @param query 查询条件
* @param pageNo 第几页
* @param pageSize 每页几条
* @return
* @author ${author}
* @since ${date}
*/
@GetMapping("/list")
@ResponseBody
public ResultInfo<IPage<${entity}>> queryPageList(@RequestParam("query") String query, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize){
QueryWrapper<${entity}> queryWrapper = new QueryWrapper<>();
//TODO 查询条件
Page<${entity}> page = new Page<>(pageNo, pageSize);
IPage<${entity}> pageList = ${table.serviceName ? uncap_first}.page(page, queryWrapper);
return ResultInfo.success(pageList);
}
/**
* 插入一条数据
* @param ${entity?uncap_first}
* @return top.plgxs.common.api.ResultInfo<java.lang.Object>
* @author ${author}
* @since ${date}
*/
@PostMapping("/insert")
@ResponseBody
public ResultInfo<Object> insert(@RequestBody ${entity} ${entity?uncap_first}){
boolean result = ${table.serviceName ? uncap_first}.save(${entity?uncap_first});
if(result){
return ResultInfo.success();
}else{
return ResultInfo.failed();
}
}
/**
* 更新一条数据
* @param ${entity?uncap_first}
* @return top.plgxs.common.api.ResultInfo<java.lang.Object>
* @author ${author}
* @since ${date}
*/
@PostMapping("/update")
@ResponseBody
public ResultInfo<Object> update(@RequestBody ${entity} ${entity?uncap_first}){
if(${entity?uncap_first} == null || StringUtils.isBlank(${entity?uncap_first}.getId())){
return ResultInfo.validateFailed();
}
boolean result = ${table.serviceName ? uncap_first}.updateById(${entity?uncap_first});
if(result){
return ResultInfo.success();
}else{
return ResultInfo.failed();
}
}
/**
* 逻辑删除一条数据
* @param id 主键
* @return top.plgxs.common.api.ResultInfo<java.lang.Object>
* @author ${author}
* @since ${date}
*/
@GetMapping("/delete/{id}")
@ResponseBody
public ResultInfo<Object> delete(@PathVariable("id") String id){
if(StringUtils.isBlank(id)){
return ResultInfo.validateFailed();
}
boolean result = ${table.serviceName ? uncap_first}.removeById(id);
if(result){
return ResultInfo.success();
}else{
return ResultInfo.failed();
}
}
}
</#if>
entity.java.ftl中集成了lombok与swagger,内容如下:
package ${cfg.customEntityPackage};
<#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;
<#if chainModel>
import lombok.experimental.Accessors;
</#if>
</#if>
/**
* <p>
* ${table.comment!}
* </p>
*
* @author ${author}
* @since ${date}
* @version 1.0
*/
<#if entityLombokModel>
@Data
<#if superEntityClass??>
@EqualsAndHashCode(callSuper = true)
<#else>
@EqualsAndHashCode(callSuper = false)
</#if>
<#if chainModel>
@Accessors(chain = true)
</#if>
</#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.annotationColumnName}", type = IdType.AUTO)
<#elseif idType??>
@TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
<#elseif field.convert>
@TableId("${field.annotationColumnName}")
</#if>
<#-- 普通字段 -->
<#elseif field.fill??>
<#-- ----- 存在字段填充设置 ----->
<#if field.convert>
@TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill})
<#else>
@TableField(fill = FieldFill.${field.fill})
</#if>
<#elseif field.convert>
@TableField("${field.annotationColumnName}")
</#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 chainModel>
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 chainModel>
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 ${cfg.customMapperPackage};
import ${cfg.customEntityPackage}.${entity};
import ${superMapperClassPackage};
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* <p>
* ${table.comment!} Mapper 接口
* </p>
*
* @author ${author}
* @since ${date}
* @version 1.0
*/
<#if kotlin>
interface ${table.mapperName} : ${superMapperClass}<${entity}>
<#else>
@Repository("${table.mapperName?uncap_first}")
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
/**
* 分页数据查询
* @param ${entity?uncap_first}
* @return
* @author ${author}
* @date ${date}
*/
List<${entity}> select${entity}List(${entity} ${entity?uncap_first});
}
</#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="${cfg.customMapperPackage}.${table.mapperName}">
<#if enableCache>
<!-- 开启二级缓存 -->
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
</#if>
<#if baseResultMap>
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${cfg.customEntityPackage}.${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>
<select id="select${entity}List" parameterType="${cfg.customEntityPackage}.${entity}" resultType="${cfg.customEntityPackage}.${entity}">
select <include refid="Base_Column_List"/>
from ${table.name} t
where 1 = 1
<#list table.fields as field>
<#if field.type?contains('char')>
<if test="${field.propertyName} != null and ${field.propertyName} != ''">
and t.${field.name} = ${r'#{'}${field.propertyName}}
</if>
<#elseif field.type?contains('text')>
<if test="${field.propertyName} != null and ${field.propertyName} != ''">
and t.${field.name} like concat('%', ${r'#{'}${field.propertyName}}, '%')
</if>
<#else>
<if test="${field.propertyName} != null">
and t.${field.name} = ${r'#{'}${field.propertyName}}
</if>
</#if>
</#list>
</select>
</mapper>
service.java.ftl内容如下:
package ${cfg.customServicePackage};
import ${cfg.customEntityPackage}.${entity};
import ${superServiceClassPackage};
import java.util.List;
/**
* <p>
* ${table.comment!} 服务类
* </p>
*
* @author ${author}
* @since ${date}
* @version 1.0
*/
<#if kotlin>
interface ${table.serviceName} : ${superServiceClass}<${entity}>
<#else>
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
/**
* 数据查询列表
* @return
* @author ${author}
* @date ${date}
*/
List<${entity}> get${entity}List();
}
</#if>
serviceImpl.java.ftl内容如下:
package ${cfg.customServiceImplPackage};
import ${cfg.customEntityPackage}.${entity};
import ${cfg.customMapperPackage}.${table.mapperName};
import ${cfg.customServicePackage}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* <p>
* ${table.comment!} 服务实现类
* </p>
*
* @author ${author}
* @since ${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} {
@Resource
private ${table.mapperName} ${table.mapperName?uncap_first};
@Override
public List<${entity}> get${entity}List() {
return ${table.mapperName?uncap_first}.select${entity}List(null);
}
}
</#if>
5、配置通用返回对象(可省略)
如果你在controller.java.ftl中将ResultInfo相关的东西删掉,那么这部分就可以不用配置了,否则执行generator后生成的代码会报错。
在random-common中新建通用返回对象ResultInfo和常用返回代码ResultCode。
ResultInfo.java
package top.plgxs.common.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* <p>通用返回对象</p>
*
* @author Stranger。
* @since 2020/12/23 15:13
* @version 1.0
*/
@Data
@ApiModel(value="通用返回对象", description="通用返回对象")
public class ResultInfo<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 成功标志
*/
@ApiModelProperty(value = "成功标志")
private boolean success = true;
/**
* 返回处理消息
*/
@ApiModelProperty(value = "返回处理消息")
private String message = "操作成功!";
/**
* 返回代码
*/
@ApiModelProperty(value = "返回代码")
private Integer code = 0;
/**
* 返回数据对象 data
*/
@ApiModelProperty(value = "返回数据对象")
private T data;
/**
* 时间戳
*/
@ApiModelProperty(value = "时间戳")
private long timestamp = System.currentTimeMillis();
public ResultInfo() {
}
/**
* 成功返回结果
* @author Stranger。
* @since 2020/12/23 16:05
*/
public static <T> ResultInfo<T> success(){
return success(ResultCode.SUCCESS.getMessage(),null);
}
/**
* 成功返回结果
* @param data 返回的数据
* @author Stranger。
* @since 2020/12/23 0023 16:06
*/
public static<T> ResultInfo<T> success(T data) {
return success(ResultCode.SUCCESS.getMessage(),data);
}
/**
* 成功返回结果
* @param msg 提示信息
* @param data 返回的数据
* @author Stranger。
* @since 2020/12/23 16:09
*/
public static<T> ResultInfo<T> success(String msg, T data) {
ResultInfo<T> r = new ResultInfo<T>();
r.setSuccess(true);
r.setCode(ResultCode.SUCCESS.getCode());
r.setMessage(msg);
r.setData(data);
return r;
}
/**
* 失败返回结果
* @author Stranger。
* @since 2020/12/23 16:10
*/
public static <T> ResultInfo<T> failed() {
return failed(ResultCode.FAILED.getMessage());
}
/**
* 失败返回结果
* @param message 错误信息
* @author Stranger。
* @since 2020/12/23 16:10
*/
public static<T> ResultInfo<T> failed(String message) {
return failed(ResultCode.FAILED.getCode(), message);
}
/**
* 失败返回结果
* @param code 错误码
* @param message 错误信息
* @author Stranger。
* @since 2020/12/23 16:10
*/
public static<T> ResultInfo<T> failed(int code, String message) {
ResultInfo<T> r = new ResultInfo<>();
r.setCode(code);
r.setMessage(message);
r.setSuccess(false);
return r;
}
/**
* 参数验证失败返回结果
* @author Stranger。
* @since 2020/12/23 16:12
*/
public static<T> ResultInfo<T> validateFailed() {
return validateFailed(ResultCode.VALIDATE_FAILED.getMessage());
}
/**
* 参数验证失败返回结果
* @param message 错误信息
* @author Stranger。
* @since 2020/12/23 16:12
*/
public static<T> ResultInfo<T> validateFailed(String message) {
return failed(ResultCode.VALIDATE_FAILED.getCode(),message);
}
/**
* 未登录返回结果
* @author Stranger。
* @since 2020/12/23 16:12
*/
public static <T> ResultInfo<T> unauthorized() {
return failed(ResultCode.UNAUTHORIZED.getCode(),ResultCode.UNAUTHORIZED.getMessage());
}
/**
* 未授权返回结果
* @author Stranger。
* @since 2020/12/23 16:12
*/
public static <T> ResultInfo<T> forbidden() {
return failed(ResultCode.FORBIDDEN.getCode(),ResultCode.FORBIDDEN.getMessage());
}
}
ResultCode.java
package top.plgxs.common.api;
/**
* <p>常用API操作码</p>
*
* @author Stranger。
* @since 2020/12/23 15:30
* @version 1.0
*/
public enum ResultCode {
SUCCESS(200, "操作成功"),
FAILED(500, "操作失败"),
VALIDATE_FAILED(404, "参数检验失败"),
UNAUTHORIZED(401, "暂未登录或token已经过期"),
FORBIDDEN(403, "没有相关权限,请联系管理员");
private Integer code;
private String message;
ResultCode(Integer code, String message){
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
6、在启动器上配置扫描mapper
在random-admin的启动类上加mapper扫描注解,启动后可以用postman测试一下。
package top.plgxs.admin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@MapperScan("top.plgxs.mbg.mapper")
@EnableTransactionManagement
public class RandomAdminApplication {
public static void main(String[] args) {
SpringApplication.run(RandomAdminApplication.class, args);
}
}
7、展示下生成的项目结构
8、附赠用于generator的表结构
CREATE TABLE `t_sys_user` (
`id` varchar(32) NOT NULL COMMENT '主键uuid',
`username` varchar(50) DEFAULT NULL COMMENT '用户名',
`password` varchar(255) DEFAULT NULL COMMENT '密码md5',
`mobile` varchar(50) DEFAULT NULL COMMENT '手机号',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
`nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
`gender` int(1) DEFAULT '0' COMMENT '性别,0-保密,1-男,2-女',
`realname` varchar(50) DEFAULT NULL COMMENT '真实姓名',
`id_number` varchar(255) DEFAULT NULL COMMENT '身份证号',
`head_url` varchar(255) DEFAULT NULL COMMENT '头像url',
`register_time` datetime DEFAULT NULL COMMENT '注册时间',
`login_number` bigint(11) DEFAULT NULL COMMENT '登录次数',
`last_login_time` datetime DEFAULT NULL COMMENT '最后登录时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`status` varchar(1) DEFAULT '0' COMMENT '状态,1-冻结,0-正常',
`mobile_verification_code` varchar(10) DEFAULT NULL COMMENT '手机验证码',
`email_verification_code` varchar(10) DEFAULT NULL COMMENT '邮箱验证码',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户';