ruoyi-vue整合mybatis-plus
提纲
1 顶层pom中引入mybatis-plus
2 ruoyi-common中引入mybatis-plus
3 ruoyi-framework中引入mybatis-plus
4 ruoyi-admin项目下application.yml中配置mybatis-plus
1 顶层pom中引入mybatis-plus
有些文章中说要家pagehelper,但是我发现ruoyi-vue后端项目中已经有pagehelper了,所以就不加了。
<mybatis-plus.version>3.5.2</mybatis-plus.version>
<lombok.version>1.18.12</lombok.version>
<!-- mybatis-plus依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
2 ruoyi-common项目下pom中引入mybatis-plus
<!-- mybatis-plus依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
3 ruoyi-framework下的pom中引入mybatis-plus
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
ruoyi-framework/src/main/java/com.ruoyi.framework/config中删除MybatisConfig类,增加MybatisPlusConfig类
package com.ruoyi.framework.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@Configuration
public class MybatisPlusConfig {
static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
@Autowired
private Environment env;
public static String setTypeAliasesPackage(String typeAliasesPackage) {
ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
List<String> allResult = new ArrayList<String>();
try {
for (String aliasesPackage : typeAliasesPackage.split(",")) {
List<String> result = new ArrayList<String>();
aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
Resource[] resources = resolver.getResources(aliasesPackage);
if (resources != null && resources.length > 0) {
MetadataReader metadataReader = null;
for (Resource resource : resources) {
if (resource.isReadable()) {
metadataReader = metadataReaderFactory.getMetadataReader(resource);
try {
result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
if (result.size() > 0) {
HashSet<String> hashResult = new HashSet<String>(result);
allResult.addAll(hashResult);
}
}
if (allResult.size() > 0) {
typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
} else {
throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
}
} catch (IOException e) {
e.printStackTrace();
}
return typeAliasesPackage;
}
public Resource[] resolveMapperLocations(String[] mapperLocations) {
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<Resource> resources = new ArrayList<Resource>();
if (mapperLocations != null) {
for (String mapperLocation : mapperLocations) {
try {
Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
} catch (IOException e) {
// ignore
}
}
}
return resources.toArray(new Resource[resources.size()]);
}
/**
* 新版配置
*
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//能够添加很多拦截器实现
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//乐观锁拦截器
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
ruoyi-framework/src/main/java/com.ruoyi.framework/下创建mybatisplus包,包下创建MyMetaObjectHandler类
package com.ruoyi.framework.mybatisplus;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.ruoyi.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.time.LocalDateTime;
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
public static final String CREATE_BY = "createBy";
public static final String CREATE_TIME = "createTime";
public static final String UPDATE_BY = "updateBy";
public static final String UPDATE_TIME = "updateTime";
public static final String DELETED = "delFlag";
/**
* 插入时的填充策略
*/
@Override
public void insertFill(MetaObject metaObject) {
// 起始版本 3.3.0(推荐使用)
this.setFieldValByName(CREATE_BY, SecurityUtils.getUsername(), metaObject);
this.setFieldValByName(CREATE_TIME, formatDate(metaObject.getSetterType(CREATE_TIME)), metaObject);
this.setFieldValByName(UPDATE_BY, SecurityUtils.getUsername(), metaObject);
this.setFieldValByName(UPDATE_TIME, formatDate(metaObject.getSetterType(CREATE_TIME)), metaObject);
this.setFieldValByName(DELETED, "0", metaObject);
}
/**
* 更新时的填充策略
*/
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName(UPDATE_BY, SecurityUtils.getUsername(), metaObject);
this.setFieldValByName(UPDATE_TIME, formatDate(metaObject.getSetterType(CREATE_TIME)), metaObject);
}
/**
* 处理特殊日期
*
* @param setterType 参数类型
* @return 日期类型
*/
private Object formatDate(Class<?> setterType) {
if (Date.class.equals(setterType)) {
return new Date();
} else if (LocalDateTime.class.equals(setterType)) {
return LocalDateTime.now();
} else if (Long.class.equals(setterType)) {
return System.currentTimeMillis();
}
return null;
}
}
4 ruoyi-admin项目下application.yml中配置mybatis-plus
ruoyi-admin下application.yml中一定要注释掉mybatis配置,加上mybatis-plus的配置
# MyBatis配置
#mybatis:
# # 搜索指定包别名
# typeAliasesPackage: com.ruoyi.**.domain
# # 配置mapper的扫描,找到所有的mapper.xml映射文件
# mapperLocations: classpath*:mapper/**/*Mapper.xml
# # 加载全局的配置文件
# configLocation: classpath:mybatis/mybatis-config.xml
# Mybatis-plus的配置
mybatis-plus:
# 对应的 XML 文件位置
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.ruoyi.**.domain
# 针对 typeAliasesPackage,如果配置了该属性,则仅仅会扫描路径下以该类作为父类的域对象
#typeAliasesSuperType: Class<?>
# 如果配置了该属性,SqlSessionFactoryBean 会把该包下面的类注册为对应的 TypeHandler
#typeHandlersPackage: null
# 如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性
#typeEnumsPackage: null
# 启动时是否检查 MyBatis XML 文件的存在,默认不检查
checkConfigLocation: false
# 通过该属性可指定 MyBatis 的执行器,MyBatis 的执行器总共有三种:
# SIMPLE:该执行器类型不做特殊的事情,为每个语句的执行创建一个新的预处理语句(PreparedStatement)
# REUSE:该执行器类型会复用预处理语句(PreparedStatement)
# BATCH:该执行器类型会批量执行所有的更新语句
executorType: SIMPLE
# 指定外部化 MyBatis Properties 配置,通过该配置可以抽离配置,实现不同环境的配置部署
configurationProperties: null
configuration:
# 自动驼峰命名规则(camel case)映射
# 如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名
mapUnderscoreToCamelCase: true
# 默认枚举处理类,如果配置了该属性,枚举将统一使用指定处理器进行处理
# org.apache.ibatis.type.EnumTypeHandler : 存储枚举的名称
# org.apache.ibatis.type.EnumOrdinalTypeHandler : 存储枚举的索引
# com.baomidou.mybatisplus.extension.handlers.MybatisEnumTypeHandler : 枚举类需要实现IEnum接口或字段标记@EnumValue注解.
defaultEnumTypeHandler: org.apache.ibatis.type.EnumTypeHandler
# 当设置为 true 的时候,懒加载的对象可能被任何懒属性全部加载,否则,每个属性都按需加载。需要和 lazyLoadingEnabled 一起使用。
aggressiveLazyLoading: true
# MyBatis 自动映射策略
# NONE:不启用自动映射
# PARTIAL:只对非嵌套的 resultMap 进行自动映射
# FULL:对所有的 resultMap 都进行自动映射
autoMappingBehavior: PARTIAL
# MyBatis 自动映射时未知列或未知属性处理策
# NONE:不做任何处理 (默认值)
# WARNING:以日志的形式打印相关警告信息
# FAILING:当作映射失败处理,并抛出异常和详细信息
autoMappingUnknownColumnBehavior: NONE
# Mybatis一级缓存,默认为 SESSION
# SESSION session级别缓存,同一个session相同查询语句不会再次查询数据库
# STATEMENT 关闭一级缓存
localCacheScope: SESSION
# 开启Mybatis二级缓存,默认为 true
cacheEnabled: true
global-config:
# 是否打印 Logo banner
banner: true
# 是否初始化 SqlRunner
enableSqlRunner: false
dbConfig:
# 主键类型
# AUTO 数据库ID自增
# NONE 空
# INPUT 用户输入ID
# ASSIGN_ID 全局唯一ID
# ASSIGN_UUID 全局唯一ID UUID
idType: AUTO
# 表名前缀
tablePrefix: null
# 字段 format,例: %s,(对主键无效)
columnFormat: null
# 表名是否使用驼峰转下划线命名,只对表名生效
tableUnderline: true
# 大写命名,对表名和字段名均生效
capitalMode: false
# 全局的entity的逻辑删除字段属性名
logicDeleteField: null
# 逻辑已删除值
logicDeleteValue: 2
# 逻辑未删除值
logicNotDeleteValue: 0
# 字段验证策略之 insert,在 insert 的时候的字段验证策略
# IGNORED 忽略判断
# NOT_NULL 非NULL判断
# NOT_EMPTY 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断)
# DEFAULT 默认的,一般只用于注解里
# NEVER 不加入 SQL
insertStrategy: NOT_NULL
# 字段验证策略之 update,在 update 的时候的字段验证策略
updateStrategy: NOT_NULL
# 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
selectStrategy: NOT_NULL
参考资料
1、https://blog.csdn.net/qq_27480007/article/details/130522139
2、https://www.jb51.net/program/330752f1y.htm
3、https://www.jianshu.com/p/e9a8d96c5ffe