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) { }
}

Mybatis拦截器,修改Date类型数据。设置毫秒为0的更多相关文章

  1. mybatis拦截器 修改mybatis返回结果集中的字段的值

    项目中使用了shardingJDBC,业务库做了分库,公共库没在一起,所以导致做码值转换的时候,需要在实现类里面做转码,重复的代码量大,故考虑用mybatis拦截器,将码值转换后再做返回给实现类.   ...

  2. 数据权限管理中心 - 基于mybatis拦截器实现

    数据权限管理中心 由于公司大部分项目都是使用mybatis,也是使用mybatis的拦截器进行分页处理,所以技术上也直接选择从拦截器入手 需求场景 第一种场景:行级数据处理 原sql: select ...

  3. Mybatis拦截器实现分页

    本文介绍使用Mybatis拦截器,实现分页:并且在dao层,直接返回自定义的分页对象. 最终dao层结果: public interface ModelMapper { Page<Model&g ...

  4. 玩转SpringBoot之整合Mybatis拦截器对数据库水平分表

    利用Mybatis拦截器对数据库水平分表 需求描述 当数据量比较多时,放在一个表中的时候会影响查询效率:或者数据的时效性只是当月有效的时候:这时我们就会涉及到数据库的分表操作了.当然,你也可以使用比较 ...

  5. Mybatis拦截器实现原理深度分析

    1.拦截器简介 拦截器可以说使我们平时开发经常用到的技术了,Spring AOP.Mybatis自定义插件原理都是基于拦截器实现的,而拦截器又是以动态代理为基础实现的,每个框架对拦截器的实现不完全相同 ...

  6. MyBatis拦截器原理探究

    MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允 ...

  7. 基于Spring和Mybatis拦截器实现数据库操作读写分离

    首先需要配置好数据库的主从同步: 上一篇文章中有写到:https://www.cnblogs.com/xuyiqing/p/10647133.html 为什么要进行读写分离呢? 通常的Web应用大多数 ...

  8. 通过spring抽象路由数据源+MyBatis拦截器实现数据库自动读写分离

    前言 之前使用的读写分离的方案是在mybatis中配置两个数据源,然后生成两个不同的SqlSessionTemplate然后手动去识别执行sql语句是操作主库还是从库.如下图所示: 好处是,你可以人为 ...

  9. 【公众号转载】MyBatis拦截器原理探究

    MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允 ...

  10. 详解Mybatis拦截器(从使用到源码)

    详解Mybatis拦截器(从使用到源码) MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能. 本文从配置到源码进行分析. 一.拦截器介绍 MyBatis 允许你在 ...

随机推荐

  1. Net6 Core Api(.net6)发布到IIS注意事项及显示HTTP 错误500.19解决方法

    Net6 Core Api发布到IIS不同于webapi,依赖框架不同,配置也移至项目内Program.cs 一.发布到指定文件夹,和IIS,不过注意IIS应用程序池选择的是 "无托管代码& ...

  2. Verilog设计指定寄存器数组在综合时使用block memory资源

    自己用verilog代码写的rom或ram会被综合成查找表LUT+REG构建,并没有使用到block memory资源. 资料:https://www.intel.com/content/www/us ...

  3. 多个module的verilog文件分割为多个文件

    python 分割含有多个module的verilog文件,按照module名来命名文件 import re # 读取 Verilog 文件 with open('test.v', 'r') as f ...

  4. 40.Ribbon和Feign

    优先级:全局代码 < 全局属性 < 细粒度代码 < 细粒度属性 推荐属性配置

  5. 【redis】配置优化及从库优先级

    https://blog.51cto.com/u_15902893/5912902 vim /etc/redis/redis.conf ##################基础############ ...

  6. battery-historian耗电量测试

    Battery-Historian简介 Battery-Historian是谷歌推出的一款专门分析Bugreport的工具,是谷歌2015年I/O大会上推出的一款检测运行在android5.0(Lol ...

  7. Word15 财务部年度报告office真题

    1.课程的讲解之前,先来对题目进行分析,首先需要在考生文件夹下,将Wrod素材.docx文件另存为Word.docx,后续操作均基于此文件,否则不得分.   2.这一步非常的简单,打开下载素材文件,在 ...

  8. C# 连接SQLSERVER数据库常用操作类

    //数据库连接字符串 public static string connectStr = @"server=.;database=test;uid=sa;pwd=123456;"; ...

  9. DataWork之 MaxComputer的使用

    注意: 由于MaxComputer里面没有主键 默认主键为 保单号+8位险种代码+责任起期 若无主键限制,就对所有的字段进行分组 所以每次join的时候,where条件需要加上 a.主键 =b.主键 ...

  10. golang 用gorm生成module文件

    网上的包过于繁琐复杂.所以写个简单.mysql的多种数据类型没有全部实现转化.可以编译成可执行文件. package main import ( "flag" "fmt& ...