oracle+myBatis ResultMap 类型为 map 时返回结果中存在 timestamp 时使用 jackson 转 json 报错
为了解决错误
/**
* ### 为了解决错误:
*
* <!doctype html>
HTTP Status 500 – Internal Server Error
Type 异常报告
消息 No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.HashMap[“data”]->com.zftdata.nyzft.pojo.ActiveUser[“user”]->com.zftdata.nyzft.controller.responsepojo.UserResponsePojoForShrio[“lonlatUpdatedAt”]->oracle.sql.TIMESTAMP[“stream”])
描述 服务器遇到一个意外的情况,阻止它完成请求。
Exception
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.HashMap[“data”]->com.zftdata.nyzft.pojo.ActiveUser[“user”]->com.zftdata.nyzft.controller.responsepojo.UserResponsePojoForShrio[“lonlatUpdatedAt”]->oracle.sql.TIMESTAMP[“stream”])
* com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
* com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
* com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:312)
* com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
* com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
* com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
* com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
* com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
* com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
* com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
* com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
* com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
* com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
* com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
* com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:718)
* com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:639)
* com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:33)
* com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
* com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
* com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3893)
* com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3207)
* com.zftdata.nyzft.shiro.CustomFormAuthenticationFilter.onLoginSuccess(CustomFormAuthenticationFilter.java:173)
* org.apache.shiro.web.filter.authc.AuthenticatingFilter.executeLogin(AuthenticatingFilter.java:54)
* org.apache.shiro.web.filter.authc.FormAuthenticationFilter.onAccessDenied(FormAuthenticationFilter.java:154)
* com.zftdata.nyzft.shiro.CustomFormAuthenticationFilter.onAccessDenied(CustomFormAuthenticationFilter.java:342)
* org.apache.shiro.web.filter.AccessControlFilter.onAccessDenied(AccessControlFilter.java:133)
* org.apache.shiro.web.filter.AccessControlFilter.onPreHandle(AccessControlFilter.java:162)
* org.apache.shiro.web.filter.PathMatchingFilter.isFilterChainContinued(PathMatchingFilter.java:203)
* org.apache.shiro.web.filter.PathMatchingFilter.preHandle(PathMatchingFilter.java:178)
* org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:131)
* org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
* org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
* org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
* org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
* org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
* org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
* org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
* org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
* org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
* org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347)
* org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)
* org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
* org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
* org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
* org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
* org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
* org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
* com.zftdata.nyzft.web.filter.CorsFilter.doFilter(CorsFilter.java:40)
*
):注意 主要问题的全部 stack 信息可以在 server logs 里查看
Apache Tomcat/8.5.53
二、解决方案
1.添加类
需注意事项:
@MappedJdbcTypes(value = {JdbcType.TIMESTAMP,JdbcType.OTHER})
注解当中的JdbcType值是根据mapper.xml中的JdbcType值自定义的
package com;
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.*;
import java.util.Date;
import oracle.sql.DATE;
import oracle.sql.TIMESTAMP;
import oracle.sql.TIMESTAMPLTZ;
import oracle.sql.TIMESTAMPTZ;
@MappedTypes({Object.class})
@MappedJdbcTypes(value = {JdbcType.TIMESTAMP,JdbcType.OTHER})
public class CustomTypeHandler extends BaseTypeHandler<Object> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {
if(o != null && o instanceof Date){
preparedStatement.setTimestamp(i, new Timestamp(((Date) o).getTime()));
}else{
preparedStatement.setObject(i, o);
}
}
@Override
public Object getNullableResult(ResultSet resultSet, String s) throws SQLException {
Object result = resultSet.getObject(s);
return resultSet.wasNull() ? null : dealResult(result);
}
@Override
public Object getNullableResult(ResultSet resultSet, int i) throws SQLException {
Object result = resultSet.getObject(i);
return resultSet.wasNull() ? null : dealResult(result);
}
@Override
public Object getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
Object result = callableStatement.getObject(i);
return callableStatement.wasNull() ? null : dealResult(result);
}
*
* @param result
* @return
* @throws SQLException
*/
private Object dealResult(Object result) throws SQLException {
if (result instanceof TIMESTAMP) {
return new Date(((TIMESTAMP) result).dateValue().getTime());
} else if (result instanceof DATE) {
return new Date(((DATE) result).dateValue().getTime());
} else if (result instanceof TIMESTAMPLTZ) {
return new Date(((TIMESTAMPLTZ) result).dateValue().getTime());
} else if (result instanceof TIMESTAMPTZ) {
return new Date(((TIMESTAMPTZ) result).dateValue().getTime());
} else{
return result;
}
}
}
2.添加配置
在mybatis配置的xml中添加
<typeHandlers>
<typeHandler handler="com.zftdata.nyzft.mybatis.CustomTypeHandler" />
</typeHandlers>