自定义编解码器读取Spring数据cassandra中的问题

时间:2017-02-15 12:01:10

标签: java spring datastax-java-driver spring-data-cassandra

我的Cassandra表中有一个时间戳字段,我希望将其映射到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最多可以找到合适的Codec。它不尊重所提供的实体构造函数的参数类型,只是选择可以处理行数据的第一个编解码器。在我的情况下,它会选择时间戳 - >日期编解码器,因为它存在于CodecRegistry codecs列表中的时间戳 - &gt;即时编解码器之前。

如何直接将时间戳转换为Instant?

  

修改

尝试注册读写转换器,但读取转换器未被使用。

    @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);
    }
}

1 个答案:

答案 0 :(得分:0)

搞定了。读转换器需要在Row-&gt; 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);
    }
}