Datastax Cassandra - Inheritance when using object

2019-06-24 02:37发布

问题:

I try using Cassandra for persisting quite simple POJOs, but using a class hierarchy (many subclasses, one superclass). I am using Java and the Datastax driver (and the object mapper).

My problem is that the Object Mapper doesn't seem to recognize fields annotated in superclasses.

The structure I implemented is:

@Table(keyspace = "...", name = "...")
public class Subclass extends Superclass {  
    public double x;
    public double y;
    public double z;

   ....
}

public class Superclass {   
    @PartitionKey(0)
    @Column(name = "user_id")
    public long userId;

    @PartitionKey(1)
    @Column(name = "device_id")
    public long deviceId;
}

I then try to save Subclass objects:

public static void main(String[] args) {
    Subclass data = new Subclass();
    data.deviceId = 123;
    data.userId = 1212;
    data.x = 0;
    data.y = 1;
    data.z = 2;

    Cluster cluster;
    Session session;

    ...

    Mapper<Subclass> mapper = new MappingManager(session).mapper(Subclass.class);

    mapper.save(data);
}

This throws:

 com.datastax.driver.core.exceptions.InvalidQueryException: Missing mandatory PRIMARY KEY part user_id

Is there any way to get it running in a structure like this? One solution was to redeclare the userId / deviceID field in the subclass, but this would be quite ugly (much repetitive code). Any ideas how to archive a good structure or best practices for a case like this?

回答1:

Update: Inheritance is now supported by the driver as described in the question as of version 3.1.0. See Polymorphism Support section of the driver manual for more details:

When mapping an entity class or a UDT class, the mapper will transparently scan superclasses and superinterfaces for annotations on fields and getter methods, thus enabling the polymorphic mapping of one class hierarchy into different CQL tables or UDTs.

Java driver 4.1.0+ will also support inheritance for entities and daos.

Original Answer:

For the time being unfortunately you cannot do this. You would need to create two separate classes with a repetitive structure. You could create an interface with the shared fields if you want to address objects of both implementations in a common way.

There is a ticket JAVA-541 for adding support for this, please vote if you would like to see this capability in the driver.