今天同事将项目改成连接db2数据库,然后登录系统就报错:
com.ibm.db2.jcc.am.SqlSyntaxErrorException: [jcc][t4][1092][13956][4.16.53] 数据转换无效:所请求转换的结果列类型错误。 ERRORCODE=-4461, SQLSTATE=42815
at com.ibm.db2.jcc.am.fd.a(fd.java:739)
at com.ibm.db2.jcc.am.fd.a(fd.java:60)
at com.ibm.db2.jcc.am.fd.a(fd.java:120)
at com.ibm.db2.jcc.am.ResultSet.getObject(ResultSet.java:1827)
at com.ibm.db2.jcc.am.ResultSet.getObject(ResultSet.java:1841)
at com.alibaba.druid.filter.FilterChainImpl.resultSet_getObject(FilterChainImpl.java:1431)
at com.alibaba.druid.filter.FilterAdapter.resultSet_getObject(FilterAdapter.java:1719)
at com.alibaba.druid.filter.FilterChainImpl.resultSet_getObject(FilterChainImpl.java:1427)
at com.alibaba.druid.filter.stat.StatFilter.resultSet_getObject(StatFilter.java:855)
at com.alibaba.druid.filter.FilterChainImpl.resultSet_getObject(FilterChainImpl.java:1427)
at com.alibaba.druid.filter.FilterAdapter.resultSet_getObject(FilterAdapter.java:1719)
at com.alibaba.druid.filter.FilterChainImpl.resultSet_getObject(FilterChainImpl.java:1427)
at com.alibaba.druid.proxy.jdbc.ResultSetProxyImpl.getObject(ResultSetProxyImpl.java:1561)
at com.alibaba.druid.pool.DruidPooledResultSet.getObject(DruidPooledResultSet.java:1777)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.ibatis.logging.jdbc.ResultSetLogger.invoke(ResultSetLogger.java:69)
at com.sun.proxy.$Proxy282.getObject(Unknown Source)
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:85)
跟踪发现是LocalDateTime和LocalDate类型转换handler报错。
换了几个版本的驱动,都不行,没办法只能重写mybatis里面这两个类型的handler,特别注意注解种的属性:includeNullJdbcType = true,否则替换不成功。
/**
* Copyright 2009-2019 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.xxx.mybatis.typehandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.LocalDateTimeTypeHandler;
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.Timestamp;
import java.time.LocalDateTime;
import java.util.Objects;
/**
* db2 LocalDateTime 转换有问题,这里重写
*
* @author Tomas Rohovsky
* @since 3.4.5
*/
@MappedTypes(LocalDateTime.class)
@MappedJdbcTypes(value = JdbcType.TIMESTAMP, includeNullJdbcType = true)
public class DB2LocalDateTimeTypeHandler extends LocalDateTimeTypeHandler {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType)
throws SQLException {
ps.setObject(i, Timestamp.valueOf(parameter));
}
@Override
public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
Object object = rs.getObject(columnName);
if (Objects.isNull(object)) {
return null;
}
if (object instanceof Timestamp) {
return ((Timestamp) object).toLocalDateTime();
}
return rs.getObject(columnName, LocalDateTime.class);
}
@Override
public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
Object object = rs.getObject(columnIndex);
if (Objects.isNull(object)) {
return null;
}
if (object instanceof Timestamp) {
return ((Timestamp) object).toLocalDateTime();
}
return rs.getObject(columnIndex, LocalDateTime.class);
}
@Override
public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
Object object = cs.getObject(columnIndex);
if (Objects.isNull(object)) {
return null;
}
if (object instanceof Timestamp) {
return ((Timestamp) object).toLocalDateTime();
}
return cs.getObject(columnIndex, LocalDateTime.class);
}
}
/**
* Copyright 2009-2019 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.xxx.mybatis.typehandler;
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.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.Objects;
/**
* @since 3.4.5
* @author Tomas Rohovsky
*/
@MappedTypes(LocalDate.class)
@MappedJdbcTypes(value = JdbcType.DATE, includeNullJdbcType = true)
public class DB2LocalDateTypeHandler extends BaseTypeHandler<LocalDate> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, LocalDate parameter, JdbcType jdbcType)
throws SQLException {
ps.setObject(i, Date.valueOf(parameter));
}
@Override
public LocalDate getNullableResult(ResultSet rs, String columnName) throws SQLException {
Object object = rs.getObject(columnName);
if (Objects.isNull(object)) {
return null;
}
if (object instanceof Date) {
return ((Date) object).toLocalDate();
}
return rs.getObject(columnName, LocalDate.class);
}
@Override
public LocalDate getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
Object object = rs.getObject(columnIndex);
if (Objects.isNull(object)) {
return null;
}
if (object instanceof Date) {
return ((Date) object).toLocalDate();
}
return rs.getObject(columnIndex, LocalDate.class);
}
@Override
public LocalDate getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
Object object = cs.getObject(columnIndex);
if (Objects.isNull(object)) {
return null;
}
if (object instanceof Date) {
return ((Date) object).toLocalDate();
}
return cs.getObject(columnIndex, LocalDate.class);
}
}
最后一步,修改mybatis-plus的配置:
mybatis-plus:
type-handlers-package: com.xxx.mybatis.typehandler
然后重启服务,日期格式类型转换已经不报错了。