【问题标题】:Cassandra CodecNotFoundException: Codec not found for requested operationCassandra CodecNotFoundException:未找到请求操作的编解码器
【发布时间】:2018-06-08 08:25:39
【问题描述】:

我有一个枚举字段,我想映射到 cassandra 中的列

public enum MyEnum {
    Aa,
    Bb,
    Cc,
}

这是我的注册方式

CodecRegistry myCodecRegistry = new CodecRegistry();
             myCodecRegistry.register(new EnumOrdinalCodec<MyEnum>(MyEnum.class));

            cluster = Cluster.builder().addContactPoint(cassandraHosts).withPort(cassandraPort).withCodecRegistry(myCodecRegistry).build();

我可以很好地连接到 cassandra。这是模型类的sn-p

public class MyModel
{
    @PartitionKey
    @Column(name="id")
    private String id;

    @ClusteringColumn
    @Column(name="name")
    private String name = "";

    @Column(name="enum")
    private MyEnum enum;

    public MyModel(String i, String n)
    {
        id=i;
        name=n
        enum=MyEnum.Aa;
    }
}

这是我使用 CQL 创建表的方式

CREATE TABLE IF NOT EXISTS 
tab 
    (
        name varchar ,
        id varchar, 
        enum varchar, 
        PRIMARY KEY ((id), name));

终于,我有了我的映射代码

    manager = new MappingManager(session);
    mapper = manager.mapper(MyModel.class);
    accessor = manager.createAccessor(MyAccessor.class);

这里是MyAccessor

@Accessor
public interface MyAccessor{

    @Query("SELECT * FROM case WHERE id=? and name=? ALLOW FILTERING;")
    MyModel readByIdAndName(String id,String name);
}

所以当我尝试执行时

MyModel m = new MyModel("asdasf","qw");
mapper.save(m);

我明白了

com.datastax.driver.core.exceptions.CodecNotFoundException: Codec not found for requested operation: [varchar <-> my.pack.MyEnum]
    at com.datastax.driver.core.exceptions.CodecNotFoundException.copy(CodecNotFoundException.java:56)
    at com.datastax.driver.core.exceptions.CodecNotFoundException.copy(CodecNotFoundException.java:25)
    at com.datastax.driver.mapping.DriverThrowables.propagateCause(DriverThrowables.java:41)
    at com.datastax.driver.mapping.Mapper.save(Mapper.java:289)

我做错了什么?

【问题讨论】:

    标签: java cassandra datastax cassandra-3.0


    【解决方案1】:

    EnumOrdinalCodec 仅用于在 int Enum 之间进行映射。由于您的 Enum 基于字符串,因此请改用 EnumNameCodec 类。这两个编解码器类的 Javadoc 如下所示。希望对您有所帮助。

    枚举名称编解码器

    将 Enum 实例序列化为 CQL varchars 的编解码器 Enum.name() 返回的程序名称。

    EnumOrdinalCodec

    将 Enum 实例序列化为 CQL 整数的编解码器,表示它们的 Enum.ordinal() 返回的序数值。

    链接到Javadoc

    【讨论】:

      【解决方案2】:

      如下修改你的代码:

      /* This is not required
      CodecRegistry myCodecRegistry = new CodecRegistry();
               myCodecRegistry.register(new EnumOrdinalCodec<MyEnum>(MyEnum.class));
      */
      cluster = Cluster
          .builder()
          .addContactPoint(cassandraHosts)
          .withPort(cassandraPort)
          .build();
      
      class MyEnumCodec: EnumOrdinalCodec<MyEnum> { MyEnumCodec() { super(MyEnum.class) } }
      
      public class MyModel
      {
          @PartitionKey
          @Column(name="id")
          private String id;
      
          @ClusteringColumn
          @Column(name="name")
          private String name = "";
      
          @Column(name="enum", codec = MyEnumCodec.class)
          private MyEnum enum;
      
          public MyModel(String i, String n)
          {
              id=i;
              name=n
              enum=MyEnum.Aa;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2019-11-28
        • 1970-01-01
        • 2017-03-24
        • 2019-01-03
        • 2017-02-16
        • 2019-05-27
        • 2017-04-07
        • 2018-01-06
        • 2019-09-30
        相关资源
        最近更新 更多