In JPA, there's a feature where it automatically handles update and cascade operations, like removing the old foreign key relationship and setting the new one. Does Neo4j have a similar feature for handling updates and relationships? If not, why is that the case?
In Spring Boot JPA, when you call repository.save(), JPA automatically handles both saving new entities and updating existing ones. It also manages cascade operations, such as updating relationships and removing old references. Why doesn't Neo4j repositories support something similar?
I assume with Neo4j you mean Spring Data Neo4j, right?
It does. Basically it does exactly what you are describing here: save either creates new nodes and relationships and related nodes, or it updates them.
The only thing where it might differ: Removing a relationship will remove the relationship, but not the related node itself. This is because SDN cannot be sure that the node is not referenced anywhere else (or should be kept).
Let's say I have 'Device' and 'DeviceManager' nodes. Initially, I create a device with a 'DeviceManager' with id: 1. After that, I update the device to associate it with a 'DeviceManager' with id: 2.
The relationship between the device and 'DeviceManager' with id: 2 will be created, but the relationship with 'DeviceManager' id: 1 will not be deleted.
This can only happen if you haven't fetched the device first, or that SDN cannot determine if the device it is about to update, is the same device as before (this is determined by the id).
Device device =DeviceRepository.findById("1");
//Previously, device.getManager() would return the Manager with ID 1
// now im setting it to null expecting to delete previous relationship automatically
device.setManager(null);
deviceRepository.save(device);
Created a short example based on your Spring Boot and Spring Data Neo4j version and enabled the Cypher log.
Foremost interesting is the test case where I wrote down, what I understood.
You can see clearly:
MATCH (startNode:`Device`)-[rel:`MANAGED_BY`]->(:`DeviceManager`) WHERE (startNode.id = $fromId AND NOT (elementId(rel) IN $__knownRelationShipIds__)) DELETE rel
But I am happy to support you in finding the difference between your approach and mine. Thought it is easier to discuss this with some code at hand.
I updated the the example and added a intentional failing test there:
If I got you correctly, you are only changing the target node but not the relationship properties instance, right? You would have to replace also the relationship properties with a new class. Otherwise, SDN would assume that this is still the same relationship, having the same target node.