无法通过UDT键从具有datastax java驱动程序的cassandra检索 [英] Can't retrieve by UDT key from cassandra with datastax java driver

查看:592
本文介绍了无法通过UDT键从具有datastax java驱动程序的cassandra检索的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将用户定义类型的对象存储在cassandra中作为分区键。我使用datastax java驱动程序对象映射,虽然我能够插入到数据库,我无法检索对象。如果我更改分区键以使用非udt(如文本),我能够保存和检索(即使对象有相同类型的其他udt)。从阅读文档看,UDTs被允许作为键。我也没有能够找到任何迹象表明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代码:

 包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;
export 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 .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 * from my_classes; 

产生:

 code> key |值
------------------- + ---------------------
{value:'theKey'} |但是我的eclipse控制台输出了一个错误:

$ {$ value:'theValue'}


$ b b
$ b

  SLF4J:无法加载类org.slf4j.impl.StaticLoggerBinder。 
SLF4J:默认为无操作(NOP)记录器实现
SLF4J:有关详细信息,请参阅http://www.slf4j.org/codes.html#StaticLoggerBinder。
线程main中的异常com.datastax.driver.core.exceptions.InvalidTypeException:CQL类型冻结< example_keyspace.my_data_type>的无效值,期望类com.datastax.driver.core.UDTValue,但类me.example .Main $ MyDataType提供
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驱动程序核心和mapper是版本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);


I'm trying to store objects in cassandra with a user defined type as the partition key. 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. 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). From reading the documentation it appears that UDTs are allowed as keys. I've also not been able to find any indication that the java driver doesn't support udts as keys either. It looks like it is failing during the mapping of the object, but only when the UDT is the partition key.

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:

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:

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:

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.

I am running cassandra 2.1.7 on OS X 10.10.4. Java version is 1.8.0_45. Datastax java driver core and mapper are version 2.1.6.

Thanks!

解决方案

This is a bug in the driver. I've created JAVA-831 in our issue tracker.

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

这篇关于无法通过UDT键从具有datastax java驱动程序的cassandra检索的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆