Spring Data Cassandra: как запрашивать таблицы с составными ключами?
У меня есть следующее семейство столбцов:
@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;
...
}
который хранится и доступен в хранилище:
@Repository
public interface RequestEventRepository extends CrudRepository<RequestEvent, LocalDateTime> {
}
к несчастью requestEventRepository.findOne(localDate)
генерирует исключение, вероятно, потому что возвращает несколько результатов. Как я могу это исправить? Кроме того, как можно получить все результаты за определенный день?
2 ответа
У вас есть два варианта представления составных ключей в Spring Data Cassandra:
- С помощью
@PrimaryKeyColumn
в типе домена (как вы сделали). - Используя
@PrimaryKeyClass
представлять первичный ключ и встраивать его в тип домена.
Репозитории Spring Data допускают использование одного ID
тип. Поэтому невозможно просто объявить LocalDateTime
как идентификатор Если вы хотите придерживаться @PrimaryKeyColumn
внутри типа домена, использование MapId
как тип идентификатора:
@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);
Если вы решили представить свой первичный ключ как объект значения, то вам нужно немного изменить тип своего домена:
@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(…))
Я просто хотел бы добавить, что последние версии spring-data-cassandra включают новый интерфейс репозитория, который устраняет необходимость указывать
Primary Keys
или же
MapId
в главном интерфейсе репозитория.
Использовать
MapIdCassandraRepository
вместо
CassandraRepository
:
public interface MyTableRepository extends MapIdCassandraRepository<MyTable> {
}
Как вы можете видеть в приведенном выше коде, расширение
MapIdCassandraRepository
интерфейс требует только указать желаемую таблицу.
Ссылка:https://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#cassandra.migration
Просто создайте дополнительные методы запроса в RequestEventRepository.
@Repository
public interface RequestEventRepository extends CrudRepository<RequestEvent, LocalDateTime> {
List<RequestEvent> findAllByDayRequested(LocalDateTime day);
RequestEvent findOneByDayRequestedAndDateRequested(LocalDateTime day, LocalDateTime localDateTime);
}
Если вы хотите выполнить поиск по ключу раздела вашего ключевого класса, вам необходимо добавить новый метод в интерфейс репозитория. Новое имя метода будет соответствовать этому соглашению.
//{MethodName}{PrimaryKeyClassName}{PrimaryKeyColumn}
ПРИМЕР:
@PrimaryKeyClass
public class UserKey implements Serializable {
private static final long serialVersionUID = 1L;
@PrimaryKeyColumn(name = "email", type = PrimaryKeyType.PARTITIONED)
private String email;
@PrimaryKeyColumn(name = "firstname", ordinal = 0, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING)
private String firstName;
@PrimaryKeyColumn(name = "lastname", ordinal = 1, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.ASCENDING)
private String lastName;
//equals and hashcode methods
}
Тогда имя метода будет
User findByUserKeyEmail(String email);