【问题标题】:Cassandra 4.5 driver issue with @Entity and Counter fields带有 @Entity 和 Counter 字段的 Cassandra 4.5 驱动程序问题
【发布时间】:2020-07-14 12:44:26
【问题描述】:

4.5 Datastax Cassandra 驱动程序有问题。我无法让这些@Queries 中的任何一个工作:

@Dao
public interface SampleTable2Dao extends BaseDao<SampleTable2> {
    //@Query("UPDATE sampletable2 SET cntrfld = cntrfld + :toAdd WHERE key1 = :key1Value AND key2 = :key2Value AND key3 = :key3Value")
    @Query("UPDATE sampletable2 SET cntrfld = cntrfld + 1 WHERE key1 = 1 AND key2 = 1 AND key3 = 1;")
    CompletableFuture<Void> addCountAsync(int toAdd, int key1Value, int key2Value, int key3Value);

    @Query("UPDATE sampletable2 SET cntrfld = cntrfld + 1 WHERE key1 = 1 AND key2 = 1 AND key3 = 1;")
    void addCount(int toAdd, int key1Value, int key2Value, int key3Value);

    @Query("UPDATE sampletable2 SET cntrfld = cntrfld + 1 WHERE key1 = 1 AND key2 = 1 AND key3 = 1;")
    void addCount();

它只是挂起: getSampleTable2Dao().addCount();

查询直接在 Cassandra 中运行良好。

谢谢

附:这是任何人都想测试的表格:

CREATE TABLE sampletable2 (
    key1 int,
    key2 int,
    key3 int,
    cntrfld counter,
    PRIMARY KEY (key1, key2, key3)
);

更新 #1

经过一番挖掘,我发现它挂在生成的代码中。与实际查询无关:

this.sampleTable2DaoCache = new LazyReference<>(() -> SampleTable2DaoImpl__MapperGenerated.init(context));

  @Override
  public SampleTable2Dao sampleTable2Dao() {
    return sampleTable2DaoCache.get();
  }

我正在逆向工作,直到我可以让它工作为止。其他 DAO 工作正常 - 唯一的区别是计数器字段。

更新#2...“真正的”问题根本不是@Query...而是带有计数器字段的@Entity。

@CqlName("cntrfld")
private Long cntrFld;

如果此字段是 Cassandra (3.11.4 btw) 中的计数器,则代码将挂起。如果我将字段设置为 bigint,它就可以正常工作!

【问题讨论】:

  • 它对我有用。你是如何建立你的会话的?一个潜在的问题是查询字符串中没有键空间,因此您的会话需要有一个默认值 (CqlSession.builder().withKeyspace(...))。但仍然缺少键空间应该产生错误,而不是挂起。
  • 这不是问题...没有键空间我无法连接...它可以连接。我还有另一个 dao 工作得很好。
  • 我试过4.5.1,还是坏了。我处于静止状态......似乎我不能在映射器中使用计数器字段。

标签: java cassandra cassandra-driver


【解决方案1】:

我认为您正在尝试将 @Insert@Update 与计数器列一起使用。这不行:counters 是一种特殊类型的列,它们只支持递增或递减操作。

您可以使用实体进行读取或删除操作。但是对于更新,@Query 是您目前唯一的选择:

@Entity @CqlName("sampletable2")
public class SampleTable2 {
  @PartitionKey private int key1;
  @ClusteringColumn(1) private int key2;
  @ClusteringColumn(2) private int key3;
  private long cntrfld;
  // getters and setters...
}

@Dao
public interface SampleTable2Dao {
  @Select
  SampleTable2 get(int key1, int key2, int key3);

  @Delete
  void delete(SampleTable2 entity);

  @Query(
      "UPDATE sampletable2 SET cntrfld = cntrfld + 1 "
          + "WHERE key1 = :key1 AND key2 = :key2 AND key3 = :key3")
  void increment(int key1, int key2, int key3);

  // THIS WON'T WORK:
  // @Insert
  // void insert(SampleTable2 entity);
}

诚然,我们可以更好地支持映射器中的计数器。我认为这样的事情可能会奏效:

  @Increment
  void increment(SampleTable2 entity);

我创建了JAVA-2721 来探索这个想法。

【讨论】:

  • 实际上...我的 BaseDao 确实有一个插入...也许就是这样。我会尝试删除它。它应该抛出一个错误,而不是永远挂起。只是一个想法。 ;)
  • 我喜欢@Increment 的想法。但是,您需要能够控制要增加的数字。 IE。 @Increment void increment(SampleTable2 entity, long delta);或者,您是否会让代码在调用之前将增量编号放入实体变量字段中?
  • 是的,我们必须稍微改进一下 API:不同的增量(包括负数)、多个计数器等。
【解决方案2】:

错误是,我的@Dao 有一个@Insert,但表使用了计数器字段类型。一旦我删除了@Insert,系统就会工作。

我按照帮助创建了一个 BaseDao 类,其中包含重复的 @Insert 和 @Delete 方法集,因此我看不出我哪里错了。

库应该在这种情况下抛出错误,而不仅仅是挂起......我认为这是库中的一个错误。

【讨论】:

  • 当我从映射器获取 DAO 时,我遇到了一个错误:com.datastax.oss.driver.api.core.servererrors.InvalidQueryException: INSERT statements are not allowed on counter tables, use UPDATE instead。可能还有其他事情发生,尝试调试一下。
猜你喜欢
  • 2016-10-02
  • 1970-01-01
  • 2019-08-01
  • 2018-02-17
  • 2022-08-08
  • 2017-03-21
  • 1970-01-01
  • 1970-01-01
  • 2013-08-30
相关资源
最近更新 更多