Spring data cassandra 中的自定义编解码器读取问题
Custom codecs read issue in Spring data cassandra
我的 Cassandra table 中有一个时间戳字段,我想将其映射到 Java Instant 类型。
在写作时很容易做到这一点。
我添加了custom codecs.
@Override
protected ClusterBuilderConfigurer getClusterBuilderConfigurer() {
return clusterBuilder -> {
clusterBuilder.getConfiguration().getCodecRegistry()
.register(InstantCodec.instance,
LocalDateCodec.instance,
LocalTimeCodec.instance);
return clusterBuilder;
};
}
告诉 spring 不要将我的 Instant 转换为其他类型。
private enum InstantWriteConverter implements Converter<Instant, Instant> {
INSTANT;
@Override
public Instant convert(Instant source) {
return source;
}
}
这样 Instant 将按原样传递并由 InstantCodec 处理。
但是当从 Cassandra 读回时,读取时间戳被映射到 Date,我无法更改此行为。因此,我需要向我的实体添加一个特殊的构造函数,以便将 Date 转换为 Instant。
我的分析。
解析Row数据时,Cassandra performs a look up to find an appropriate Codec. It does not respect the parameter types of the provided entity constructor and simply picks up the first codec which can handle the row data. In my case it picks up the timestamp->date codec because its present before the timestamp->instant codec in the CodecRegistry codecs list.
有什么方法可以直接将时间戳转换为 Instant 吗?
EDIT
已尝试注册读写转换器,但未使用读取转换器。
@WritingConverter
private enum InstantWriteConverter implements Converter<Instant, Long> {
INSTANT;
@Override
public Long convert(Instant source) {
return source.toEpochMilli();
}
}
@ReadingConverter
private enum InstantReadConverter implements Converter<Long, Instant> {
INSTANT;
@Override
public Instant convert(Long source) {
return Instant.ofEpochMilli(source);
}
}
成功了。读取转换器需要在Row->Class级别。
@Override
protected ClusterBuilderConfigurer getClusterBuilderConfigurer() {
return clusterBuilder -> {
clusterBuilder.getConfiguration().getCodecRegistry()
.register(InstantCodec.instance,
LocalDateCodec.instance,
LocalTimeCodec.instance);
return clusterBuilder;
};
}
@Override
public CustomConversions customConversions() {
return new CustomConversions(
Arrays.asList(ReadConverter.INSTANCE,
InstantWriteConverter.INSTANCE,
LocalTimeWriteConverter.INSTANCE,
DurationWriteConverter.INSTANCE,
LocalDateWriteConverter.INSTANCE));
}
@ReadingConverter
private enum ReadConverter implements Converter<Row, FlightFareInfo> {
INSTANCE;
@Override
public FlightFareInfo convert(Row source) {
return FlightFareInfo.convertFromRow(source);
}
}
我的 Cassandra table 中有一个时间戳字段,我想将其映射到 Java Instant 类型。 在写作时很容易做到这一点。
我添加了custom codecs.
@Override
protected ClusterBuilderConfigurer getClusterBuilderConfigurer() {
return clusterBuilder -> {
clusterBuilder.getConfiguration().getCodecRegistry()
.register(InstantCodec.instance,
LocalDateCodec.instance,
LocalTimeCodec.instance);
return clusterBuilder;
};
}
告诉 spring 不要将我的 Instant 转换为其他类型。
private enum InstantWriteConverter implements Converter<Instant, Instant> {
INSTANT;
@Override
public Instant convert(Instant source) {
return source;
}
}
这样 Instant 将按原样传递并由 InstantCodec 处理。
但是当从 Cassandra 读回时,读取时间戳被映射到 Date,我无法更改此行为。因此,我需要向我的实体添加一个特殊的构造函数,以便将 Date 转换为 Instant。
我的分析。 解析Row数据时,Cassandra performs a look up to find an appropriate Codec. It does not respect the parameter types of the provided entity constructor and simply picks up the first codec which can handle the row data. In my case it picks up the timestamp->date codec because its present before the timestamp->instant codec in the CodecRegistry codecs list.
有什么方法可以直接将时间戳转换为 Instant 吗?
EDIT
已尝试注册读写转换器,但未使用读取转换器。
@WritingConverter
private enum InstantWriteConverter implements Converter<Instant, Long> {
INSTANT;
@Override
public Long convert(Instant source) {
return source.toEpochMilli();
}
}
@ReadingConverter
private enum InstantReadConverter implements Converter<Long, Instant> {
INSTANT;
@Override
public Instant convert(Long source) {
return Instant.ofEpochMilli(source);
}
}
成功了。读取转换器需要在Row->Class级别。
@Override
protected ClusterBuilderConfigurer getClusterBuilderConfigurer() {
return clusterBuilder -> {
clusterBuilder.getConfiguration().getCodecRegistry()
.register(InstantCodec.instance,
LocalDateCodec.instance,
LocalTimeCodec.instance);
return clusterBuilder;
};
}
@Override
public CustomConversions customConversions() {
return new CustomConversions(
Arrays.asList(ReadConverter.INSTANCE,
InstantWriteConverter.INSTANCE,
LocalTimeWriteConverter.INSTANCE,
DurationWriteConverter.INSTANCE,
LocalDateWriteConverter.INSTANCE));
}
@ReadingConverter
private enum ReadConverter implements Converter<Row, FlightFareInfo> {
INSTANCE;
@Override
public FlightFareInfo convert(Row source) {
return FlightFareInfo.convertFromRow(source);
}
}