You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MyBatis与Oracle数据库时无法通过Timestamp过滤数据

问题分析

核心问题是:MyBatis通过java.sql.Timestamp参数查询Oracle的TIMESTAMP字段时返回空结果,但在SQL Developer中用TO_TIMESTAMP函数能正常查到数据。日志显示参数已正确传递,但匹配失败,大概率是时区不一致或TIMESTAMP精度不匹配导致的。

解决方案

方案1:统一参数与字段的精度匹配

Oracle的TIMESTAMP类型默认支持9位小数(纳秒级),而Java的java.sql.Timestamp在驱动传递时可能存在精度截断,导致和数据库存储的9位小数时间无法匹配。可以在SQL中显式转换精度对齐:

修改StudentDao.xml中的查询语句:

<select id="getStudent" resultMap="studentMap">
    SELECT
      s.id
    , s.name
    , s.audit_timestamp as auditTimestamp
    FROM
      student_audit s
    WHERE
      s.audit_timestamp = CAST(#{auditTimestamp} AS TIMESTAMP(9))
</select>

或者反过来,将数据库字段截断到参数的6位微秒精度:

<select id="getStudent" resultMap="studentMap">
    SELECT
      s.id
    , s.name
    , s.audit_timestamp as auditTimestamp
    FROM
      student_audit s
    WHERE
      CAST(s.audit_timestamp AS TIMESTAMP(6)) = #{auditTimestamp}
</select>

方案2:复用SQL Developer的查询逻辑(推荐)

既然SQL Developer中用TO_TIMESTAMP能成功,直接在MyBatis中复刻该逻辑,将参数转为指定格式的字符串后用Oracle函数解析:

方式1:修改参数类型为String

调整Mapper方法参数为字符串类型,传入格式如"2022-06-22 07:23:59.515462":

StudentEntity getStudent(@Param("name") String name,
      @Param("auditTimestamp") String auditTimestamp)

修改XML查询语句:

<select id="getStudent" resultMap="studentMap">
    SELECT
      s.id
    , s.name
    , s.audit_timestamp as auditTimestamp
    FROM
      student_audit s
    WHERE
      s.audit_timestamp = TO_TIMESTAMP(#{auditTimestamp}, 'YYYY-MM-DD HH24:MI:SS.FF6')
</select>

方式2:不修改参数类型,直接转换

如果不想改动Java参数类型,可在MyBatis中直接将Timestamp转为字符串后解析:

<select id="getStudent" resultMap="studentMap">
    SELECT
      s.id
    , s.name
    , s.audit_timestamp as auditTimestamp
    FROM
      student_audit s
    WHERE
      s.audit_timestamp = TO_TIMESTAMP(#{auditTimestamp, javaType=java.sql.Timestamp, jdbcType=VARCHAR}, 'YYYY-MM-DD HH24:MI:SS.FF6')
</select>

方案3:检查并统一时区

Java应用时区与Oracle数据库会话时区不一致,会导致时间值转换后无法匹配:

  • 查看数据库时区:执行SELECT DBTIMEZONE, SESSIONTIMEZONE FROM DUAL;
  • 查看Java应用时区:在代码中添加System.out.println(TimeZone.getDefault());
  • 统一时区的方法:
    1. JVM启动参数添加-Duser.timezone=Asia/Shanghai(替换为你的实际时区)
    2. 在MyBatis初始化脚本中执行Oracle时区设置:ALTER SESSION SET TIME_ZONE='Asia/Shanghai';
额外提示

你的Mapper方法定义了@Param("name")参数,但SQL中并未使用,建议移除该参数或补充对应的查询条件,避免代码冗余。

内容的提问来源于stack exchange,提问作者chaitanya guruprasad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 00:25:31