问题
最近协助渠道组开发新需求,封装实现了一个公共模块供不同渠道项目使用。
以前各个渠道项目有很多相似的菜单和功能,各自项目里自己的代码实现,本公共模块对新需求的功能点进行抽象,减少重复代码,提高模块复用性和可维护性。
目前有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