我正在使用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'字段来标记它不能为空?任何线索都表示赞赏。谢谢。
答案 0 :(得分:4)
Cassandra将空集合存储为null
,Spring Data Cassandra会覆盖初始化字段。
Cassandra list / set typed columns将空集合表示为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;
}
答案 1 :(得分:1)
作为mp911de的重要补充,您必须设置@org.springframework.data.annotation.AccessType(AccessType.Type.PROPERTY)
才能使此解决方案正常运行。