问题描述

在使用 Insert 插入数据到 Oracle 中时,对于  java.util.Date  类型数据,只会记录年月日,丢失了时分秒。

原因分析

在插入数据时指定了  Date  类型的 JDBC 类型为  DATE,其在向 Oracle 插入数据时,会默认调用  DateOnlyTypeHandler  处理  DATE  类型的日期,转化 Java 类型到 Sql 格式。

1
#{updateTime,jdbcType=DATE}

Mybatis 通过  TypeHandlerRegistry  注册 Java 类型与 JDBC 类型之间的映射关系:

1
2
3
4
5
6
7
8
9
10
11
12
// java 类型为 Date.class,不指定 jdbc 类型,则默认使用 DateTypeHandler
register(Date.class, new DateTypeHandler());
// java 类型为 Date.class,jdbc 类型为 DATE,则默认使用 DateOnlyTypeHandler
register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
// java 类型为 Date.class,jdbc 类型为 TIME,则默认使用 DateOnlyTypeHandler
register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
// 不指定 java 类型,jdbc 类型为 TIMESTAMP,则默认使用 DateTypeHandler
register(JdbcType.TIMESTAMP, new DateTypeHandler());
// 不指定 java 类型,jdbc 类型为 DATE,则默认使用 DateOnlyTypeHandler
register(JdbcType.DATE, new DateOnlyTypeHandler());
// 不指定 java 类型,jdbc 类型为 TIME,则默认使用 DateOnlyTypeHandler
register(JdbcType.TIME, new TimeOnlyTypeHandler());

在  DateOnlyTypeHandler 中,使用了  java.sql.Date  设置时间,该日期格式只会精确到年月日。

1
2
3
4
public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType)
throws SQLException {
ps.setDate(i, new java.sql.Date((parameter.getTime())));
}

解决方案

参考  TypeHandlerRegistry  中的映射关系可以得出以下解决方案:

  1. 不指定 JDBC 类型;
  2. 指定 JDBC 类型为  TIMESTAMP
  3. 指定  typeHandler 为  org.apache.ibatis.type.DateTypeHandler(需要写全处理器的限定名),且指定处理优先级最高。

评论