Saving node without updating node in relationship?

Hi, I'm new to Neo4J

In my app I have those entities :

 @NodeEntity
 public class ManagedList {
     @Id
     @GeneratedValue()
     private Long id;
 
     private String name;
 
     @Relationship(type = "CONTAINS")
     private List<ListElement> listElement;
 
}
 
 @NodeEntity
 public class ListElement {
     @Id
     @GeneratedValue()
     private Long id;
 
     private int elementOrder;
 
     @Relationship(type = "CONTAINS", direction = Relationship.INCOMING)
     private ManagedList managedList;
 }

When I add a new ListElement to a ManagedList with my WS, the ListElement in the JSON only has the ManagedList id, not the full object (to avoid sending unecessary informations). So when this JSON is mapped into a ListElement entity, nested ManagedList object only has its id, the other properties like name are == null.

Previously my app used to work with Mysql, and when I saved ListElement this way, it was correctly associated with ManagedList, and ManagedList object still has his name in DB (ManagedList object was not updated in any way in DB when I saved ListElement , no matter what has changed in its properties).

But now with Neo4J DB, when I save ListElement, it also updates the ManagedList object and set the name to null.

Is there any way to specify that when I save ListElement I don't want to update ManagedList, but only use ManagedList id to associate them, like it uses to happen in Mysql? Or this is impossible and I must first get the ManagedList object with the id, set it into my ListElement, and then save?

Many thx

I recommend reading this relevant section of the OGM docs: Reference - OGM Library

Short version: I don't think there's a way to exactly accomplish what you want, but the OGM session is smart enough to know that you haven't changed the ManagedList, so if you can load the full ManagedList once and attach it to the ListElements, saving new ListElements will not re-save ManagedList's properties (as far as I understand it)

In JPA cascade types was helping but I am searching similar functionality on Neo4j. I am handling it with writing cypher, however complex objects makes it unpleasant.

There is something upcoming for Spring Data Neo4j 6.1 that solves this problem: Projection based persistence.
This means only properties (and relationships) will get touched on save that are declared as part of the projection.
We have this already in the main branch:

2 Likes

Thank you for wonderful news. I changed the version 6.1.0 to try this out.
I tried with neo4jTemplate

private ReactiveNeo4jTemplate neo4jTemplate;

Mono<Production> productionMono = neo4jTemplate.save(production);

But it does not work, it overwrites all relation data.

My nodes;

@Node("Production")
@Data
public class Production {
    @Id
	@GeneratedValue(UUIDStringGenerator.class)
	private String identity;

	@Builder.Default
	@Relationship(type = "GENRE_BASED", direction = Direction.OUTGOING)
	private List<ProductionGenre> genres = new ArrayList<>();
}

@Node("ProductionGenre")
@Data
public class ProductionGenre {
	@Id
	@GeneratedValue
	private Long identity;
	
	@Builder.Default
	@Relationship(type = "TRANSLATED_IN", direction = Direction.OUTGOING)
	private List<Translation> names = new ArrayList<>();
}

Normally I was using ReactiveNeo4jRepository but it is also overwriting the data. Can it be related with reactive?

Please be aware that you have to also supply a projection to the template's save method.

neo4jTemplate.saveAs(p, OpenProjection.class);

^^ taken from the example above.
The template describes the limited view on the entity that you want to persist. SDN will than take just its defined properties for the update/save.

I think there is a misunderstanding, I want create relationship between nodes without saving (updating) all nodes.
In my example; I have already saved genres and I am trying to save production with genre relationship only using id of genre. It this case it overwrites genre objects.

Is there any solution to avoid that without writing any cypher?

If you want to do this without any Cypher, you would have at least to fetch all ProductionGenres on the Production to add (or remove) others.
This is needed because SDN does not know about the relationships on Production when you save just with the new one. It assumes strict, that the Java model represents the Graph model and this moment (projections aside). So it will remove the existing relationships first.
And yes, when it processes the relationships it will update the related nodes also.
Because there is no "deep / multi-level projection" and only first level supported, it will also touch the Translations.