Cassandra Spring Data doesn't let me query data by composite primary key directly
Asked Answered
H

4

5

I am trying to use Spring Data Cassandra using Composite primary key class. But when I try to query data I get an exception:

org.springframework.data.repository.query.QueryCreationException: **Could not create query for public abstract java.util.List com.amdocs.cassandrapoc.repository.ServiceRepository.findByKey(com.amdocs.cassandrapoc.entities.Key)! Reason: Cannot use composite primary key directly. Reference a property of the composite primary key**

This is my code:

@PrimaryKeyClass
public class Key implements Serializable {

   @PrimaryKeyColumn(name = "id", ordinal = 0, type = 
      PrimaryKeyType.PARTITIONED)
   @CassandraType(type = DataType.Name.UUID)
      private UUID id;
   @PrimaryKeyColumn(name = "tenant", ordinal = 1, type = 
      PrimaryKeyType.PARTITIONED)
   @CassandraType(type = DataType.Name.TEXT)
      private String tenant;
  (Equals, hashcode, getters, setters omitted)
}

Table(value = "service")
public class Service implements Serializable {
   @PrimaryKey
   private Key key;

   @Column
   private String value;
   (constructors, setters, getters omitted)
}

@Repository
public interface ServiceRepository extends CassandraRepository<Service, Key> {

    List<Service> findByKey(Key key);

}

This is how I create table (using embedded Cassandra and junit):

@Autowired
private CassandraAdminOperations adminTemplate;
private final String DATA_TABLE_NAME = "service";

@Before
public void createTable() {
    adminTemplate.createTable(
            true, CqlIdentifier.of(DATA_TABLE_NAME),
            Service.class, new HashMap<String, Object>());
}

What did I do wrong?

Holguin answered 25/4, 2018 at 14:47 Comment(6)
can you add the table definition?Tondatone
I use embedded Cassandra and I create table every time in Junit using Service class structure: private CassandraAdminOperations adminTemplate; private final String DATA_TABLE_NAME = "service"; private final String TENANT = "Test"; @Before public void createTable() { adminTemplate.createTable( true, CqlIdentifier.of(DATA_TABLE_NAME), Service.class, new HashMap<String, Object>()); }Holguin
I edited my original message for a better formattingHolguin
And also I checked with not embedded Cassandra CREATE TABLE service ( id uuid, tenant text, value blob, PRIMARY KEY ((id, tenant))); The same resultHolguin
I tried to use standard method from CrudRepository Interface findById(Key key) and it works now.Holguin
Cannot use composite primary key directly is currently a limitation of how query mapping is implemented. Looking at your code you could expect exact property matching. There are a lot of other possibilities (findByKeyGreaterThan, findByKeyIn, dealing with null properties in your key) which raise a couple of questions how to deal with these possibilities. Care to file a ticket at jira.spring.io/browse/DATACASS so we can continue the discussion in our issue tracker?Distributive
P
7

I faced same issue. I got it resolved in my case with below implementation.

@Repository
public interface ServiceRepository extends CassandraRepository<Service, Key> {

    List<Service> findByKeyIdAndKeyTenant(UUID id, String tenant);

}
Punctilio answered 30/4, 2019 at 3:28 Comment(0)
S
1

Try to use CrudRepository instead of CassandraRepository:

Repositories based on CassandraRepository can define either a single primary key, use a primary key class or a compound primary key without a primary key class. Types using a compound primary key without a primary key class must use MapId to declare their key value.

Source: https://docs.spring.io/spring-data/cassandra/docs/current/api/org/springframework/data/cassandra/repository/CassandraRepository.html

Sennet answered 26/4, 2018 at 13:48 Comment(1)
It would help if you would add an example with MapId.Yawp
P
1

I encounter the same issue, but solve using the following implementation style.

@Repository
public interface ServiceRepository extends CassandraRepository<Service, Key> {

    List<Service> findByKeyTent(Key key);
    // findBy{PrimaryKey}{PrimaryKeyColumn} format
}
Postbellum answered 1/8, 2019 at 7:4 Comment(0)
C
-1

I was facing same issue. This was resolved by defining Cassandra Configuration by using AbstractCassandraConfiguration provided with Cassandra spring framework .

@Configuration
@EnableCassandraRepositories(basePackages = "A.B.Z")  // package location of repository
@ComponentScan(value = "X.Y.X")  // enable autowire
public class CassandraConfiguration extends AbstractCassandraConfiguration {

    public String getContactPoints() {
        return "HOTNAME OF CASSANDRA CLUSTER"; // your cluster host 
    }

    @Override
    protected int getPort() {
        return 9042; //default port
    }

    @Override
    protected String getKeyspaceName() {
        return "YOUR KEY SPACE NAME";  // Cassandra Keyspace Name
    }

}
Conventionality answered 12/12, 2018 at 17:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.