Spring Data Cassandra:如何使用复合键查询表?

时间:2017-06-10 02:15:33

标签: java spring cassandra spring-data 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)抛出异常,可能是因为它返回了多个结果。我怎样才能解决这个问题?此外,如何检索特定日期的所有结果?

4 个答案:

答案 0 :(得分:7)

有两个选项可以用Spring Data Cassandra表示复合键:

  1. 在域类型中使用@PrimaryKeyColumn(与您一样)。
  2. 使用@PrimaryKeyClass表示主键并将其嵌入域类型中。
  3. Spring Data存储库接受单个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(…))
    

答案 1 :(得分:1)

只需在RequestEventRepository中创建其他查询方法。

@Repository
public interface RequestEventRepository extends CrudRepository<RequestEvent, LocalDateTime> {
    List<RequestEvent> findAllByDayRequested(LocalDateTime day);
    RequestEvent findOneByDayRequestedAndDateRequested(LocalDateTime day, LocalDateTime localDateTime);
}

答案 2 :(得分:0)

如果要按键类的分区键进行搜索 那么您需要在存储库接口中添加新方法 新方法的名称将遵循此约定

// {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);

答案 3 :(得分:0)

我想补充一下,spring-data-cassandra的最新版本包括一个新的存储库接口,从而无需在主存储库接口中指定Primary KeysMapId

使用MapIdCassandraRepository代替CassandraRepository

public interface MyTableRepository extends MapIdCassandraRepository<MyTable> {
}

如您在上面的代码中所见,扩展MapIdCassandraRepository接口仅需要指示所需的表。

参考: https://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#cassandra.migration