如何确保 CassandraOperations.selectOneById() 初始化 POJO 中的所有字段?

use*_*270 0 spring-data-cassandra

我正在使用 Spring Data Cassandra 1.3.4.RELEASE 来保留我拥有的类的实例。该类是用 Groovy 编写的,但我认为这并不重要。我已经实现了一个 CrudRepository,我正在将一个 CassandraOperations 实例注入到 repo 实现类中。我可以成功插入、删除和执行大多数其他操作。但是,我遇到的一个场景会破坏我的测试用例。我的实体类看起来像这样:

@Table("foo")
class FooData {
  @PrimaryKey("id")
  long id
  @Column("created")
  long updated
  @Column("name")
  String name
  @Column("user_data")
  String userData
  @Column("numbers")
  List numberList = []
}
Run Code Online (Sandbox Code Playgroud)

在我的测试用例中,我碰巧在调用 CassandraOperations.insert(entity) 之前只设置了几个字段,例如 'id' 和 'updated',因此在插入时实体实例中的大多数字段为空。但是 numberList 字段不为空,它是一个空列表。在 insert() 之后,我直接调用 CassandraOperations.selectOneById(FooData.class, id)。我得到了一个 FooData 实例,并且在我保存它时初始化的字段填充了数据。但是,我在我的测试中检查内容相等性,但它失败了,因为空列表没有作为从 CassandraOperations.selectOneById() 返回的 POJO 中的空列表返回。它实际上是空的。我认为这可能是某种 Cassandra 优化。它似乎发生在实例化 POJO/实体的 CGLIB 代码中。这是一个众所周知的“

mp9*_*1de 5

简而言之

Cassandra 将空集合存储为nullSpring Data Cassandra 覆盖已初始化的字段。

解释

Cassandra 列表/集类型列将空集合表示为null. 列表/集合(从 Java/Groovy 中查看)是空的还是null. 因此,存储空列表会产生null. 从这里我们无法判断null在保存值时状态是还是空的。

插入空列表

Spring Data Cassandra使用从结果集中检索的值覆盖所有字段,因此您的预初始化字段设置为null. 我创建了一个票证DATACASS-266来跟踪这个问题的状态。

解决方法

如果可能,Spring Data 会使用 setter,因此您有机会进行干预。一个非常简单的null守卫可能是:

public void setMyList(List<Long> myList) { if(myList == null){ this.myList = new ArrayList<>(); return; } this.myList = myList; }