简体   繁体   English

无法使用带有datastax java驱动程序的cassandra通过UDT键检索

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

I'm trying to store objects in cassandra with a user defined type as the partition key. 我正在尝试使用用户定义的类型作为分区键在cassandra中存储对象。 I am using the datastax java driver for object mapping, and while I am able to insert into the database, I cannot retrieve the object. 我使用datastax java驱动程序进行对象映射,虽然我能够插入数据库,但我无法检索该对象。 If I change the partition key to use a non-udt (such as text) I am able to save and retrieve (even if there are other udt of the same type on the object). 如果我更改分区键以使用非udt(例如文本),我可以保存和检索(即使对象上还有其他相同类型的udt)。 From reading the documentation it appears that UDTs are allowed as keys. 从阅读文档看来,UDT被允许作为键。 I've also not been able to find any indication that the java driver doesn't support udts as keys either. 我也没能找到任何迹象表明java驱动程序也不支持udts作为键。 It looks like it is failing during the mapping of the object, but only when the UDT is the partition key. 看起来它在对象映射期间失败,但仅当UDT是分区键时才会失败。

Is this an unsupported feature? 这是不受支持的功能吗? Do I need to only use the default types as keys when using the object mapper? 使用对象映射器时,是否只需要使用默认类型作为键? Or am I just doing something wrong? 或者我只是做错了什么?

Here are the cql commands I used to set up the database: 这是我用来设置数据库的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));

Here is the java code I used to try inserting and retrieving: 这是我用来尝试插入和检索的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;
        }
    }

}

A select shows the object was inserted successfully: 选择显示对象已成功插入:

select * from my_classes;

yields: 收益率:

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

But my eclipse console is outputting an error: 但我的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)

I've also tried using a UDTValue object as the key to retrieve the object, but I still get the same error. 我也尝试使用UDTValue对象作为检索对象的键,但我仍然得到相同的错误。

I am running cassandra 2.1.7 on OS X 10.10.4. 我在OS X 10.10.4上运行cassandra 2.1.7。 Java version is 1.8.0_45. Java版本是1.8.0_45。 Datastax java driver core and mapper are version 2.1.6. Datastax java驱动程序核心和映射器是版本2.1.6。

Thanks! 谢谢!

This is a bug in the driver. 这是驱动程序中的错误。 I've created JAVA-831 in our issue tracker. 我在我们的问题跟踪器中创建了JAVA-831

In the meantime, you can use the following workaround: 在此期间,您可以使用以下解决方法:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM