MyBatis-Plus实现公共字段自动填充功能详解
作者:小刘要努力(????_??)? 发布时间:2021-10-19 22:14:39
1.问题分析
我们在开发中经常遇到多个实体类有共同的属性字段,例如在用户注册时需要设置创建时间、创建人、修改时间、修改人等字段,在用户编辑信息时需要设置修改时间和修改人等字段。这些字段属于公共字段,也就是很多表中都有这些字段,能不能对于这些公共字段在某个地方统一处理,来简化开发呢?
答案就是我们可是使用Mybatis Plus提供的公共字段自动填充功能。
2.实现步骤
Mybatis Plus公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。
实现步骤:
在实体类的属性上加入@TableField注解,指定自动填充的策略
@TableField(fill = FieldFill.INSERT)//插入时填充字段
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)//插入、更新时填充字段
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)//插入时填充字段
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)//插入、更新时填充字段
private Long updateUser;
按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectHandler接口
package com.lyq.reggie.common;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 自定义元数据对象处理器
*/
@Component
@Slf4j
public class MyMetaObjecthandler implements MetaObjectHandler {
/**
* 插入操作,自动填充
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充[insert]...");
log.info(metaObject.toString());
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime",LocalDateTime.now());
metaObject.setValue("createUser", BaseContext.getCurrentId());
metaObject.setValue("updateUser",BaseContext.getCurrentId());
}
/**
* 更新操作,自动填充
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
log.info("公共字段自动填充[update]...");
log.info(metaObject.toString());
long id = Thread.currentThread().getId();
log.info("线程id为:{}",id);
metaObject.setValue("updateTime",LocalDateTime.now());
metaObject.setValue("updateUser",BaseContext.getCurrentId());
}
}
3. 实现字段全局填充
这个时候我们嫌弃每个表都需要加对应的注解,麻烦,这个时候我们就可以使用Mybatis Plus提供全局配置 sqlInjector 用于注入ISqlInjector接口的子类,实现自定义方法注入。
自定义自己的通用方法可以实现接口ISqlInjector也可以继承抽象类 AbstractSqlInjector 注入通用方法 SQL 语句 然后继承 BaseMapper 添加自定义方法,全局配置 sqlInjector 注入 MP 会自动将类所有方法注入到 mybatis 容器中。
首先我们需要增加一个配置类,将这个数据过滤器注册为bean
@Configuration
public class MybatisPlusConfig {
/*
* @version V1.0
* Title: updateInterceptor
* @author LiuYanQiang
* @description 插入数据过滤器
* @createTime 2022/1/13 14:30
* @param []
* @return com.tfjybj.intelligentArticleSystem.config.MybatisPlusConfig.UpdateInterceptor*/
@Bean
public UpdateInterceptor updateInterceptor() {
return new UpdateInterceptor();
}
}
再接着写拦截方法继承抽象类 AbstractSqlInjector 并且实现接口ISqlInjector来进行SQL的拦截实现公共字段的全局填充
package com.lyq.jsoup.config.MybatisPlusConfig;
import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
/**
* @author : [LiuYanQiang]
* @version : [v1.0]
* @className : UpdateInterceptor
* @description : [自动给创建时间个更新时间加值]
* @createTime : [2022/1/12 9:09]
* @updateUser : [LiuYanQiang]
* @updateTime : [2022/1/12 9:09]
* @updateRemark : [描述说明本次修改内容]
*/
@Intercepts(value = {@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class UpdateInterceptor extends AbstractSqlParserHandler implements Interceptor {
/**
* 创建时间
*/
private static final String CREATE_TIME = "createTime";
/**
* 更新时间
*/
private static final String UPDATE_TIME = "updateTime";
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
// SQL操作命令
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
// 获取新增或修改的对象参数
Object parameter = invocation.getArgs()[1];
// 获取对象中所有的私有成员变量(对应表字段)
Field[] declaredFields = parameter.getClass().getDeclaredFields();
if (parameter.getClass().getSuperclass() != null) {
Field[] superField = parameter.getClass().getSuperclass().getDeclaredFields();
declaredFields = ArrayUtils.addAll(declaredFields, superField);
}
// mybatis plus判断
boolean plus= parameter.getClass().getDeclaredFields().length == 1 && parameter.getClass().getDeclaredFields()[0].getName().equals("serialVersionUID");
//兼容mybatis plus
if (plus) {
Map<String, Object> updateParam = (Map<String, Object>) parameter;
Class<?> updateParamType = updateParam.get(updateParam.keySet().iterator().next()).getClass();
declaredFields = updateParamType.getDeclaredFields();
if (updateParamType.getSuperclass() != null) {
Field[] superField = updateParamType.getSuperclass().getDeclaredFields();
declaredFields = ArrayUtils.addAll(declaredFields, superField);
}
}
String fieldName = null;
for (Field field : declaredFields) {
fieldName = field.getName();
if (Objects.equals(CREATE_TIME, fieldName)) {
if (SqlCommandType.INSERT.equals(sqlCommandType)) {
field.setAccessible(true);
field.set(parameter, new Timestamp(System.currentTimeMillis()));
}
}
if (Objects.equals(UPDATE_TIME, fieldName)) {
if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
field.setAccessible(true);
//兼容mybatis plus的update
if (plus) {
Map<String, Object> updateParam = (Map<String, Object>) parameter;
field.set(updateParam.get(updateParam.keySet().iterator().next()), new Timestamp(System.currentTimeMillis()));
} else {
field.set(parameter, new Timestamp(System.currentTimeMillis()));
}
}
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
if (target instanceof Executor) {
return Plugin.wrap(target, this);
}
return target;
}
@Override
public void setProperties(Properties properties) {
}
}
来源:https://blog.csdn.net/weixin_44684272/article/details/126067864


猜你喜欢
- 修改加密和验证方法/** * 生成BCryptPasswordEncoder密码 *
- 程序性能的主要表现点:执行速度:程序的反映是否迅速,响应时间是否足够短内存分配:内存分配是否合理,是否过多地消耗内存或者存在内存泄漏启动时间
- 前言感觉Jpa的动态构建查询不好使用,然后mybatis-plus没有动态构建表的功能,有没有可能使两者混合使用,利用Jpa自动建表的优势
- 官方文档 8.0Spring为不同缓存做了一层抽象,这里通过阅读文档以及源码会对使用以及原理做一些学习笔记。1.简介
- springboot Jpa通用接口,公共方法de 简单使用 pom文件加入jpa这是我的例子使用的依赖。jpa必须当
- 本文介绍了Android EasyBarrage实现轻量级弹幕效果,分享给大家,具体如下:概述EasyBarrage是Android平台的一
- 前言JDK 1.5 之前 synchronized 的性能是比较低的,但在 JDK 1.5 中,官方推出一个重量级功能 Lock,一举改变了
- 本文实例讲述了C#实现将浮点数表示的货币数量以汉字大写形式输出的方法。分享给大家供大家参考。具体如下:1.函数代码注:本段代码中能转化的最大
- Java命令运行jar 报错运行jar命令java -jar xxx.jar报错:Caused by: java.lang.ClassNot
- 废话不多说了额,直接给大家贴代码了,具体代码如下所示:/** * 下载指定路径的文件,并写入到指定的位置 * &
- 指示器时间轴在外卖、购物类的APP里会经常用到,效果大概就像下面这样,看了网上很多文章,大都是自己绘制,太麻烦,其实通过ListView就可
- 这篇文章主要介绍了Spring如何使用注解的方式创建bean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需
- 本文需求实现了java通过方向键控制小球移动的具体过程,供大家参考,具体内容如下需求分析:第一 要画出一个小球第二 要能通过控制方向键控制它
- 一.关于使用Mybatisplus自带的selectById和insert方法时的一些问题1.selectById的问题(1).表的主键列名
- spring mvc url匹配禁用后缀访问在spring mvc中默认 访问url 加任意后缀名都能访问比如:你想访问 /login ,但
- js和python是两种语言,js处理网页数据,python可作为服务端开发,两者通过websocket进行通信。websocket是soc
- 在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 S
- MessageFormat本身与语言环境无关,而与用户提供给MessageFormat的模式和用于已插入参数的子格式模式有关,以生成适用于不
- IDEA 2020.1 版自动导入MAVEN依赖的方法(新版MAVEN无法自动导入/更新POM依赖、MAVEN设置自动更新、自动更新快捷键)
- 一、List<T>对象中的T是值类型的情况(int 类型等)对于值类型的List直接用以下方法就可以复制:List<T&g