无法使用 datastax java 驱动程序通过 UDT 密钥从 cassandra 检索

Can't retrieve by UDT key from cassandra with datastax java driver

我正在尝试使用用户定义的类型作为分区键在 cassandra 中存储对象。我正在使用 datastax java 驱动程序进行对象映射,虽然我能够插入到数据库中,但我无法检索对象。如果我更改分区键以使用非 udt(例如文本),我可以保存和检索(即使对象上有其他相同类型的 udt)。通过阅读文档,似乎允许 UDT 作为键。我也找不到任何迹象表明 java 驱动程序也不支持 udts 作为键。看起来它在对象的映射过程中失败了,但只有当 UDT 是分区键时才会失败。

这是不受支持的功能吗?使用对象映射器时是否只需要使用默认类型作为键?还是我做错了什么?

以下是我用来设置数据库的cql命令:

create keyspace example_keyspace;
use example_keyspace;
create type my_data_type (value text);
create table my_classes (key frozen<my_data_type>, value frozen<my_data_type>, primary key (key));

这是我用来尝试插入和检索的 java 代码:

package me.example;

import com.datastax.driver.core.Cluster;
import com.datastax.driver.mapping.Mapper;
import com.datastax.driver.mapping.MappingManager;
import com.datastax.driver.mapping.annotations.Frozen;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.datastax.driver.mapping.annotations.Table;
import com.datastax.driver.mapping.annotations.UDT;

public class Main {

    public static void main(String[] args) {
        try (Cluster cluster = Cluster.builder().addContactPoint("127.0.0.1")
                .build()) {
            Mapper<MyClass> mapper = new MappingManager(cluster.newSession())
                    .mapper(MyClass.class);

            MyDataType value = new MyDataType();
            value.setValue("theValue");

            MyDataType key = new MyDataType();
            key.setValue("theKey");

            MyClass myClass = new MyClass();
            myClass.setKey(key);
            myClass.setValue(value);

            mapper.save(myClass);

            MyClass toret = mapper.get(key);
            System.out.println(toret.getKey());
            System.out.println(toret.getValue().getValue());
        }
    }

    @Table(keyspace = "example_keyspace", name = "my_classes")
    public static class MyClass {
        @PartitionKey
        @Frozen
        private MyDataType key;

        @Frozen
        private MyDataType value;

        public MyDataType getKey() {
            return key;
        }

        public void setKey(MyDataType key) {
            this.key = key;
        }

        public MyDataType getValue() {
            return value;
        }

        public void setValue(MyDataType value) {
            this.value = value;
        }

    }

    @UDT(keyspace = "example_keyspace", name = "my_data_type")
    public static class MyDataType {

        private String value;

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((value == null) ? 0 : value.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (!(obj instanceof MyDataType)) {
                return false;
            }
            MyDataType other = (MyDataType) obj;
            if (value == null) {
                if (other.value != null) {
                    return false;
                }
            } else if (!value.equals(other.value)) {
                return false;
            }
            return true;
        }
    }

}

一个select表示对象插入成功:

select * from my_classes;

产量:

     key               | value
-------------------+---------------------
 {value: 'theKey'} | {value: 'theValue'}

但是我的 eclipse 控制台输出错误:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Exception in thread "main" com.datastax.driver.core.exceptions.InvalidTypeException: Invalid value for CQL type frozen<example_keyspace.my_data_type>, expecting class com.datastax.driver.core.UDTValue but class me.example.Main$MyDataType provided
    at com.datastax.driver.core.DataType.serialize(DataType.java:619)
    at com.datastax.driver.mapping.Mapper.getQuery(Mapper.java:320)
    at com.datastax.driver.mapping.Mapper.get(Mapper.java:342)
    at me.example.Main.main(Main.java:31)

我也试过使用 UDTValue 对象作为检索对象的键,但我仍然遇到同样的错误。

我在 OS X 10.10.4 上 运行 cassandra 2.1.7。 Java 版本为 1.8.0_45。 Datastax java 驱动核心和映射器是版本 2.1.6.

谢谢!

这是驱动程序中的错误。我在我们的问题跟踪器中创建了 JAVA-831

同时,您可以使用以下解决方法:

MappingManager manager = new MappingManager(cluster.newSession());
UDTMapper<MyDataType> myDataTypeMapper = manager.udtMapper(MyDataType.class);

UDTValue keyAsUDTValue = myDataTypeMapper.toUDT(key);
MyClass toret = mapper.get(keyAsUDTValue);