MyBatis+ShardingJDBC实体类LocalDateTime类型字段查询报SQLFeatureNotSupportedException: getObject with type
问题
最近协助渠道组开发新需求,封装实现了一个公共模块供不同渠道项目使用。
以前各个渠道项目有很多相似的菜单和功能,各自项目里自己的代码实现,表设计和代码风格迥异。
本公共模块对新需求的功能点进行抽象,通过设计回调接口来实现差异性,减少重复代码,提高模块复用性和可维护性。
目前有2个渠道项目接入了该公共模块,自测时发现其中1个运行正常,另1个项目运行报错,日志如下:
Error attempting to get column ‘create_time’ from result set.
...
at com.xxx.xxx(XxxServiceImpl.java:76)
Caused by: java.sql.SQLFeatureNotSupportedException: getObject with type
at org.apache.shardingsphere.shardingjdbc.jdbc.unsupported.AbstractUnsupportedOperationResultSet.getObject(AbstractUnsupportedOperationResultSet.java:221)
at org.apache.ibatis.type.LocalDateTimeTypeHandler.getNullableResult(LocalDateTimeTypeHandler.java:38)
at org.apache.ibatis.type.LocalDateTimeTypeHandler.getNullableResult(LocalDateTimeTypeHandler.java:28)
at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:81)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.applyAutomaticMappings(DefaultResultSetHandler.java:521)
注意到日志里的shardingjdbc
,该渠道项目使用了shardingjdbc
进行分表。
在公共模块里使用了MyBatis
,公共的实体类中定义了LocalDateTime
类型字段:
@TableField(value = "create_time", insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER)
private LocalDateTime createTime;
@TableField(value = "update_time" insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER)
private LocalDateTime updateTime;
本地启动项目调试,在LocalDateTimeTypeHandler
类的38行rs.getObject(columnName, LocalDateTime.class)
打上断点:
public class LocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime> {
...
@Override
public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getObject(columnName, LocalDateTime.class);
}
}
进到了AbstractUnsupportedOperationResultSet
类,抛出了SQLFeatureNotSupportedException
异常。
mybatis-plus-boot-starter
版本:3.1.2sharding-jdbc-core
版本:4.1.1
查询资料发现2者有冲突。
解决
通过自定义类扩展TypeHandler
来处理LocalDateTime
类型字段。
/**
* @author cdfive
*/
@MappedTypes(LocalDateTime.class)
@MappedJdbcTypes(value = JdbcType.TIMESTAMP, includeNullJdbcType = true)
public class CustomLocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime> {
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType)
throws SQLException {
if (parameter != null) {
ps.setString(i, dateTimeFormatter.format(parameter));
}
}
@Override
public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
String columnValue = rs.getString(columnName);
if (StringUtils.isEmpty(columnValue)) {
return null;
}
return LocalDateTime.parse(columnValue, dateTimeFormatter);
}
@Override
public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String columnValue = rs.getString(columnIndex);
if (StringUtils.isEmpty(columnValue)) {
return null;
}
return LocalDateTime.parse(columnValue, dateTimeFormatter);
}
@Override
public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String columnValue = cs.getString(columnIndex);
if (StringUtils.isEmpty(columnValue)) {
return null;
}
return LocalDateTime.parse(columnValue, dateTimeFormatter);
}
}
通过DateTimeFormatter
进行格式转换。
在项目的yml配置文件里指定类型处理类的包路径:
mybatis-plus:
type-handlers-package: com.xxx.mybatis.typehandler
参考
- 记ShardingSphere-JDBC的一个坑 https://blog.csdn.net/weixin_43356458/article/details/108101896
- mybaties plus实体类设置typeHandler不生效的解决 https://www.jb51.net/article/260371.htm
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人