How can I ensure CassandraOperations.selectOneById() initializes all fields in the POJO?

浪子不回头ぞ 提交于 2019-12-20 07:49:06

问题


I'm using Spring Data Cassandra 1.3.4.RELEASE to persist instances of a class that I have. The class is written in Groovy, but I don't think that really matters. I have implemented a CrudRepository, and I'm injecting an instance of CassandraOperations into the repo implementation class. I can insert, delete, and do most of the other operations successfully. However, there's a scenario I'm running into which breaks my test case. My entity class looks something like this:

@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 = []
}

In my test case, I happened to only set a few fields like 'id' and 'updated' before calling CassandraOperations.insert(entity), so most of them were null in the entity instance at the time of insertion. But the numberList field was not null, it was an empty List. Directly after the insert(), I'm calling CassandraOperations.selectOneById(FooData.class, id). I get a FooData instance back, and the fields that were initialized when I saved it are populated with data. However, I was checking content equality in my test, and it failed because the empty list was not returned as an empty list in the POJO coming back from CassandraOperations.selectOneById(). It's actually null. I assume this may be some sort of Cassandra optimization. It seems to happen in the CGLIB code that instantiates the POJO/entity. Is this a known "feature"? Is there some annotation I can mark the 'numberList' field with to indicate that it cannot be null? Any leads are appreciated. Thanks.


回答1:


In short

Cassandra stores empty collections as null and Spring Data Cassandra overwrites initialized fields.

Explanation

Cassandra list/set typed columns represent an empty collection as null. It does not matter whether the list/set (as viewed from Java/Groovy) was empty or null. Storing an empty list yields therefore in null. From here one can't tell whether the state was null or empty at the time saving the value.

Spring Data Cassandra overwrites all fields with values retrieved from the result set and so your pre-initialized fields is set to null. I created a ticket DATACASS-266 to track the state of this issue.

Workaround

Spring Data uses setters if possible so you have a chance to intervene. A very simple null guard could be:

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




回答2:


As important addition to mp911de answer you have to set @org.springframework.data.annotation.AccessType(AccessType.Type.PROPERTY) to make this solution work.



来源:https://stackoverflow.com/questions/36349896/how-can-i-ensure-cassandraoperations-selectonebyid-initializes-all-fields-in-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!