Description
In this code, Person has an attribute source:
@CompositeProperty(converter = SourceConverter.class)
Source source;
In "AService", I save a person having source, then make the source null and save it again. After retrieving the person from the database, the source attribute still has its previous value. I guess that when the updated object is saved, Neo4jPersistentPropertyToMapConverter does not add the converted attributes but the attributes are there from the previous save and no one deletes them. I checked this in a code with SDN+OGM (in which I used CompositeAttributeConverter). It seems that in there, the node didn't have the attributes. Maybe in SDN+OGM all the attributes not generated when converting the updated node were removed, but in the new version it keeps the attributes.
Here is the sample code:
template.deleteAll(Person.class);
Person person = template.save(new Person("John", new Source("123", "john-smith", 280L)));
person.setSource(null);
person.setName("Jack");
Person updatedPerson = template.save(person);
System.out.println("The updated person: " + updatedPerson.getName() + " " + updatedPerson.getSource() + " " +(updatedPerson.getSource() != null ? updatedPerson.getSource().getUserId() : null));
Person savedPerson = template.findById(updatedPerson.getId(), Person.class).get();
System.out.println("The found person: " + savedPerson.getName() + " " + savedPerson.getSource() + " " +(savedPerson.getSource() != null ? savedPerson.getSource().getUserId() : null));
and here is the converter code
public static class SourceConverter implements Neo4jPersistentPropertyToMapConverter<String, Source> {
@Override
public Source compose(Map<String, Value> map, Neo4jConversionService neo4jConversionService) {
Value userId = map.get("source_userId");
Value userName = map.get("source_userName");
Value size = map.get("source_size");
if (userId != null || userName != null || size != null) {
return new Source(
userId != null ? userId.asString() : null,
userName != null ? userName.asString() : null,
size != null ? size.asLong() : null
);
} else {
return null;
}
}
@Override
public Map<String, Value> decompose(Source source, Neo4jConversionService neo4jConversionService) {
Map map = new LinkedHashMap<>();
if (source != null) {
map.put("source_userId", source.getUserId() != null ? Values.value(source.getUserId()) : NullValue.NULL);
map.put("source_userName", source.getUserName() != null ? Values.value(source.getUserName()) : NullValue.NULL);
map.put("source_size", source.getSize() != null ? Values.value(source.getSize()) : NullValue.NULL);
}
return map;
}
}
And here is the result:
The updated person: Jack null null
The found person: Jack com.neo4j.sdn.Source@b20c47e2 123
How should we handle that? The updated object doesn't have a source but what I get the object from database with a source inside it.