19
19
20
20
import java .util .Arrays ;
21
21
import java .util .List ;
22
+ import java .util .Optional ;
22
23
import java .util .stream .Collectors ;
23
24
24
25
import org .junit .jupiter .api .BeforeAll ;
25
26
import org .junit .jupiter .api .RepeatedTest ;
27
+ import org .junit .jupiter .api .BeforeEach ;
26
28
import org .junit .jupiter .api .Test ;
27
29
import org .neo4j .driver .Driver ;
28
30
import org .neo4j .driver .Session ;
@@ -69,6 +71,21 @@ protected static void setupData(@Autowired BookmarkCapture bookmarkCapture) {
69
71
}
70
72
}
71
73
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
+
72
89
@ Test // GH-2323
73
90
void listOfRelationshipPropertiesShouldBeUnwindable (@ Autowired PersonService personService ) {
74
91
Person person = personService .updateRel (personId , Arrays .asList ("German" ));
@@ -84,10 +101,14 @@ void listOfRelationshipPropertiesShouldBeUnwindable(@Autowired PersonService per
84
101
void dontMixRelatedNodes (@ Autowired PersonRepository repository , @ Autowired BookmarkCapture bookmarkCapture ) {
85
102
String id ;
86
103
try (Session session = neo4jConnectionSupport .getDriver ().session (bookmarkCapture .createSessionConfig ());
87
- Transaction transaction = session .beginTransaction ();
104
+ Transaction transaction = session .beginTransaction ();
88
105
) {
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 ();
91
112
transaction .commit ();
92
113
bookmarkCapture .seedWith (session .lastBookmark ());
93
114
@@ -101,14 +122,40 @@ void dontMixRelatedNodes(@Autowired PersonRepository repository, @Autowired Book
101
122
}
102
123
}
103
124
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
+
104
138
@ Repository
105
139
public interface PersonRepository extends Neo4jRepository <Person , String > {
106
140
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
+ )
111
149
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 );
112
159
}
113
160
114
161
@ Service
@@ -127,6 +174,21 @@ public Person updateRel(String from, List<String> languageNames) {
127
174
.collect (Collectors .toList ());
128
175
return personRepository .updateRel (from , knownLanguages );
129
176
}
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
+ }
130
192
}
131
193
132
194
@ Configuration
0 commit comments