Spring Batch No serializer found for class java.io.ByteArrayInputStream for oracle.sql.TIMESTAMP
Posted
技术标签:
【中文标题】Spring Batch No serializer found for class java.io.ByteArrayInputStream for oracle.sql.TIMESTAMP【英文标题】: 【发布时间】:2021-10-21 10:44:51 【问题描述】:我使用 Spring Batch 并且有一个作业定义。我可以成功地从 db 中获取数据,但是在尝试处理第一个块后我的工作失败了。
我有一个JdbcPagingItemReader
并且有一个日期字段的排序定义:
Map<String, Order> sortKeys = new HashMap<>();
sortKeys.put("MY_DT", Order.ASCENDING);
OraclePagingQueryProvider queryProvider = new OraclePagingQueryProvider();
queryProvider.setSelectClause("---");
queryProvider.setFromClause("FROM ---");
queryProvider.setWhereClause("WHERE MY_DT >= :myDt");
但是我得到了这个错误:
Caused by: 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["JdbcPagingItemReader.start.after"]->java.util.LinkedHashMap["MY_DT"]->oracle.sql.TIMESTAMP["stream"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1277)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serializeWithType(UnknownSerializer.java:45)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:730)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeWithType(BeanSerializerBase.java:640)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeTypedFields(MapSerializer.java:941)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:696)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:681)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithType(MapSerializer.java:650)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithType(MapSerializer.java:33)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeTypedFields(MapSerializer.java:941)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:696)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:681)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithType(MapSerializer.java:650)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithType(MapSerializer.java:33)
at com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer.serialize(TypeWrappedSerializer.java:32)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4409)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:3621)
at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.serialize(Jackson2ExecutionContextStringSerializer.java:141)
at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.serialize(Jackson2ExecutionContextStringSerializer.java:104)
at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao.serializeContext(JdbcExecutionContextDao.java:302)
我认为这个问题与oracle.sql.TIMESTAMP
没有公共构造函数有关。因此,如果我将排序参数更改为非日期类型,一切都会像魅力一样。但是,即使我尝试自定义对象映射器,我也无法使其与日期排序一起使用。
有什么想法吗?
PS:作为一种解决方法,我尝试了这个但没有用:
@Configuration
public class JacksonObjectMapperConfiguration
@Bean
@Primary
public ObjectMapper objectMapper()
ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(TIMESTAMP.class, new OracleTimestampSerializer());
mapper.registerModule(simpleModule);
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
return mapper;
private static class OracleTimestampSerializer extends JsonSerializer<TIMESTAMP>
@Override
public void serializeWithType(oracle.sql.TIMESTAMP timestamp, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSerializer) throws IOException
WritableTypeId typeId = typeSerializer.writeTypePrefix(gen, typeSerializer.typeId(timestamp, JsonToken.VALUE_EMBEDDED_OBJECT));
serialize(timestamp, gen, serializers);
gen.writeTypeSuffix(typeId);
throw new RuntimeException("Error!");
@Override
public void serialize(oracle.sql.TIMESTAMP timestamp, JsonGenerator gen, SerializerProvider serializers)
try
gen.writeBinary(timestamp.getBytes());
throw new RuntimeException("Error!");
catch (IOException e)
System.out.println("serialize oracle.sql.Timestamp error :" + e.getMessage());
但是,也不会抛出运行时异常。
【问题讨论】:
这有帮助吗? ***.com/questions/60381349/… 很遗憾没有。我将使用与该问题相关的解决方法代码更新该问题。 【参考方案1】:从您共享的堆栈跟踪中,我看到问题发生在执行上下文被序列化时。事实上,这是由于默认的 Jackson 映射器不知道如何(反)序列化时间戳。提供自定义映射器是要走的路。但是,为此,您需要在自定义实现中提供自定义 JobRepository
到 JobRepositoryFactoryBean#setSerializer
。仅在应用程序上下文中将序列化程序声明为 bean 是不够的(我们计划改进此 here,如果您有兴趣,请对该问题进行投票或评论)。您可以在Configuring a JobRepository 部分找到有关如何自定义作业存储库的更多详细信息。
在您的情况下,您需要提供自定义BatchConfigurer
(或扩展DefaultBatchConfigurer
)并实现getJobRepository
(或覆盖createJobRepository
),例如:
@Configuration
@EnableBatchProcessing
public class MyJobConfigWithCustomSerializer
@Bean
public BatchConfigurer batchConfigurer(ObjectMapper objectMapper)
return new DefaultBatchConfigurer()
@Override
public JobRepository createJobRepository() throws Exception
Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer();
// customize serializer
serializer.setObjectMapper(objectMapper);
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setSerializer(serializer);
// set other properties on the factory bean
factory.afterPropertiesSet();
return factory.getObject();
【讨论】:
以上是关于Spring Batch No serializer found for class java.io.ByteArrayInputStream for oracle.sql.TIMESTAMP的主要内容,如果未能解决你的问题,请参考以下文章
Spring Batch ORA-08177: 运行单个作业时无法序列化此事务的访问,SERIALIZED 隔离级别
Spring Batch 解决 Could not autowire. No beans of ‘StepBuilderFactory‘ type found.
萤石-module 'serial' has no attribute 'Serial'
解决AttributeError: module ‘serial‘ has no attribute ‘Serial‘