Cassandra CodecNotFoundException: кодек не найден для запрошенной операции

У меня есть поле enum, которое я хочу сопоставить со столбцом в 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();

я могу подключиться к кассандре просто отлично. Вот фрагмент класса модели

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)

Что я делаю не так?


person AbtPst    schedule 27.12.2017    source источник


Ответы (2)


EnumOrdinalCodec используется только для отображения между int ‹-> Enum. Поскольку ваш Enum основан на строке, используйте вместо этого класс EnumNameCodec. Javadoc для этих двух классов кодеков приведен ниже. Надеюсь, поможет.

ИмяЭнумКодек

Кодек, который сериализует экземпляры Enum как varchars CQL, представляющие их программные имена, возвращаемые Enum.name().

ЭнумОрдиналКодек

Кодек, который сериализует экземпляры Enum как целые числа CQL, представляющие их порядковые значения, возвращаемые Enum.ordinal().

Ссылка на Javadoc

person sayboras    schedule 28.12.2017

Измените код следующим образом:

/* 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;
    }
}
person Sergey Okatov    schedule 04.04.2019