【问题标题】:Spring Data Cassandra: How to query tables with compound keys?Spring Data Cassandra:如何使用复合键查询表?
【发布时间】:2017-11-12 03:02:17
【问题描述】:

我有以下列族:

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

【问题讨论】:

    标签: java spring cassandra spring-data spring-data-cassandra


    【解决方案1】:

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

    使用MapIdCassandraRepository 代替CassandraRepository

    public interface MyTableRepository extends MapIdCassandraRepository<MyTable> {
    }
    
    

    从上面的代码可以看出,扩展MapIdCassandraRepository接口只需要指明你想要的Table即可。

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

    【讨论】:

      【解决方案2】:

      如果你想按你的键类的分区键搜索 那么你需要在 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);
      

      【讨论】:

        【解决方案3】:

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

        1. 在域类型中使用@PrimaryKeyColumn(就像您所做的那样)。
        2. 使用@PrimaryKeyClass 表示主键并将其嵌入到域类型中。

        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(…))
        

        【讨论】:

        • 查询方法名中需要包含属性路径。对于上面的示例,它将是 findAllByKeyDayRequested(…)
        • 而且Spring还提供了MapIdCassandraRepository
        【解决方案4】:

        只需在 RequestEventRepository 中创建额外的查询方法。

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

        【讨论】:

          猜你喜欢
          • 2016-03-25
          • 2021-12-27
          • 2017-05-13
          • 1970-01-01
          • 2018-10-06
          • 2014-07-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多