在实际项目上,使用 mybatis 进行数据插入或者更新的操作时,有时需要将系统内的所有特定字段属性进行赋值,这时我们需要在代码里面进行更新或者插入的时候将值赋值给指定的字段属性,但是这样做会显得很笨,代码也会很臃肿,所以我们可以使用 mybatis 提供的拦截器接口来实现我们特定的字段进行赋值。
一、mybatis 拦截器接口( Interceptor)
mybatis 提供一个拦截器接口 interceptor 帮助我们处理数据,实现该接口内的 intercept 方法可以处理我们的一些业务逻辑包括字段的赋值或者字段脱敏等等。
二、使用方法
/** * packageName com.easyadmin.pro.common.interceptor * * @author 骑着蚂蚁去上天 * @version JDK 17 * @className MybatisMetaObjectInterceptor * @date 2024/4/7 * @description mybatis 数据前置拦截器 */@Component@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})public class MybatisMetaObjectInterceptor implements Interceptor {}
注解解析:
- @Component:将类注册入 Spring 容器
- @Intercepts:标识此类为一个拦截器
MyBatis拦截器默认可以拦截的类型只有四种,即四种接口类型Executor、StatementHandler、ParameterHandler和ResultSetHandler。对于我们的自定义拦截器必须使用MyBatis提供的@Intercepts注解来指明我们要拦截的是四种类型中的哪一种接口。
接口类型解析:
-
Executor:拦截执行器方法
-
StatementHandler:拦截SQL语法构建处理
-
ParameterHandler:拦截参数处理
-
ResultSetHandler:拦截结果集处理
三、拦截器实现
/** * packageName com.easyadmin.pro.common.interceptor * * @author 骑着蚂蚁去上天 * @version JDK 17 * @className MybatisMetaObjectInterceptor * @date 2024/4/7 * @description mybatis 数据前置拦截器 */@Component@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})public class MybatisMetaObjectInterceptor implements Interceptor { /** * 拦截方法 * @param invocation * @return * @throws Throwable */ @Override public Object intercept(Invocation invocation) throws Throwable { MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; // 获取 SQL 命令 SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType(); // 只处理新增跟修改 if (Objects.equals(SqlCommandType.INSERT, sqlCommandType) || Objects.equals(SqlCommandType.UPDATE, sqlCommandType)) { // 获取参数 Object parameter = invocation.getArgs()[1]; MapperMethod.ParamMap map = (MapperMethod.ParamMap) parameter; Object obj = map.get(BaseConstants.PARAM);
// 业务逻辑处理
dealParameter(obj, sqlCommandType); } return invocation.proceed(); }
}
四、全部代码
package com.easyadmin.pro.common.interceptor;import com.easyadmin.pro.common.constants.BaseConstants;import com.easyadmin.pro.common.entity.BaseEntity;import com.easyadmin.pro.tool.WebUtils;import org.apache.ibatis.binding.MapperMethod;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.mapping.SqlCommandType;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.plugin.Intercepts;import org.apache.ibatis.plugin.Invocation;import org.apache.ibatis.plugin.Signature;import org.springframework.stereotype.Component;import java.lang.reflect.Field;import java.time.LocalDateTime;import java.util.Objects;/** * packageName com.easyadmin.pro.common.interceptor * * @author 骑着蚂蚁去上天 * @version JDK 17 * @className MybatisMetaObjectInterceptor * @date 2024/4/7 * @description mybatis 数据前置拦截器 */@Component@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})public class MybatisMetaObjectInterceptor implements Interceptor { /** * 拦截方法 * @param invocation * @return * @throws Throwable */ @Override public Object intercept(Invocation invocation) throws Throwable { MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; // 获取 SQL 命令 SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType(); // 只处理新增跟修改 if (Objects.equals(SqlCommandType.INSERT, sqlCommandType) || Objects.equals(SqlCommandType.UPDATE, sqlCommandType)) { // 获取参数 Object parameter = invocation.getArgs()[1]; MapperMethod.ParamMap map = (MapperMethod.ParamMap) parameter; Object obj = map.get(BaseConstants.PARAM); // 业务逻辑处理 dealParameter(obj, sqlCommandType); } return invocation.proceed(); } /** * 处理参数 * @param parameter * @param sqlCommandType */ private void dealParameter(Object parameter, SqlCommandType sqlCommandType) throws IllegalAccessException { Class<?> aClass = parameter.getClass(); Field[] declaredFields; // 父类不为BaseEntity说明不需要处理 if (!BaseEntity.class.isAssignableFrom(aClass)) { return; } // 获取父类私有成员变量 declaredFields = aClass.getSuperclass().getDeclaredFields(); for (Field field : declaredFields) { // insert 语句插入 创建人、创建时间 if (Objects.equals(SqlCommandType.INSERT, sqlCommandType)) { if (Objects.equals(BaseConstants.CREATE_USER_ID, field.getName())) { field.setAccessible(true); try { field.set(parameter, WebUtils.getUserId()); } catch (Exception e) { field.set(parameter, 1L); } } if (Objects.equals(BaseConstants.CREATE_TIME, field.getName())) { field.setAccessible(true); field.set(parameter, LocalDateTime.now()); } } // update 语句插入 更新人、更新时间 if (Objects.equals(SqlCommandType.UPDATE, sqlCommandType)) { if (Objects.equals(BaseConstants.UPDATE_USER_ID, field.getName())) { field.setAccessible(true); try { field.set(parameter, WebUtils.getUserId()); } catch (Exception e) { field.set(parameter, 1L); } } if (Objects.equals(BaseConstants.UPDATE_TIME, field.getName())) { field.setAccessible(true); field.set(parameter, LocalDateTime.now()); } } } }}
以上就是本次的Mybatis 数据前置处理实现,属于个人想法与实现,有问题请及时指出,谢谢!!!