下面是详细的攻略:
问题描述
在进行 MyBatis 版本升级时,发现项目中的 OffsetDateTime 类型的参数无法正常解析,导致调用 SQL 语句失败。
复盘过程
经过分析,我们发现问题出在 MyBatis 版本升级之后,其内部使用的 Jackson 依赖库(用于 JSON 数据的解析和序列化操作)也进行了更新,从 2.9.4 更新到了 2.11.3。其中,2.11.3 版本对于 OffsetDateTime 的解析策略做了一些改变,导致了参数解析异常。
具体来说,2.11.3 版本的解析策略是将参数按照 UTC(协调世界时)解析为一个时间戳,然后再根据时差转换成本地时间。但是,原先的版本则是直接按照本地时间解析参数。
如果我们直接使用 Mybatis 的默认配置,则会发生参数解析异常。要解决该问题,需要进行如下配置:
<!-- mybatis-config.xml 配置中增加如下配置 -->
<typeHandler>
<jdbcType>OTHER</jdbcType>
<javaType>java.time.OffsetDateTime</javaType>
<handler>org.apache.ibatis.type.OffsetDateTimeTypeHandler</handler>
</typeHandler>
示例
我们提供两个示例,第一个示例展示了使用默认配置时的参数解析异常,第二个示例展示了使用了手动配置解析器之后的正常结果。
示例一
在 MyBatis 配置文件中增加如下配置:
<!-- mybatis-config.xml 中增加以下配置 -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
假设我们有以下的表结构:
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`created_at` datetime(6) DEFAULT CURRENT_TIMESTAMP(6),
`updated_at` datetime(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
然后我们想要使用 Mybatis 进行查询,查询用户创建时间在某一时间之后的数据。
public interface UserMapper {
List<User> selectByCreatedAtAfter(@Param("createdAt") OffsetDateTime createdAt);
}
<!-- user.xml 中定义的 SQL -->
<select id="selectByCreatedAtAfter" resultType="User">
SELECT *
FROM `user`
WHERE `created_at` > #{createdAt}
</select>
// 测试代码,模拟调用 Mapper 接口
public void testSelectByCreatedAtAfter() {
OffsetDateTime createdAt = OffsetDateTime.of(LocalDateTime.of(2021, 8, 1, 0, 0, 0), ZoneOffset.UTC);
List<User> users = userMapper.selectByCreatedAtAfter(createdAt);
System.out.println(users);
}
运行该测试方法,会发现 Mybatis 解析参数时,无法将 OffsetDateTime 类型的参数正确解析为本地时间,从而查询失败,报错信息如下:
org.springframework.dao.DataIntegrityViolationException:
### Error querying database. Cause: java.sql.SQLException:
### Cannot parse value of "java.time.OffsetDateTime" to java.sql.Timestamp
示例二
在 Mybatis 配置文件中增加以下配置:
<!-- mybatis-config.xml 配置 -->
<typeHandlers>
<typeHandler javaType="java.time.OffsetDateTime" handler="org.apache.ibatis.type.OffsetDateTimeTypeHandler"/>
</typeHandlers>
然后重新执行上述的测试代码,此时参数解析正常,查询结果也正确输出。
总结
通过以上的分析和解决方案,我们可以得到以下几个结论:
- MyBatis 升级版本时,需要注意其所依赖的外部包,比如 Jackson。
- 当参数类型为 OffsetDateTime 时,需要针对这个类型单独配置 TypeHandler。
- 配置 TypeHandler 时,需要明确设置 jdbcType 和 javaType 两个属性。
- TypeHandler 的配置位置有多种,可以在 MyBatis 配置文件中全局配置,也可以针对单个字段或参数进行配置。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:MyBatis版本升级导致OffsetDateTime入参解析异常问题复盘 - Python技术站