1919
2020import java .util .Arrays ;
2121import java .util .List ;
22+ import java .util .Optional ;
2223import java .util .stream .Collectors ;
2324
2425import org .junit .jupiter .api .BeforeAll ;
2526import org .junit .jupiter .api .RepeatedTest ;
27+ import org .junit .jupiter .api .BeforeEach ;
2628import org .junit .jupiter .api .Test ;
2729import org .neo4j .driver .Driver ;
2830import org .neo4j .driver .Session ;
@@ -69,6 +71,21 @@ protected static void setupData(@Autowired BookmarkCapture bookmarkCapture) {
6971 }
7072 }
7173
74+ @ BeforeEach
75+ protected void removeRelationships (@ Autowired BookmarkCapture bookmarkCapture ) {
76+ try (Session session = neo4jConnectionSupport .getDriver ().session (bookmarkCapture .createSessionConfig ());
77+ Transaction transaction = session .beginTransaction ();
78+ ) {
79+ transaction .run ("MATCH ()- [r:KNOWS]-() DELETE r" ).consume ();
80+ transaction .run ("MATCH (n:Language) DELETE n" ).consume ();
81+ transaction .run ("MATCH (n:Person {name: 'Gerrit'}) DETACH DELETE n" ).consume ();
82+ transaction .run ("unwind ['German', 'English'] as name create (n:Language {name: name}) return name" )
83+ .consume ();
84+ transaction .commit ();
85+ bookmarkCapture .seedWith (session .lastBookmark ());
86+ }
87+ }
88+
7289 @ Test // GH-2323
7390 void listOfRelationshipPropertiesShouldBeUnwindable (@ Autowired PersonService personService ) {
7491 Person person = personService .updateRel (personId , Arrays .asList ("German" ));
@@ -84,10 +101,14 @@ void listOfRelationshipPropertiesShouldBeUnwindable(@Autowired PersonService per
84101 void dontMixRelatedNodes (@ Autowired PersonRepository repository , @ Autowired BookmarkCapture bookmarkCapture ) {
85102 String id ;
86103 try (Session session = neo4jConnectionSupport .getDriver ().session (bookmarkCapture .createSessionConfig ());
87- Transaction transaction = session .beginTransaction ();
104+ Transaction transaction = session .beginTransaction ();
88105 ) {
89- id = transaction .run ("CREATE (n:Person {id:randomUUID(), name: 'Gerrit'})-[:KNOWS]->(:Language{name:'English'}) return n.id" ).single ().get (0 ).asString ();
90- transaction .run ("MATCH (n:Person {name: 'Gerrit'}) MERGE (n)-[:MOTHER_TONGUE_IS]->(:Language{name:'German'})" ).consume ();
106+ id = transaction .run (
107+ "CREATE (n:Person {id:randomUUID(), name: 'Gerrit'})-[:KNOWS]->(:Language{name:'English'}) return n.id" )
108+ .single ().get (0 ).asString ();
109+ transaction .run (
110+ "MATCH (n:Person {name: 'Gerrit'}) MERGE (n)-[:MOTHER_TONGUE_IS]->(:Language{name:'German'})" )
111+ .consume ();
91112 transaction .commit ();
92113 bookmarkCapture .seedWith (session .lastBookmark ());
93114
@@ -101,14 +122,40 @@ void dontMixRelatedNodes(@Autowired PersonRepository repository, @Autowired Book
101122 }
102123 }
103124
125+ @ Test // GH-2537
126+ void ensureRelationshipsAreSerialized (@ Autowired PersonService personService ) {
127+
128+ Optional <Person > optionalPerson = personService .updateRel2 (personId , Arrays .asList ("German" ));
129+ assertThat (optionalPerson ).isPresent ().hasValueSatisfying (person -> {
130+ assertThat (person .getKnownLanguages ()).hasSize (1 );
131+ assertThat (person .getKnownLanguages ()).first ().satisfies (knows -> {
132+ assertThat (knows .getDescription ()).isEqualTo ("Some description" );
133+ assertThat (knows .getLanguage ()).extracting (Language ::getName ).isEqualTo ("German" );
134+ });
135+ });
136+ }
137+
104138 @ Repository
105139 public interface PersonRepository extends Neo4jRepository <Person , String > {
106140
107- @ Query ("UNWIND $relations As rel WITH rel " +
108- "CREATE (f:Person {id: $from}) - [r:KNOWS {description: rel.__properties__.description}] -> (t:Language {name: rel.__properties__.__target__.__id__}) "
109- +
110- "RETURN f, collect(r), collect(t)" )
141+ // Using separate id and than relationships on top level
142+ @ Query (""
143+ + "UNWIND $relations As rel WITH rel "
144+ + "MATCH (f:Person {id: $from}) "
145+ + "MATCH (t:Language {name: rel.__target__.__id__}) "
146+ + "CREATE (f)- [r:KNOWS {description: rel.__properties__.description}] -> (t) "
147+ + "RETURN f, collect(r), collect(t)"
148+ )
111149 Person updateRel (@ Param ("from" ) String from , @ Param ("relations" ) List <Knows > relations );
150+
151+ // Using the whole person object
152+ @ Query (""
153+ + "UNWIND $person.__properties__.KNOWS As rel WITH rel "
154+ + "MATCH (f:Person {id: $person.__id__}) "
155+ + "MATCH (t:Language {name: rel.__target__.__id__}) "
156+ + "CREATE (f) - [r:KNOWS {description: rel.__properties__.description}] -> (t) "
157+ + "RETURN f, collect(r), collect(t)" )
158+ Person updateRel2 (@ Param ("person" ) Person person );
112159 }
113160
114161 @ Service
@@ -127,6 +174,21 @@ public Person updateRel(String from, List<String> languageNames) {
127174 .collect (Collectors .toList ());
128175 return personRepository .updateRel (from , knownLanguages );
129176 }
177+
178+ public Optional <Person > updateRel2 (String id , List <String > languageNames ) {
179+
180+ Optional <Person > original = personRepository .findById (id );
181+ if (original .isPresent ()) {
182+ Person person = original .get ();
183+ List <Knows > knownLanguages = languageNames .stream ().map (Language ::new )
184+ .map (language -> new Knows ("Some description" , language ))
185+ .collect (Collectors .toList ());
186+ person .setKnownLanguages (knownLanguages );
187+ return Optional .of (personRepository .updateRel2 (person ));
188+ }
189+
190+ return original ;
191+ }
130192 }
131193
132194 @ Configuration
0 commit comments