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

时间:2016-04-01 06:56:54

标签: 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 = []
}

在我的测试用例中,我碰巧在调用CassandraOperations.insert(entity)之前只设置了一些像'id'和'updated'这样的字段,所以在插入时它们中的大部分都是null。但是numberList字段不是null,它是一个空List。在insert()之后,我正在调用CassandraOperations.selectOneById(FooData.class,id)。我得到了一个FooData实例,当我保存它时初始化的字段填充了数据。但是,我在我的测试中检查了内容相等性,并且失败了,因为空列表没有返回到从CassandraOperations.selectOneById()返回的POJO中的空列表。它实际上是空的。我假设这可能是某种Cassandra优化。它似乎发生在实例化POJO /实体的CGLIB代码中。这是一个众所周知的“功能”吗?是否有一些注释我可以用'numberList'字段来标记它不能为空?任何线索都表示赞赏。谢谢。

2 个答案:

答案 0 :(得分:4)

简而言之

Cassandra将空集合存储为null,Spring Data Cassandra会覆盖初始化字段。

说明

Cassandra list / set typed columns将空集合表示为null。列表/集(从Java / Groovy查看)是空的还是null并不重要。因此,存储空列表会在null中生成。从这里可以判断状态是null还是在保存值时为空。

Insert empty list

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; }

答案 1 :(得分:1)

作为mp911de的重要补充,您必须设置@org.springframework.data.annotation.AccessType(AccessType.Type.PROPERTY)才能使此解决方案正常运行。