1 | create table la_trans_monitor |
其他和本题无关字段已省略。
生成的Model:
1 | package com.kangyonggan.app.dfjz.model.vo; |
问题分析
从debug日志中可以看出参数是有毫秒的,但是数据库中就是没有落入毫秒
1 | [DEBUG] 2017-06-16 10:59:11.039 [com.kangyonggan.app.dfjz.mapper.LaTransMonitorMapper.insertSelective.main:145] - ==> Preparing: INSERT INTO la_trans_monitor ( sys_date,sys_time,method_type,method_route,method_name,begin_time,end_time,used_time ) VALUES ( ?,?,?,?,?,?,?,? ) |
解决这个问题的过程中有想到:
- 会不会是MySQL版本问题?
- 会不会是Mybatis版本问题?
- 会不会是建表脚本问题?
- 会不会是配置问题?
通过控制变量法,经过一一验证,都没发现问题。
我曾经手写过简版Mybatis,所以清楚以下几点:
- 日志不等于它实际执行的SQL,所以看到日志中有毫秒是没多大意义的。
- PreparedStatement有两个主要步骤,一个是准备带有占位符的SQL,另一个就是给占位符填数据。
所以我猜测PreparedStatement在填数据的时候,对java.util.date的处理过程中丢掉了毫秒,接下来就是debug跟踪源代码,最后发现PreparedStatement填数据的类是在mysql-connector-java这个jar包下的。
源代码如下:
1 | private void setTimestampInternal(int parameterIndex, Timestamp x, Calendar targetCalendar, TimeZone tz, boolean rollForward) throws SQLException { |
从上面代码中可以看出,它在处理时间的时候,使用SimpleDateFormat进行格式化的,格式化中没保留毫秒,紧接着后面又去拼接纳秒formatNanos,但是继续跟踪此方法后发现它返回的是0,因此最后PreparedStatement填的值形如”yyyy-MM-dd HH:MM:ss.0”。
问题已经定位到,所以就想着能不能升级jar包版本解决问题呢?
去中央仓库搜一把, 发现我现在的版本5.1.9实在是太古老了,用的人也不多,于是换了新版的用的人较多的5.1.34, 果然成功解决问题。新版jar包核心代码如下:
1 | private void setTimestampInternal(int parameterIndex, Timestamp x, Calendar targetCalendar, TimeZone tz, boolean rollForward) throws SQLException { |