Skip to content

Allow custom composite converters to delete decomposed properties. #2280

Closed
@shayantabrizi

Description

@shayantabrizi

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.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions