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

如何解决MyBatis映射MSSQL Time到Java LocalTime报错问题

问题根因

该报错和MyBatis本身映射逻辑无关,核心原因是项目使用的jTDS JDBC驱动早已停止维护,最新正式版本仅支持JDBC 4.0规范,没有实现JDBC 4.2新增的ResultSet#getObject(int columnIndex, Class<T> type)重载方法。MyBatis内置的LocalTimeTypeHandler会直接调用该方法尝试获取LocalTime类型的返回值,jTDS未实现该方法就会抛出AbstractMethodError。

解决方案

方案1(优先推荐):替换为微软官方MSSQL驱动

jTDS驱动最后一个正式版本发布于2013年,后续无任何功能更新,不仅不支持Java 8+的时间类型,还存在高版本SQL Server兼容性差、未修复安全漏洞等问题。直接替换为微软官方持续维护的mssql-jdbc驱动即可一劳永逸解决所有JDBC新特性兼容问题,替换后无需修改任何现有MyBatis映射配置,数据库TIME类型到POJOLocalTime属性的映射可以直接正常工作。

方案2(存量场景兼容):自定义jTDS适配的LocalTime类型处理器

如果受历史项目约束暂时无法替换jTDS驱动,可以自定义类型处理器,绕开jTDS未实现的接口方法,通过老版本JDBC接口获取java.sql.Time类型值后手动转换为LocalTime:

  1. 编写自定义类型处理器类,代码如下:
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.time.LocalTime;

@MappedTypes(LocalTime.class)
@MappedJdbcTypes(JdbcType.TIME)
public class JtdsLocalTimeTypeHandler extends BaseTypeHandler<LocalTime> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, LocalTime parameter, JdbcType jdbcType) throws SQLException {
        ps.setTime(i, Time.valueOf(parameter));
    }

    @Override
    public LocalTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Time sqlTime = rs.getTime(columnName);
        return sqlTime == null ? null : sqlTime.toLocalTime();
    }

    @Override
    public LocalTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Time sqlTime = rs.getTime(columnIndex);
        return sqlTime == null ? null : sqlTime.toLocalTime();
    }

    @Override
    public LocalTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Time sqlTime = cs.getTime(columnIndex);
        return sqlTime == null ? null : sqlTime.toLocalTime();
    }
}
  1. 注册该类型处理器:
  • 如果使用MyBatis Spring Boot Starter,直接将该类放到Spring Boot启动类的子包路径下,即可被自动扫描注册
  • 如果使用原生MyBatis,可在mybatis-config.xml中添加如下配置注册:
<typeHandlers>
    <typeHandler handler="替换为该类的全限定类名.JtdsLocalTimeTypeHandler"/>
</typeHandlers>

注册完成后原有字段映射配置无需修改,即可正常完成TIME类型到LocalTime的转换。

注意事项

除LocalTime外,jTDS驱动对所有Java 8新增的java.time包下的时间类型(LocalDate、LocalDateTime、OffsetDateTime等)都存在相同的兼容问题,只要使用MyBatis内置的对应类型处理器都会抛出相同的AbstractMethodError,如果坚持使用jTDS,需要为所有这些时间类型逐一编写兼容的自定义类型处理器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:36:27