Mybatis XML文件中,对java.util.Date对象的值到转换为执行SQL进行比较所做的隐式行为分析。

news/2024/9/27 7:16:52

本次分析了mybatis的mapper XML文件,sql的where子句中使用java.util.Date进行比较进行分析。

假设使用的是以下sql语句。

select * from xxx where create_time > '2024-06-20 20:38:38'

在mybatis中,会将java.util.Date对象的值转为java.sql.Timestamp,之后在mybatis取值的时候,会调用java.sql.Timestamp.toString()方法获取字符串值(也就是'2024-06-20 20:38:38')。
带有日期对比字符串的sql通过jdbc传到MySQL服务器端,此时,mysql会怎么处理这种对比呢?答案就是**字符串会隐式的转换create_time 值所代表的MySQL类型,之后进行对比。


分析只关注核心位置,不对整个流程进行分析(你断点此位置一般就能看到)。

下面就着重分析**Mybatis的XML文件,对java.util.Date类型的处理方式是怎样的?

首先进入到org.apache.ibatis.type.DateTypeHandler#setNonNullParameter方法,这里没什么说明的。

org.apache.ibatis.logging.jdbc.PreparedStatementLogger#invoke方法中,
我们会看到SET_METHODS方法是个Set集合。
SET_METHODS方法的值列表
核心位置

经过debug,我们会进到org.apache.ibatis.logging.jdbc.BaseJdbcLogger类的位置。

getParameterValueString方法用于打印输出值和值的类型。


这一行是关键语句return method.invoke(statement, params);
接着进入这行代码,会执行到com.alibaba.druid.pool.DruidPooledPreparedStatement#setTimestamp(int, java.sql.Timestamp)

在debug进入 stmt.setTimestamp(parameterIndex, x);


会到com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl#setTimestamp(int, java.sql.Timestamp)方法位置处,这里的选中这一行chain.preparedStatement_setTimestamp(this, parameterIndex, x);是核心,


之后会到com.mysql.cj.jdbc.ClientPreparedStatement#setTimestamp(int, java.sql.Timestamp)方法位置处。


最后会到com.mysql.cj.NativeQueryBindings#setTimestamp,这里就是给PreparedStatement对象的sql占位符绑定值得位置了。
可以看到,到最后这个值还是java.sql.Timestamp类型的。

至于PreparedStatement之后怎么处理我觉的就可以不用关注了,因为PreparedStatement配套的提供了setTimestamp方法,就说明内部已有支持的转换方式,而且MySQL驱动本身自身也支持setTimestamp。

MySQL官方文档的对于DATETIME和TIMESTAMP类型进行对比的资料。

https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html

https://dev.mysql.com/doc/refman/8.0/en/type-conversion.html

如果其中一个参数是 TIMESTAMP 或 DATETIME 列,而另一个参数是常量,那么在进行比较之前,会将常量转换为时间戳。这样做是为了对 ODBC 更友好。但 IN() 的参数不会这样做。为了安全起见,在进行比较时应始终使用完整的日期时间、日期或时间字符串。例如,在使用带有日期或时间值的 BETWEEN 时,为了获得最佳结果,应使用 CAST() 将值明确转换为所需的数据类型。来自一个或多个表的单行子查询不视为常量。例如,如果子查询返回一个要与 DATETIME 值比较的整数,那么比较将以两个整数的形式进行。整数不会转换为时间值。要将操作数作为 DATETIME 值进行比较,请使用 CAST() 将子查询值显式转换为 DATETIME 值。

其他资料

MySQL关于日期格式化的相关函数。
CAST转换类型
The DATE, DATETIME, and TIMESTAMP Types

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/46034.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

工作中的大分母规律简述

因为在工作之中,我总是遇到这种现象,姑且称此现象为大分母规律。

C# OpenFileDialog 选择本地文件

private void button1_Click(object sender, EventArgs e){OpenFileDialog ofd = new OpenFileDialog();//选择图片(*.png,*.jpg,*.gft) 是title提示//*.png;*.jpg;*.gft; 是你要过滤的类型ofd.Filter = "选择图片(*.png,*.jpg,*.gft)|*.png;*.jpg;*.gft;|选择文本(*.txt)…

apisix~为自定义插件设计一个configmap脚本

configMap Kubernetes 中的 ConfigMap 是一种用来存储配置数据的 API 资源,它允许您将配置信息以键值对的形式保存,并在容器中使用这些配置信息。ConfigMap 提供了一种将配置数据与应用程序解耦的方式,使得应用程序可以动态地获取配置而无需重新构建镜像。 以下是 ConfigMap…

F分布简述

4.1 简介 F分布英文名称F-distribution,最初由英国统计学家Fisher提出。 图4.1 F分布 4.2 性质 4.3 应用 4.3.1 ANOVA ANOVA全称analysis of variance,又称“变异数分析”或“F检验”,用于两个及两个以上样本均数差别的显著性检验。 某因素影响下…

vue3 详细配置 pinia,以及持久化处理

安装pinia pnpm install pinia pnpm install pinia-plugin-persistedstate使用pinia根目录下创建store文件夹,新家moudules文件夹和index.ts文件,如图:index.ts 文件// store/index.ts // 仓库大仓库 import { createPinia } from "pinia"; import piniaPluginPer…

拦截器的执行顺序

翻看源码: registry.addInterceptor()​public InterceptorRegistration addInterceptor(HandlerInterceptor interceptor) {InterceptorRegistration registration = new InterceptorRegistration(interceptor);this.registrations.add(registration);return registration;}​…

准入控制器(Admission Controller):ResourceQuota,ImagePolicyWebhook

准入控制器(Admission Controller):ResourceQuota,ImagePolicyWebhook ,准入控制器简介,为什么需要准入控制器,启用/禁用ResourceQuota资源配额,查看默认启用/禁用的准入控制器插件,ResourceQuota资源配额示例,禁用ResourceQuota ,配置ImagePolicyWebhook准入控制器禁止…

卡方分布简述

2.1 简介 卡方分布英文名称chi-square distribution,最初由法国数学家Abbe提出,后来德国科学家Helmert和英国数学家Pearson也分别导出。 则其概率密度函数如下,具体分布图如图2.1: 图2.1 卡方分布 2.2 性质 2.3 应用 2.3.1 卡方检验 卡方检验的基本思想来源于卡方分布,…