编写myBaits插件,insert,update操作自动更新新增时间,插入时间

一  定义相关的常量

public class DatabaseConstants {
    public static final String ET = "et";
    public static final String PARAM1 = "param1";
    public static final String INSERT = "INSERT";
    public static final String UPDATE = "UPDATE";
    public static final List<String> SQL_COMMAND_TYPE_LIST = Arrays.asList("INSERT", "UPDATE");
    public static final String CREATE_TIME = "createTime";
    public static final String CREATE_USER_ID = "createUserId";
    public static final String CREATE_USER_NAME = "createUserName";
    public static final String UPDATE_TIME = "updateTime";
    public static final String UPDATE_USER_ID = "updateUserId";
    public static final String UPDATE_USER_NAME = "updateUserName";
    public static final String TENANT_ID = "tenantId";
    public static final String DELETE_FLAG = "deleteFlag";

    public DatabaseConstants() {
    }
}

二  编写配置拦截器

2.1插入或更新是自动填充数据

package com.mdgyl.hussar.basic.config;

import com.jxdinfo.hussar.common.security.BaseSecurityUtil;
import com.jxdinfo.hussar.common.security.SecurityUser;
import com.mdgyl.common.constants.DatabaseConstants;
import com.mdgyl.common.enums.DeleteStatusEnum;
import com.mdgyl.common.util.ReflectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Properties;

/**
 * description: mybatis全局拦截器
 * author: wuyc
 * createTime: 2023-12-02 14:03:19
 */
@Slf4j
@Component
@Intercepts({
        @Signature(
                type = Executor.class, method = "update",
                args = {MappedStatement.class, Object.class}
        )
})
public class MybatisParamInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        // 获取Mybatis的当前操作方法名称
        String sqlCommandType = mappedStatement.getSqlCommandType().name();

        if (!DatabaseConstants.SQL_COMMAND_TYPE_LIST.contains(sqlCommandType)) {
            return invocation.proceed();
        }

        if (invocation.getArgs().length < 2) {
            return invocation.proceed();
        }

        // 获取Mybatis插入或更新时传入的参数对象
        Object paramEntity = invocation.getArgs()[1];
        this.interceptInsertOrUpdateMethod(sqlCommandType, paramEntity);

        return invocation.proceed();
    }

    /**
     * 插入或更新时的参数拦截方法
     *
     * @param methodName  Mybatis方法名称
     * @param paramEntity 参数实体类
     */
    private void interceptInsertOrUpdateMethod(String methodName, Object paramEntity) {
        SecurityUser securityUser = getSecurityUser();
        LocalDateTime systemTime = LocalDateTime.now();
        // 若Mybatis的当前方法为INSERT
        if (DatabaseConstants.INSERT.equals(methodName)) {
            fillInsertMethodProperties(paramEntity, securityUser, systemTime);
            return;
        }

        // 若Mybatis的当前方法为UPDATE
        if (DatabaseConstants.UPDATE.equals(methodName)) {
            fillUpdateMethodProperties(paramEntity, securityUser, systemTime);
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }

    // -------------------------------------- private method start, 私有方法放公有方法下面 --------------------------------------------

    /**
     * 新增数据时填充创建人、创建时间
     *
     * @param paramEntity  新增数据参数对象
     * @param securityUser 用户信息
     * @param systemTime   当前系统时间
     */
    private void fillInsertMethodProperties(Object paramEntity, SecurityUser securityUser, LocalDateTime systemTime) {
        fillProperties(paramEntity, DatabaseConstants.CREATE_TIME, systemTime);
        fillProperties(paramEntity, DatabaseConstants.CREATE_USER_ID, securityUser.getUserId());
        fillProperties(paramEntity, DatabaseConstants.CREATE_USER_NAME, securityUser.getUserName());
        fillProperties(paramEntity, DatabaseConstants.UPDATE_TIME, systemTime);
        fillProperties(paramEntity, DatabaseConstants.UPDATE_USER_ID, securityUser.getUserId());
        fillProperties(paramEntity, DatabaseConstants.UPDATE_USER_NAME, securityUser.getUserName());
        fillProperties(paramEntity, DatabaseConstants.DELETE_FLAG, DeleteStatusEnum.NORMAL.getCode());
        fillProperties(paramEntity, DatabaseConstants.TENANT_ID, securityUser.getTenantId());
    }

    /**
     * 编辑数据时填充创建人、创建时间
     *
     * @param paramEntity  新增数据参数对象
     * @param securityUser 登录用户信息
     * @param systemTime   当前系统时间
     */
    private void fillUpdateMethodProperties(Object paramEntity, SecurityUser securityUser, LocalDateTime systemTime) {
        if (!(paramEntity instanceof MapperMethod.ParamMap)) {
            return;
        }

        MapperMethod.ParamMap<?> paramMap = (MapperMethod.ParamMap<?>) paramEntity;
        Object updateEntity = paramMap.containsKey(DatabaseConstants.ET) ? paramMap.get(DatabaseConstants.ET) : paramMap.get(DatabaseConstants.PARAM1);
        if (Objects.isNull(updateEntity)) {
            return;
        }
        fillProperties(updateEntity, DatabaseConstants.UPDATE_TIME, systemTime);
        fillProperties(updateEntity, DatabaseConstants.UPDATE_USER_ID, securityUser.getUserId());
        fillProperties(updateEntity, DatabaseConstants.UPDATE_USER_NAME, securityUser.getUserName());
    }

    /**
     * 校验字段在数据是否存在,存在的话设置默认值
     *
     * @param paramEntity     操作对象
     * @param propertiesKey   数据库的key
     * @param propertiesValue 默认赋的值
     */
    private void fillProperties(Object paramEntity, String propertiesKey, Object propertiesValue) {
        if (!ReflectionUtils.existsField(paramEntity, propertiesKey)) {
            return;
        }
        try {
            ReflectionUtils.invokeSetterMethod(paramEntity, propertiesKey, propertiesValue);
        } catch (Exception e) {
            log.error("MybatisParamInterceptor fillProperties error,propertiesKey: {}, propertiesValue: {}, failReason: {}",
                    propertiesKey, propertiesValue, e.getMessage());
        }
    }

    /**
     * 获取系统登录用户信息
     *
     * @return SecurityUser
     */
    private SecurityUser getSecurityUser() {
        SecurityUser securityUser = BaseSecurityUtil.getUser();
        return Objects.isNull(securityUser) ? new SecurityUser() : securityUser;
    }

}

2.2  查询时处理逻辑删除的数据

package com.mdgyl.hussar.basic.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;


import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.Properties;
@Slf4j
@Component

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare",
        args = {Connection.class, Integer.class})})

public class LogicalDeleteInterceptor implements Interceptor {

    public static final String TARGET_TABLE ="t_exchange_rate";

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();

        // 获取原始的 SQL 语句
        String originalSql = statementHandler.getBoundSql().getSql();

        // 检查 SQL 是否是 SELECT 查询
        if (originalSql != null && originalSql.trim().toLowerCase().startsWith("select")) {
            // 检查表名是否为目标表
                if (originalSql.contains(TARGET_TABLE)) {
                    // 修改 SQL,添加逻辑删除字段的条件

                    String[] sqlStrArr = originalSql.split("WHERE");

                    StringBuilder stringBuilder = new StringBuilder(originalSql);
                    // 判断数据库是否有删除标识字段,如果有的话,就拼接
                    if (sqlStrArr.length <= 1) {
                        stringBuilder.append(" WHERE delete_flag = 0");
                        log.info("拼接后的sql是: {}", stringBuilder);
                    }
                  else  if (! sqlStrArr[1].contains("delete_flag")) {
                        stringBuilder.append(" and delete_flag = 0");
                    }

                    String modifiedSql = stringBuilder.toString();


                    // 设置修改后的 SQL
                    ReflectUtil.setFieldValue(statementHandler.getBoundSql(), "sql", modifiedSql);
                }
        }

        // 执行拦截的方法
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 这里可以用来设置插件的属性
    }
    public static class ReflectUtil {
        public static Object getFieldValue(Object obj, String fieldName) throws NoSuchFieldException, IllegalAccessException {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(obj);
        }

        public static void setFieldValue(Object obj, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj, value);
        }
    }
}

三  数据源绑定配置拦截器

package com.mdgyl.hussar.basic.config;

import org.apache.ibatis.plugin.Interceptor;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.boot.autoconfigure.SqlSessionFactoryBeanCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * description: mybatis拦截器配置
 * author: wuyc
 * createTime: 2023-12-02 14:13:54
 */
@Configuration
public class DataSourceConfig {

    // 注入数据源
    @Resource
    private DataSource dataSource;

    // 注入自定义参数拦截器
    @Resource
    private MybatisParamInterceptor paramInterceptor;
    @Resource
    LogicalDeleteInterceptor  logicalDeleteInterceptor;

    // 官方推荐的实现方式
    @Bean
    SqlSessionFactoryBeanCustomizer sqlSessionFactoryBeanCustomizer() {
        return new SqlSessionFactoryBeanCustomizer() {
            @Override
            public void customize(SqlSessionFactoryBean customizeFactoryBean) {
                // 设置数据源
                customizeFactoryBean.setDataSource(dataSource);
                // 设置自定义拦截器(可设置多个)
                Interceptor[] plugins = {logicalDeleteInterceptor,paramInterceptor};
                customizeFactoryBean.setPlugins(plugins);
            }
        };
    }


}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值