I'm using SDN 4.1.2 with neo4j 3.0.4 and I discovered strange behaviors that I summarized in simple code snippets (using HttpDriver with remote database).
I have 2 problems (see details below):
MODEL CLASSES:
@NodeEntity
public class A {
@GraphId
private Long graphId;
@Relationship(type="HAS_B", direction = Relationship.OUTGOING)
private Set<B> bSet = new HashSet<>();
public Long getGraphId() {
return graphId;
}
public Set<B> getBSet() {
return bSet;
}
}
@RelationshipEntity(type="HAS_B")
public class B {
@GraphId
private Long graphId;
private String value;
@StartNode
private A a;
@EndNode
private C c;
public B() {
}
public B(A a, C c, String value) {
this.a = a;
this.c = c;
this.value = value;
}
}
@NodeEntity
public class C {
@GraphId
private Long graphId;
}
PROBLEM 1:
// Create C node
C c = new C();
c = cRepository.save(c);
// Create A node
A a = new A();
a = aRepository.save(a);
assertEquals(0, a.getBSet().size());
// Create B relationships from A to C (relationship entities)
B b1 = new B(a, c, "value1");
B b2 = new B(a, c, "value2");
b1 = bRepository.save(b1);
b2 = bRepository.save(b2);
//assertEquals(2, bRepository.count()); // returns 0 instead of 2 !!
Last line: repository count returns 0 instead of 2 !
PROBLEM 2:
// Create C node
C c = new C();
c = cRepository.save(c);
// Create A node
A a = new A();
a = aRepository.save(a);
assertEquals(0, a.getBSet().size());
// Create B relationships from A to C (relationship entities)
B b1 = new B(a, c, "value1");
B b2 = new B(a, c, "value2");
b1 = bRepository.save(b1);
b2 = bRepository.save(b2);
// Reload a
a = aRepository.findOne(a.getGraphId(), -1);
assertEquals(2, a.getBSet().size());
// Delete b1
bRepository.delete(b1);
// This is not working (deleted in DB, but still present in POJO when fetched again below)
//neo4jOperations.query("MATCH (a:A)-[b1:HAS_B]-(c:C) WHERE b1.value = 'value1' DELETE b1", new HashMap());
// Reload a
a = aRepository.findOne(a.getGraphId(), -1);
assertEquals(1, a.getBSet().size());
If the relationship delete is done with a CYPHER query instead of repository delete operation, when the object is reloaded via the repository, the deleted relationship is still present in the POJO (last assert fails, size == 2 instead of 1). But I can see that the relationship has been correctly deleted in the database.
I tried to play with the scope of the session (@Scope(value = "session", proxyMode = ScopedProxyMode.xxx) but it is not helping. In the documentation, it is explicitely said that SDN/OGM has no cache, but I don't understand this behavior.
Thank you in advance for telling me if I'm doing something wrong or if it's a bug.
The first issue is a bug with count on relationship entities. Please log an issue here https://jira.spring.io/browse/DATAGRAPH
The second one is not- the session is unaware of what happens within custom Cypher queries, and reloading the entity within the same session will only have the effect of expanding the subgraph if applicable. Unfortunately this was not documented well enough in 4.1.x. The docs of 4.2.x are much improved here: http://docs.spring.io/spring-data/neo4j/docs/4.2.x/reference/html/#_design_consideration_session_caching
The bottom line is if you're using custom cypher queries to modify the state of your entities, then you must obtain a new session to reload them from the underlying graph.