2

下面是我们的实体类


  @Entity(defaultKeyspace = CASSANDRA_KEYSPACE)
  @CqlName(CASSANDRA_TABLE)
  public static class Scientist implements Serializable {

    @CqlName("person_name")
    public String name;

    @Computed("writetime(person_name)")
    @CqlName("name_ts")
    public Long nameTs;

    @CqlName("person_id")
    @PartitionKey
    public Integer id;

    public Scientist() {}

    public Scientist(int id, String name) {
      super();
      this.id = id;
      this.name = name;
    }

    public Integer getId() {
      return id;
    }

    public void setId(Integer id) {
      this.id = id;
    }


    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    @Override
    public String toString() {
      return id + ":" + name;
    }

    @Override
    public boolean equals(@Nullable Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      Scientist scientist = (Scientist) o;
      return id.equals(scientist.id) && Objects.equal(name, scientist.name);
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(name, id);
    }
  }

  @Dao
  public interface ScientistDao {
  @GetEntity
  MappedAsyncPagingIterable<Scientist> map(AsyncResultSet resultSet);

  @Delete
  CompletionStage<Void> deleteAsync(Scientist entity);

  @Insert
  CompletionStage<Void> saveAsync(Scientist entity);
}

面临的问题是,当计算字段(在上述情况下为 writetime(person_name) )未被选为查询的一部分时,映射将失败。

在 3.x 驱动程序中:忽略 ResultSet 中不存在的映射字段。关联

在 4.x 驱动程序中:对于每个实体字段,数据库表或 UDT 必须包含具有相应名称的列。关联

请提出一个可能的解决方案/解决方法,其中此计算字段可以根据需要成为查询的一部分,并且映射成功发生而不会引发 IllegalArgumentException。

编辑:

科学家表模式

CREATE TABLE beam_ks.scientist (person_id int PRIMARY KEY,person_name text);

以下是尝试的查询:

   select person_id,writetime(person_name) as name_ts from beam_ks.scientist where person_id=10

使用 @GetEntity 映射结果集失败并出现以下错误:

Caused by: java.lang.IllegalArgumentException: person_name is not a column in this row
    at com.datastax.oss.driver.internal.core.cql.DefaultRow.firstIndexOf(DefaultRow.java:110)
    at com.datastax.oss.driver.api.core.data.GettableByName.get(GettableByName.java:144)
    at org.apache.beam.sdk.io.cassandra.CassandraIOTest_ScientistHelper__MapperGenerated.get(CassandraIOTest_ScientistHelper__MapperGenerated.java:89)

在 CassandraIOTest_ScientistHelper__MapperGenerated 中获取方法:

  @Override
  public CassandraIOTest.Scientist get(GettableByName source) {
    CassandraIOTest.Scientist returnValue = new CassandraIOTest.Scientist();

    Integer propertyValue = source.get("person_id", Integer.class);
    returnValue.setId(propertyValue);

    String propertyValue1 = source.get("person_name", String.class);
    returnValue.setName(propertyValue1);
    return returnValue;
  }

此外,文档没有指定是否为计算值添加 getter 和 setter 方法。因此,它们从实体类中删除

4

1 回答 1

0

使用@GetEntity方法时,您有责任提供与实体定义 100% 兼容的结果集对象。

在这里,您的Scientist实体包含两个常规字段:(person_id整数)和person_name(文本)。因此,您的结果集必须包含(至少)两列具有这些名称和类型的列。

但是您说您提供了以下查询:select person_id,writetime(person_name) as name_ts from beam_ks.scientist where person_id=10.

此查询不包含所需的列。您应该将查询更改为以下查询或类似内容:

select person_id, person_name from beam_ks.scientist where person_id=10

请注意,@GetEntity方法不识别计算值,仅识别常规值。没有必要包含writetime(person_name) as name_ts,它无论如何都不会被映射。

于 2021-04-19T11:39:05.590 回答