整合Mybatis-Plus和代码生成器
编辑早就想写这个记录,主要为了记录MP常用配置以及代码生成器,也常用但总不记得配置,做个记录吧,一直拖着好久了。
官方也有很全的说明文档和demo,自行查阅,这里也就是将官方文档再说一遍,在此基础上提取一些通用配置形成配置文件,方便其他项目使用而已。
温馨提示:MP和SpringBoot有对应的版本要求,自行查看,maven仓库也可以看到一些。
一、版本、配置说明
JDK:1.8
SpringBoot:2.3.2.RELEASE
Mybatis-Plus:3.3.2
Mybatis-Plus Generator:3.3.2
Velocity:2.2(模板引擎,代码生成器需要)
数据库:MySQL5.7
二、数据表设计
create_time/create_user/modify_user/modify_time/is_deleted
作为公共字段,几乎每张表都有,当然有的表也可以没有,这要看设计,但是is_deleted是逻辑删除字段代表着该条记录是否删除,必须每张表都有。
三、创建项目,引入相关依赖
创建一个普通SpringBoot项目,以下是完整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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>online.heycm</groupId>
<artifactId>mybatis-plus</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis-plus</name>
<description>Mybatis Plus Demo for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<!-- 自定义工具包:统一返回对象 -->
<dependency>
<groupId>online.heycm</groupId>
<artifactId>utils</artifactId>
<version>0.0.3</version>
</dependency>
<!-- MySql数据库连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.18</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>
<!-- 模板引擎 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
自定义工具包里主要有一些通用工具,以及统一返回对象,工具代码地址:https://github.com/heycm/demo/tree/master/utils
创建完成,项目结构如下图,习惯将配置文件重命名为yml
四、代码生成器
这里将生成器一些配置提取出来,放在配置文件。
1、创建配置文件,放资源文件夹下
# Mybatis Plus 代码生成器配置
# 生成模板输出路径
outPutDir=F:/github/demo/mybatis-plus/src/main/java
# 生成xml输出路径
xmlOutPutDir=F:/github/demo/mybatis-plus/src/main/resources/mapper
# 父包名
parentPackage=online.heycm.mybatisplus
# 作者
author=heycm
# 数据源
dataSource.driverName=com.mysql.cj.jdbc.Driver
dataSource.username=root
dataSource.password=root
dataSource.url=jdbc:mysql://localhost:3306/shiro?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
# 表前缀,以","分割
tablePrefix=
# 字段前缀,以","分割
fieldPrefix=
# 是否生成swagger2注解
isUseSwagger2=false
# 使用lombok
isLombokModel=true
# 需要生成的表,以","分割
tables=permission,role,role_permission,user,user_role
2、创建utils包,创建代码生成器
package online.heycm.mybatisplus.utils;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
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.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
public class CodeGenerator {
public static void main(String[] args) {
// 读取配置文件
ResourceBundle rb = ResourceBundle.getBundle("mp-generator");
// 实例一个代码生成器
AutoGenerator ag = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(rb.getString("outPutDir")); // 输出路径
gc.setFileOverride(true); // 同名覆盖
gc.setActiveRecord(true); // 开启 activeRecord 模式
gc.setEnableCache(false); // XML 二级缓存
gc.setBaseResultMap(true); // XML ResultMap
gc.setBaseColumnList(true); // XML columnList
gc.setAuthor(rb.getString("author")); // 作者
gc.setDateType(DateType.ONLY_DATE); // 时间类型对应策略
gc.setSwagger2("true".equals(rb.getString("isUseSwagger2"))); // 实体属性 Swagger2 注解
gc.setEntityName("%s"); // 实体命名方式,如 %sEntity 生成 UserEntity
gc.setControllerName("%sController"); // controller命名方式,如 %sAction 生成 UserAction
gc.setServiceName("%sService"); // service命名方式,如 %sBusiness 生成 UserBusiness
gc.setServiceImplName(gc.getServiceName() + "Impl"); // service impl命名方式,如 %sBusinessImpl 生成 UserBusinessImpl
gc.setMapperName("%sMapper"); // mapper命名方式,如 %sDao 生成 UserDao
// gc.setXmlName("%sMapper"); // Mapper xml命名方式,如 %sDao 生成 UserDao.xml
ag.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig ds = new DataSourceConfig();
ds.setDbType(DbType.MYSQL); // 数据库类型
ds.setTypeConvert(new MySqlTypeConvert()); // 类型转换
ds.setDriverName(rb.getString("dataSource.driverName"));
ds.setUsername(rb.getString("dataSource.username"));
ds.setPassword(rb.getString("dataSource.password"));
ds.setUrl(rb.getString("dataSource.url"));
ag.setDataSource(ds);
// 生成策略配置
StrategyConfig sc = new StrategyConfig();
sc.setTablePrefix(rb.getString("tablePrefix").split(",")); // 表前缀
sc.setNaming(NamingStrategy.underline_to_camel); // 表名生成策略 t_user_xxx UserXxx,驼峰命名
sc.setFieldPrefix(rb.getString("fieldPrefix").split(",")); // 字段前缀
sc.setEntityLombokModel("true".equals(rb.getString("isLombokModel"))); // 实体用 lombok
sc.setRestControllerStyle(true);//restful api
sc.setInclude(rb.getString("tables").split(",")); // 需要生成的表
/*
逻辑删除列和自动填充列,需要看需求来定,可以有也可以没有
如果有,还需要涉及数据表的设计
若不需要,注释掉即可
*/
sc.setLogicDeleteFieldName("is_deleted"); // 逻辑删除列
List<TableFill> tableFillList = new ArrayList<TableFill>();//自动填充列配置
tableFillList.add(new TableFill("is_deleted", FieldFill.INSERT)); // 插入时自动填充数据
tableFillList.add(new TableFill("create_user", FieldFill.INSERT)); // 插入时自动填充数据
tableFillList.add(new TableFill("create_time", FieldFill.INSERT)); // 插入时自动填充数据
tableFillList.add(new TableFill("modify_user", FieldFill.INSERT_UPDATE)); // 插入和更新时自动填充数据
tableFillList.add(new TableFill("modify_time", FieldFill.INSERT_UPDATE)); // 插入和更新时自动填充数据
sc.setTableFillList(tableFillList);
ag.setStrategy(sc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent(rb.getString("parentPackage"));
pc.setController("controller");
pc.setService("service");
pc.setServiceImpl("service.impl");
pc.setEntity("model");
pc.setMapper("mapper");
ag.setPackageInfo(pc);
//注入自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
ArrayList<FileOutConfig> focList = new ArrayList<>();
// 调整 xml 生成目录
focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("xmlOutPutDir") + "/" + tableInfo.getEntityName() + "Mapper.xml";
}
});
cfg.setFileOutConfigList(focList);
ag.setCfg(cfg);
// 模板设置,null就不生成
TemplateConfig tc = new TemplateConfig();
tc.setController("/templates/controller.java.vm");
tc.setService("/templates/service.java.vm");
tc.setServiceImpl("/templates/serviceImpl.java.vm");
tc.setEntity("/templates/entity.java.vm");
tc.setMapper("/templates/mapper.java.vm");
tc.setXml(null);
ag.setTemplate(tc);
// 执行
ag.execute();
}
}
这个代码生成器对应的是MySQL数据库,如果是Oracle或者其他,需要修改相应的的数据源配置。
3、执行程序,显示文件“=======文件生成完成!!!=======”说明成功
五、Mybatis Plus 启动配置
1、主配置文件配置,主要看 Mybatis Plus 配置
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/shiro?characterEncoding=utf8&useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
username: root
password: root
druid:
initial-size: 5
min-idle: 5
max-active: 20
min-evictable-idle-time-millis: 600000
validation-query: SELECT 1
test-while-idle: true
test-on-borrow: false
test-on-return: false
keep-alive: true
filters: stat,wall,slf4j
mybatis-plus:
mapper-locations: classpath:mapper/*.xml # 映射文件位置
global-config:
db-config:
id-type: auto # 自动递增ID
logic-not-delete-value: 0 # 逻辑未删除
logic-delete-value: 1 # 逻辑已删除
update-strategy: not_empty # 字段策略,当字段值为null或""时,不更新
insert-strategy: not_empty # 字段策略,当字段值为null或""时,不插入
select-strategy: not_empty # 字段策略,当字段值为null或""时,不增加相应查询条件,要使用Wrapper.setEntity设置的查询条件,selectStrateg才会生效
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL
# 自定义配置
jwt:
token:
name: Authorization
2、在启动类扫描Mapper类 或者 在Mapper类加注解@Mapper,二选一
六、分页配置
创建 Mybatis Plus 配置类,内容如下
package online.heycm.mybatisplus.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
/**
* 分页配置
* 配置bean,将逻辑分页变为物理分页
*/
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
}
七、字段自动填充配置
创建字段自动填充配置类,内容如下
package online.heycm.mybatisplus.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
@Component
public class AutoFillHandler implements MetaObjectHandler {
@Value("${jwt.token.name}")
private String jwtTokenName;
@Autowired
HttpServletRequest request;
/**
* 插入填充策略
*/
@Override
public void insertFill(MetaObject metaObject) {
//判断表里是否有setIsDeleted方法,如果有可以再去加自动填充,因为我们所有表都有,所以不加判断
//boolean hasSetter = metaObject.hasSetter("isDeleted");
setInsertFieldValByName("isDeleted", 0, metaObject);
setInsertFieldValByName("createTime", new Date(), metaObject);
setInsertFieldValByName("modifyTime", new Date(), metaObject);
setInsertFieldValByName("createUser", getIdByToken(), metaObject);
setInsertFieldValByName("modifyUser", getIdByToken(), metaObject);
}
/**
* 更新填充策略
*/
@Override
public void updateFill(MetaObject metaObject) {
// 判断是否已设置修改人,若已设置,此处不再填充
Object modifyUser = getFieldValByName("modifyUser", metaObject);
if(modifyUser == null) {
setUpdateFieldValByName("modifyUser", getIdByToken(), metaObject);
}
setUpdateFieldValByName("modifyTime", new Date(), metaObject);
}
/**
* 获取当前用户ID
*/
private Integer getIdByToken() {
String token = request.getHeader(jwtTokenName);
// 打印token
System.out.println("=======>token: " + token);
if (token == null) {
return null;
}
// TODO 解析JWT,获取JTW中的用户ID
return 1;
}
}
八、模拟测试
1、写接口
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping("/save")
public ResModel save(@RequestBody User user) {
// 有ID执行更新,无ID执行插入
// 测试 update-strategy、insert-strategy、字段填充
boolean isOk = user.insertOrUpdate();
return Result.apiRes(isOk, "成功", "失败");
}
@PostMapping("/query")
public ResModel query(@RequestBody User user) {
// 按条件查询
// 测试 select-strategy
User one = user.selectOne(new QueryWrapper<User>().setEntity(user));
return Result.apiRes(one != null, one, "查无此人");
}
}
2、测试
插入测试:字段为""或null时不插入,字段自动插入策略
发送请求
请求结果
控制台打印
数据库
更新测试:字段为""或null时不更新,字段自动更新策略,获取token
发送请求
请求结果
控制台打印
数据库
查询测试:当字段值为null或""时,不增加相应查询条件
发送请求
请求结果
控制台打印
发送请求
请求结果
控制台打印
更多用法参考官网,很详细。
- 0
- 0
-
分享