Spring Data Cassandra:如何使用复合键查询表?
Spring Data Cassandra: How to query tables with compound keys?
我有以下列族:
@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)
抛出异常,可能是因为它返回了多个结果。我怎样才能解决这个问题?另外,如何检索特定日期的所有结果?
只需在 RequestEventRepository 中创建额外的查询方法。
@Repository
public interface RequestEventRepository extends CrudRepository<RequestEvent, LocalDateTime> {
List<RequestEvent> findAllByDayRequested(LocalDateTime day);
RequestEvent findOneByDayRequestedAndDateRequested(LocalDateTime day, LocalDateTime localDateTime);
}
您有两个选项可以用 Spring Data Cassandra 表示复合键:
- 在域类型中使用
@PrimaryKeyColumn
(就像您所做的那样)。
- 使用
@PrimaryKeyClass
表示主键并将其嵌入到域类型中。
Spring 数据存储库接受单一 ID
类型。因此不可能只将 LocalDateTime
声明为 id。如果要在域类型中坚持使用 @PrimaryKeyColumn
,请使用 MapId
作为 id 类型:
@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(…))
如果你想按你的键的分区键搜索class
那么你需要在Respository Interface中添加一个新方法
新方法名称将遵循此约定
//{方法名}{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);
我只想补充一点,最新版本的 spring-data-cassandra 包含一个新的存储库界面,无需在主存储库界面中指定 Primary Keys
或 MapId
。
使用MapIdCassandraRepository
代替CassandraRepository
:
public interface MyTableRepository extends MapIdCassandraRepository<MyTable> {
}
在上面的代码中可以看到,扩展MapIdCassandraRepository
接口只需要指明你想要的Table。
参考:
https://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#cassandra.migration
我有以下列族:
@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)
抛出异常,可能是因为它返回了多个结果。我怎样才能解决这个问题?另外,如何检索特定日期的所有结果?
只需在 RequestEventRepository 中创建额外的查询方法。
@Repository
public interface RequestEventRepository extends CrudRepository<RequestEvent, LocalDateTime> {
List<RequestEvent> findAllByDayRequested(LocalDateTime day);
RequestEvent findOneByDayRequestedAndDateRequested(LocalDateTime day, LocalDateTime localDateTime);
}
您有两个选项可以用 Spring Data Cassandra 表示复合键:
- 在域类型中使用
@PrimaryKeyColumn
(就像您所做的那样)。 - 使用
@PrimaryKeyClass
表示主键并将其嵌入到域类型中。
Spring 数据存储库接受单一 ID
类型。因此不可能只将 LocalDateTime
声明为 id。如果要在域类型中坚持使用 @PrimaryKeyColumn
,请使用 MapId
作为 id 类型:
@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(…))
如果你想按你的键的分区键搜索class 那么你需要在Respository Interface中添加一个新方法 新方法名称将遵循此约定
//{方法名}{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);
我只想补充一点,最新版本的 spring-data-cassandra 包含一个新的存储库界面,无需在主存储库界面中指定 Primary Keys
或 MapId
。
使用MapIdCassandraRepository
代替CassandraRepository
:
public interface MyTableRepository extends MapIdCassandraRepository<MyTable> {
}
在上面的代码中可以看到,扩展MapIdCassandraRepository
接口只需要指明你想要的Table。
参考: https://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#cassandra.migration