Reputation: 93
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!
Upvotes: 3
Views: 2464
Reputation: 2312
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);
Upvotes: 2