Here is quick example of the problem, which doesn't even use Spring Neo4j, but plain java objects.
Lets say I have a myEntity class that has 2 fields: graphId and naturalKey. We'll use public fields for shortness. Equals/hashCode are overriden accordingly.
Code:
public class MyEntity {
public Long graphId;
public String naturalKey;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MyEntity myEntity = (MyEntity) o;
if (graphId != null ? !graphId.equals(myEntity.graphId) : myEntity.graphId != null) {
return false;
}
if (naturalKey != null ? !naturalKey.equals(myEntity.naturalKey) : myEntity.naturalKey != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = graphId != null ? graphId.hashCode() : 0;
result = 31 * result + (naturalKey != null ? naturalKey.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "[MyEntity graphId=" + graphId + ", naturalKey=" + naturalKey + "]";
}
And if you run this piece of code:
Code:
// this is what happens when Spring Neo4j loads entity collection from DB...
MyEntity myEntity1 = new MyEntity();
myEntity1.graphId = 10L;
MyEntity myEntity2 = new MyEntity();
myEntity2.graphId = 20L;
Set<MyEntity> set = new HashSet<MyEntity>();
set.add(myEntity1);
set.add(myEntity2);
System.out.println("set = " + set);
// this is simulation of what happens when neo4jTemplate.fetch(set) is called on collection ...
myEntity1.naturalKey = "SomeKey1";
myEntity2.naturalKey = "SomeKey2";
System.out.println("set.contains(myEntity1) = " + set.contains(myEntity1));
And final result is that set DOES NOT contain myEntity1, because its equals/hashCode has changed AFTER being put in Set at first:
set = [[MyEntity graphId=10, naturalKey=null], [MyEntity graphId=20, naturalKey=null]]
set.contains(myEntity1) = false