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) {
}
}
Mybatis拦截器,修改Date类型数据。设置毫秒为0的更多相关文章
- mybatis拦截器 修改mybatis返回结果集中的字段的值
项目中使用了shardingJDBC,业务库做了分库,公共库没在一起,所以导致做码值转换的时候,需要在实现类里面做转码,重复的代码量大,故考虑用mybatis拦截器,将码值转换后再做返回给实现类. ...
- 数据权限管理中心 - 基于mybatis拦截器实现
数据权限管理中心 由于公司大部分项目都是使用mybatis,也是使用mybatis的拦截器进行分页处理,所以技术上也直接选择从拦截器入手 需求场景 第一种场景:行级数据处理 原sql: select ...
- Mybatis拦截器实现分页
本文介绍使用Mybatis拦截器,实现分页:并且在dao层,直接返回自定义的分页对象. 最终dao层结果: public interface ModelMapper { Page<Model&g ...
- 玩转SpringBoot之整合Mybatis拦截器对数据库水平分表
利用Mybatis拦截器对数据库水平分表 需求描述 当数据量比较多时,放在一个表中的时候会影响查询效率:或者数据的时效性只是当月有效的时候:这时我们就会涉及到数据库的分表操作了.当然,你也可以使用比较 ...
- Mybatis拦截器实现原理深度分析
1.拦截器简介 拦截器可以说使我们平时开发经常用到的技术了,Spring AOP.Mybatis自定义插件原理都是基于拦截器实现的,而拦截器又是以动态代理为基础实现的,每个框架对拦截器的实现不完全相同 ...
- MyBatis拦截器原理探究
MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允 ...
- 基于Spring和Mybatis拦截器实现数据库操作读写分离
首先需要配置好数据库的主从同步: 上一篇文章中有写到:https://www.cnblogs.com/xuyiqing/p/10647133.html 为什么要进行读写分离呢? 通常的Web应用大多数 ...
- 通过spring抽象路由数据源+MyBatis拦截器实现数据库自动读写分离
前言 之前使用的读写分离的方案是在mybatis中配置两个数据源,然后生成两个不同的SqlSessionTemplate然后手动去识别执行sql语句是操作主库还是从库.如下图所示: 好处是,你可以人为 ...
- 【公众号转载】MyBatis拦截器原理探究
MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允 ...
- 详解Mybatis拦截器(从使用到源码)
详解Mybatis拦截器(从使用到源码) MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能. 本文从配置到源码进行分析. 一.拦截器介绍 MyBatis 允许你在 ...
随机推荐
- Too many requests in 1 hour. Try again later.的解决办法
原因 你的梯子用的人太多了,openAI本身就有问答频率限制. 解决办法 换个相对独立,没那么多人用的梯子,找个"安静点"的地区.
- latex table \ref{}编号混乱
解决:\lable{}要紧放在\caption{}下 点击查看代码 \begin{table} ... \caption{Table A} \label{TableA} ... \end{table}
- zabbix-agent2安装问题汇总
1.yum源报错 # 具体报错信息 failure: repodata/4bb73bd0742c638c3cd1e73a5f3dc8838c7b0d693c9f50b7ed8266c3e83308d3 ...
- list.ftl
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 < ...
- .net core 3.1项目运行在Windows server 2012R2服务器上,Decimal类型小数点不见了,求解!32112.7958
.net core 3.1项目运行在Windows server 2012R2服务器上,Decimal类型小数点不见了,求解! string str = "1002910.8241" ...
- 获取select的选中的值
var select = document.getElementById("sec")//获取元素 var idx = select.selectedIndex;//获取当前选中的 ...
- 092_Schema获取表字段的方式
Map<String, Schema.SObjectField> objectFields = Schema.getGlobalDescribe().get('ObjectName').g ...
- netmiko批量操作网络设备_pandas版
from concurrent.futures import ThreadPoolExecutor import netmiko import os from threading import Loc ...
- Burp学院-OS命令注入
1.OS command injection, simple case. 最简单的命令执行,[|] 两个只要有一个为True就执行 2.Blind OS command injection with ...
- js判断图片链接是否有效
let checkImgExists = function(url) { return new Promise(function(resolve, reject) { let ImgObj = new ...