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

最新文章

  1. python 之 logging
  2. mysql错误汇总
  3. 总结一下classpath
  4. android手电筒(摇一摇也可开启手电筒)
  5. MongoDB中的字段类型Id
  6. WCF 入门 (18)
  7. 用css制作三角形
  8. (翻译)什么是Java的永久代(PermGen)内存泄漏
  9. SCVMM问题汇总
  10. 整理 iOS 9 适配中出现的坑
  11. ExtJs4 笔记(12) Ext.toolbar.Toolbar 工具栏、Ext.toolbar.Paging 分页栏、Ext.ux.statusbar.StatusBar 状态栏
  12. msys2 安装注意事项
  13. Disassembly2:Built-in Type
  14. 移动端返回上一页,刚需!document.referrer 详解
  15. 转 InnoDB索引
  16. vue中兄弟组件间 的传值 bus(可以理解为公共交通)
  17. 记录:.user.ini 使用
  18. 放大Button热区的方法哟
  19. django2.1---admin 修改模块的名字为中文显示
  20. UOJ #185【ZJOI2016】 小星星

热门文章

  1. js控制关闭layui的switch开关
  2. Stable Diffusion 关键词tag语法教程
  3. 第六周作业-N67044-张铭扬
  4. ChatGPT is at capacity right now.ChatGPT Plus subscriber login Add your email for a personalized login link的解决办法
  5. k8s之pod的生命周期
  6. Centos7 MyCat2 安装部署
  7. 设备树编译链接报错arch/arm/boot/dts/imx50.dtsi:16:42: fatal error: dt-bindings/
  8. C++ MFC学习 (一)
  9. netstate查找端口占用
  10. Django 之RestFramework