Mybatis拦截器,修改Date类型数据。设置毫秒为0

1:背景

  Mysql自动将datetime类型的毫秒数四舍五入,比如代码中传入的Date类型的数据值为  2021.03.31 23:59:59.700     到数据库   2021.04.01 00:00:00.0。

对数据准确性造成影响。

 

2:解决方案

  存入数据库之前去除毫秒数,终极方案使用mybatis拦截器,对insert和update类型的操作修改Date类型的参数值,去除毫秒数。

3:源代码

    package com.hyx.study.commom.aop.interceptor;
    
    import com.hyx.study.commom.util.JacksonUtils;
    import com.xkzhangsan.time.calculator.DateTimeCalculatorUtil;
    import org.apache.ibatis.executor.Executor;
    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.mapping.SqlCommandType;
    import org.apache.ibatis.plugin.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.apache.commons.beanutils.BeanUtils;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.sql.Connection;
    import java.sql.Statement;
    import java.util.*;
    
    /**
     * @author huangyaxiong
     * @version 1.0
     * @description: 利用mybatis拦截器,修改所有得Date类型得参数省略毫秒数
     * @date 2022-09-06 9:59
     */
    @Intercepts({
            @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
    })
    @Component
    public class MybatisDateInterceptor implements Interceptor {
    
        private static Logger logger = LoggerFactory.getLogger(MybatisDateInterceptor.class);
        /**
         * 获取sql语句
         * @param invocation
         * @return
         */
        public static String getSqlByInvocation(Invocation invocation) {
            final Object[] args = invocation.getArgs();
            MappedStatement ms = (MappedStatement) args[0];
            Object parameterObject = args[1];
            BoundSql boundSql = ms.getBoundSql(parameterObject);
            return boundSql.getSql();
        }
        @Override
        public Object intercept(Invocation invocation) throws InvocationTargetException, IllegalAccessException {
            String processSql = getSqlByInvocation(invocation);
            logger.info("原始sql==>{}",processSql);
            Object[] args = invocation.getArgs();
            for(Object arg:args){
                if(arg instanceof MappedStatement){
                    MappedStatement mappedStatement = (MappedStatement) arg;
                    SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
                    logger.info("操作类型==>{}",sqlCommandType);
                    if(sqlCommandType ==  SqlCommandType.INSERT || sqlCommandType == SqlCommandType.UPDATE){
                        continue;
                    }else{
                        break;
                    }
                }else if(arg instanceof Map){
                    //如果是map,有两种情况:(1)使用@Param多参数传入,由Mybatis包装成map。(2)原始传入Map
                    logger.info("这是一个包装过的类型!");
                    Map map=(Map)arg;
                    for (Object obj : map.values()){
                        tranDateProperty(obj);
                    }
                }else {
                    tranDateProperty(arg);
                }
            }
            return invocation.proceed ();
        }
    
        /**
         * @description: 修改对象中对的Date类型并且舍弃毫秒数
         * @param arg
         * @author 'huangyaxiong'
         * @date: 2022-09-06 11:16
         */
        private static void tranDateProperty(Object arg){
            try{
                Field[] declaredFields = arg.getClass().getDeclaredFields();
                for(Field field:declaredFields){
                    Class<?> type = field.getType();
                    if(Date.class == field.getType()){
                        field.setAccessible(true);
                        System.out.println(type);
                        String name = field.getName();
                        Object temp = field.get(arg);
                        if(temp != null){
                            Date value = (Date) field.get(arg);
                            System.out.println(value.getTime());
                            Date date = DateTimeCalculatorUtil.reduceAccuracyToSecond(value);
                            System.out.println(date.getTime());
                            field.set(arg,date);
    //                        BeanUtils.setProperty(arg,name,date);
                        }
                    }
                }
            }catch (Exception e){
                logger.error("日期数据转换出现了异常==>data:{}==>e:{}", JacksonUtils.object2Json(arg),e);
            }
        }
    
        @Override
        public Object plugin(Object target) {
            // 当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的次数
            return Plugin.wrap(target, this);
    //        return null;
        }
    
        @Override
        public void setProperties(Properties properties) {
    
        }
    }

 

posted @ 2022-09-06 17:45  低调小雄  阅读(681)  评论(0编辑  收藏  举报