我使用Spring Batch与H2等嵌入式存储相结合,获得了奇怪的结果。
以下是我的案例:
我的项目只是常规的Spring Boot微服务。域层具有实体 Model 类,具有瞬态 List 字段。该字段由字节数组字段支持,该字段又不是瞬态的,应该存储。我使用 @PrePersist 和 @PostLoad 序列化和反序列化列表。加载模型后,我清除数组,因此它不会占用内存。
该服务有两个控制器: ModelController 和 AnalyzeController 。他们每个人都执行Spring Batch作业。第一个作业创建Model并将其存储到db中。 db的第二个作业拉模型并用它来计算。
@Entity
@Getter
@Setter
@Table(name = "Model")
@Slf4j
public class Model {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Column(name = "id", length = 36)
private String id;
@Transient
private List<Cluster<ItemPoints>> clusters;
@Column(columnDefinition = "BYTEA")
private byte[] serializedClusters;
//region Serialization / Deserialization
@PrePersist
public void serializeClusters() {
try (ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out)) {
oos.writeObject(clusters);
serializedClusters = out.toByteArray();
} catch (IOException e) {
log.error(SERIALIZATION_ERROR_MESSAGE, e);
}
}
@PostLoad
@SuppressWarnings("unchecked")
public void deserializeClusters() {
try (ByteArrayInputStream in = new ByteArrayInputStream(serializedClusters);
ObjectInputStream is = new ObjectInputStream(in)) {
clusters = (List<Cluster<TimeSeriesItemPoints>>) is.readObject();
} catch (IOException | ClassNotFoundException e) {
log.error(SERIALIZATION_ERROR_MESSAGE, e);
}
// clear serialized data as it is no more needed
serializedClusters = new byte[]{};
}
//endregion
}
存储库层由Spring(CrudRepository)提供
如果我第一次尝试在ModelController之后执行AnalyzeController它按预期工作,但是对存储库的进一步调用返回带有空数组的模型(并且List不会被反序列化)。
这仅适用于嵌入式数据库和单个DataSource(批处理和模型相同)。
如果我使用两个不同的DataSource,它可以正常工作。如果我使用外部数据库,即使使用单个DataSource(例如PostgreSQL)也能正常工作。它也适用于单个数据源而没有Spring Batch。
单个数据源案例的配置:
@Configuration
@Profile("default")
public class DefaultDataSourceConfiguration {
@Bean
public DataSource batchDataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
}
}