Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data Cassandra: How to query tables with compound keys?

I have the following column family:

@Table(value = "request_event")
public class RequestEvent {

    @PrimaryKeyColumn(name = "day_requested", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
    private LocalDate dayRequested;

    @PrimaryKeyColumn(name = "date_requested", ordinal = 1, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING)
    private LocalDateTime dateRequested;

    ...
}

which is stored and accessed by a repository:

@Repository
public interface RequestEventRepository extends CrudRepository<RequestEvent, LocalDateTime> {
}

Unfortunately requestEventRepository.findOne(localDate) is throwing an exception, probably because it is returning multiple results. How can I fix this? Also, how can all results from a particular day be retrieved?

like image 558
cscan Avatar asked Dec 10 '22 11:12

cscan


1 Answers

You have two options to represent compound keys with Spring Data Cassandra:

  1. Using @PrimaryKeyColumn within the domain type (like you did).
  2. Using a @PrimaryKeyClass to represent the primary key and embed it in the domain type.

Spring Data repositories accept a single ID type. Therefore it's not possible to just declare LocalDateTime as id. If you want to stick to @PrimaryKeyColumn within the domain type, the use MapId as id type:

@Table(value = "request_event")
public class RequestEvent {

    @PrimaryKeyColumn(name = "day_requested", ordinal = 0,
            type = PrimaryKeyType.PARTITIONED) 
    private LocalDate dayRequested;

    @PrimaryKeyColumn(name = "date_requested", ordinal = 1, type = PrimaryKeyType.CLUSTERED,
            ordering = Ordering.DESCENDING) 
    private LocalDateTime dateRequested;

}

public interface RequestEventRepository extends CrudRepository<RequestEvent, MapId> {}

MapId mapId = BasicMapId.id("dayRequested", …).with("dateRequested", …);

RequestEvent loaded = eventRepository.findOne(mapId);

If you decide to represent your primary key as a value object, then you need to adjust your domain type slightly:

@PrimaryKeyClass
public class Key implements Serializable {

    @PrimaryKeyColumn(name = "day_requested", ordinal = 0,
            type = PrimaryKeyType.PARTITIONED) 
    private LocalDate dayRequested;

    @PrimaryKeyColumn(name = "date_requested", ordinal = 1, type = PrimaryKeyType.CLUSTERED,
            ordering = Ordering.DESCENDING) 
    private LocalDateTime dateRequested;

}

@Table(value = "request_event")
public class RequestEvent {

    @PrimaryKey 
    private Key key;

}

public interface RequestEventRepository extends CrudRepository<RequestEvent, Key> {}

eventRepository.findOne(new Key(…))
like image 166
mp911de Avatar answered Mar 06 '23 16:03

mp911de