use of org.neo4j.ogm.context.MappedRelationship in project neo4j-ogm by neo4j.
the class CompilerTest method shouldCorrectlyRemoveRelationshipWhenItemIsMovedToDifferentCollection.
@Test
public void shouldCorrectlyRemoveRelationshipWhenItemIsMovedToDifferentCollection() {
Long teacherId = 0L;
Long businessStudiesCourseId = 1L;
Long designTechnologyCourseId = 2L;
Long shivaniId = 3L;
Course designTech = new Course("GCSE Design & Technology");
designTech.setId(designTechnologyCourseId);
Course businessStudies = new Course("GNVQ Business Studies");
businessStudies.setId(businessStudiesCourseId);
Teacher msThompson = new Teacher();
msThompson.setId(teacherId);
msThompson.setName("Ms Thompson");
msThompson.setCourses(Arrays.asList(businessStudies, designTech));
Student shivani = new Student("Shivani");
shivani.setId(shivaniId);
mappingContext.addNodeEntity(msThompson);
mappingContext.addNodeEntity(businessStudies);
mappingContext.addNodeEntity(designTech);
mappingContext.addNodeEntity(shivani);
mappingContext.addRelationship(new MappedRelationship(teacherId, "COURSES", businessStudiesCourseId, null, Teacher.class, Course.class));
mappingContext.addRelationship(new MappedRelationship(teacherId, "COURSES", designTechnologyCourseId, null, Teacher.class, Course.class));
mappingContext.addRelationship(new MappedRelationship(businessStudiesCourseId, "STUDENTS", shivaniId, null, Teacher.class, Student.class));
// move shivani from one course to the other
businessStudies.setStudents(Collections.emptyList());
designTech.setStudents(Arrays.asList(shivani));
// Save msThomson
// we expect a new relationship to be created, and an old one deleted
Compiler compiler = mapAndCompile(msThompson, -1);
List<Statement> statements = compiler.createNodesStatements();
assertThat(statements).isEmpty();
statements = compiler.createRelationshipsStatements();
assertThat(statements).extracting(Statement::getStatement).containsOnly("UNWIND $rows as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId WITH row,startNode MATCH (endNode) WHERE ID(endNode) = row.endNodeId MERGE (startNode)-[rel:`STUDENTS`]->(endNode) RETURN row.relRef as ref, ID(rel) as id, $type as type");
for (Statement statement : statements) {
List rows = (List) statement.getParameters().get("rows");
assertThat(rows).hasSize(1);
}
List<Statement> deleteRelsStatements = compiler.deleteRelationshipStatements();
assertThat(deleteRelsStatements).extracting(Statement::getStatement).containsOnly("UNWIND $rows as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId WITH row,startNode MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`STUDENTS`]->(endNode) DELETE rel");
assertThat(((List) deleteRelsStatements.get(0).getParameters().get("rows"))).hasSize(1);
// fixme: these other tests now need to be in their own test method, because
// a bug fix to the deletion code means that a second deletion won't (correctly) fire again
// expect a delete, but don't expect the new relationship to be created, because the fact of it
// is inaccessible from the businessStudies object
// expectOnSave(businessStudies,
// "MATCH ($1)-[_0:STUDENTS]->($3) WHERE id($1)=1 AND id($3)=3 DELETE _0");
//
// // expect the new relationship, but don't expect the old one to be deleted, because the fact
// // of it is inaccessible from the designTech object
// expectOnSave(designTech,
// "MATCH ($2) WHERE id($2)=2 MATCH ($3) WHERE id($3)=3 MERGE ($2)-[_0:`STUDENTS`]->($3) RETURN id(_0) AS _0");
//
// // we can't explore the object model from shivani at all, so no changes.
// expectOnSave(shivani, "");
}
use of org.neo4j.ogm.context.MappedRelationship in project neo4j-ogm by neo4j.
the class CompilerTest method shouldDeleteExistingRelationshipEntity.
@Test
public void shouldDeleteExistingRelationshipEntity() {
Long forumId = 0L;
Long topicId = 1L;
Long linkId = 2L;
Forum forum = new Forum();
forum.setId(forumId);
forum.setName("Spring Data Neo4j");
Topic topic = new Topic();
topic.setTopicId(topicId);
topic.setInActive(Boolean.FALSE);
ForumTopicLink link = new ForumTopicLink();
link.setId(linkId);
link.setForum(forum);
link.setTopic(topic);
forum.setTopicsInForum(Arrays.asList(link));
mappingContext.addNodeEntity(forum);
mappingContext.addNodeEntity(topic);
mappingContext.addRelationshipEntity(link, linkId);
// the mapping context remembers the relationship between the forum and the topic in the graph
mappingContext.addRelationship(new MappedRelationship(forumId, "HAS_TOPIC", topicId, null, Forum.class, ForumTopicLink.class));
// unlink the objects manually
forum.setTopicsInForum(null);
link.setTopic(null);
// expect the delete to be recognised when the forum is saved
Compiler compiler = mapAndCompile(forum, -1);
List<Statement> statements = compiler.createRelationshipsStatements();
assertThat(statements).isEmpty();
statements = compiler.deleteRelationshipStatements();
assertThat(statements).extracting(Statement::getStatement).containsOnly("UNWIND $rows as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId WITH row,startNode MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`HAS_TOPIC`]->(endNode) DELETE rel");
assertThat(((List) statements.get(0).getParameters().get("rows"))).hasSize(1);
// expect the delete to be recognised if the RE is saved
// expectOnSave(link, "MATCH ($0)-[_0:HAS_TOPIC]->($1) WHERE id($0)=0 AND id($1)=1 DELETE _0");
//
// // expect nothing to happen if the topic is saved, because the domain model does not
// // permit navigation from the topic to the RE (topic has no reference to it)
// expectOnSave(topic, "");
// todo: more tests re saving deletes from REs marked as incoming relationships
}
use of org.neo4j.ogm.context.MappedRelationship in project neo4j-ogm by neo4j.
the class RequestExecutor method updateRelationships.
/**
* Update the mapping context with new relationships created in a request.
*
* @param context the compile context
* @param relRefMappings mapping of relationship reference used in the compile context and the relationship id from the database
*/
private void updateRelationships(CompileContext context, List<ReferenceMapping> relRefMappings) {
final Map<Long, TransientRelationship> registeredTransientRelationshipIndex = buildRegisteredTransientRelationshipIndex(context);
for (ReferenceMapping referenceMapping : relRefMappings) {
if (registeredTransientRelationshipIndex.containsKey(referenceMapping.ref)) {
TransientRelationship transientRelationship = registeredTransientRelationshipIndex.get(referenceMapping.ref);
boolean isRelationshipEntity = session.context().getRelationshipEntity(referenceMapping.id) != null;
MappedRelationship mappedRelationship = new MappedRelationship(context.getId(transientRelationship.getSrc()), transientRelationship.getRel(), context.getId(transientRelationship.getTgt()), isRelationshipEntity ? referenceMapping.id : null, transientRelationship.getSrcClass(), transientRelationship.getTgtClass());
session.context().addRelationship(mappedRelationship);
}
}
}
use of org.neo4j.ogm.context.MappedRelationship in project neo4j-ogm by neo4j.
the class SaveEventDelegate method dirty.
// returns true if the object in question is dirty (has changed)
// an object is dirty if either or both of:
// - its properties have changed
// - its relationships has changed
private boolean dirty(Object parent) {
// have any properties changed
if (this.session.context().isDirty(parent)) {
logger.debug("dirty: {}", parent);
return true;
}
ClassInfo parentInfo = this.session.metaData().classInfo(parent);
long parentId = session.context().nativeId(parent);
// an RE cannot contain additional refs because hyperedges are forbidden in Neo4j
if (!parentInfo.isRelationshipEntity()) {
// build the set of mapped relationships for this object. if there any new ones, the object is dirty
for (FieldInfo reader : relationalReaders(parent)) {
clearPreviousRelationships(parentId, reader);
for (MappedRelationship mappable : map(parentInfo, parentId, reader.read(parent), reader)) {
if (isNew(mappable)) {
logger.debug("added new relationship: {} to {}", mappable, parent);
this.addedRelationships.add(mappable);
return true;
}
this.registeredRelationships.add(mappable);
// no longer deleted
this.deletedRelationships.remove(mappable);
}
}
for (MappedRelationship previous : session.context().getRelationships()) {
if (isDeleted(previous) && (previous.getStartNodeId() == parentId || previous.getEndNodeId() == parentId)) {
logger.debug("deleted: {} from {}", previous, parent);
return true;
}
}
}
return false;
}
use of org.neo4j.ogm.context.MappedRelationship in project neo4j-ogm by neo4j.
the class SaveEventDelegate method deregisterIncomingRelationship.
private void deregisterIncomingRelationship(Long id, String relationshipType, Class endNodeType) {
Iterator<MappedRelationship> iterator = this.registeredRelationships.iterator();
while (iterator.hasNext()) {
MappedRelationship mappedRelationship = iterator.next();
if (mappedRelationship.getEndNodeId() == id && mappedRelationship.getRelationshipType().equals(relationshipType) && endNodeType.equals(mappedRelationship.getStartNodeType())) {
deletedRelationships.add(mappedRelationship);
iterator.remove();
}
}
}
Aggregations