25
25
import org .neo4j .cypherdsl .core .Node ;
26
26
import org .neo4j .cypherdsl .core .Parameter ;
27
27
import org .neo4j .cypherdsl .core .PatternElement ;
28
+ import org .neo4j .cypherdsl .core .Property ;
28
29
import org .neo4j .cypherdsl .core .Relationship ;
29
30
import org .neo4j .cypherdsl .core .RelationshipPattern ;
30
31
import org .neo4j .cypherdsl .core .SortItem ;
49
50
50
51
import static org .neo4j .cypherdsl .core .Cypher .anyNode ;
51
52
import static org .neo4j .cypherdsl .core .Cypher .listBasedOn ;
53
+ import static org .neo4j .cypherdsl .core .Cypher .literalOf ;
52
54
import static org .neo4j .cypherdsl .core .Cypher .match ;
53
55
import static org .neo4j .cypherdsl .core .Cypher .node ;
54
56
import static org .neo4j .cypherdsl .core .Cypher .optionalMatch ;
55
57
import static org .neo4j .cypherdsl .core .Cypher .parameter ;
58
+ import static org .neo4j .cypherdsl .core .Functions .coalesce ;
56
59
57
60
/**
58
61
* A generator based on the schema defined by node and relationship descriptions. Most methods return renderable Cypher
@@ -223,7 +226,7 @@ public Statement createStatementReturningDynamicLabels(NodeDescription<?> nodeDe
223
226
224
227
PersistentProperty versionProperty = ((Neo4jPersistentEntity ) nodeDescription ).getRequiredVersionProperty ();
225
228
versionCondition = rootNode .property (versionProperty .getName ())
226
- .isEqualTo (parameter (Constants .NAME_OF_VERSION_PARAM ));
229
+ .isEqualTo (coalesce ( parameter (Constants .NAME_OF_VERSION_PARAM ), literalOf ( 0 ) ));
227
230
} else {
228
231
versionCondition = Conditions .noCondition ();
229
232
}
@@ -261,26 +264,34 @@ public Statement prepareSaveOf(NodeDescription<?> nodeDescription,
261
264
.orElseThrow (() -> new MappingException ("External id does not correspond to a graph property!" ));
262
265
263
266
if (((Neo4jPersistentEntity ) nodeDescription ).hasVersionProperty ()) {
264
-
265
- PersistentProperty versionProperty = ((Neo4jPersistentEntity ) nodeDescription ).getRequiredVersionProperty ();
267
+ Property versionProperty = rootNode .property (((Neo4jPersistentEntity ) nodeDescription ).getRequiredVersionProperty ().getName ());
266
268
String nameOfPossibleExistingNode = "hlp" ;
267
269
Node possibleExistingNode = node (primaryLabel , additionalLabels ).named (nameOfPossibleExistingNode );
268
270
269
271
Statement createIfNew = updateDecorator .apply (optionalMatch (possibleExistingNode )
270
- .where (possibleExistingNode .property (nameOfIdProperty ).isEqualTo (idParameter )).with (possibleExistingNode )
271
- .where (possibleExistingNode .isNull ()).create (rootNode )
272
- .set (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM ))).returning (rootNode .internalId ()).build ();
273
-
274
- Statement updateIfExists = updateDecorator
275
- .apply (match (rootNode ).where (rootNode .property (nameOfIdProperty ).isEqualTo (idParameter ))
276
- .and (rootNode .property (versionProperty .getName ()).isEqualTo (parameter (Constants .NAME_OF_VERSION_PARAM )))
277
- .mutate (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM )))
278
- .returning (rootNode .internalId ()).build ();
272
+ .where (possibleExistingNode .property (nameOfIdProperty ).isEqualTo (idParameter ))
273
+ .with (possibleExistingNode )
274
+ .where (possibleExistingNode .isNull ())
275
+ .create (rootNode .withProperties (versionProperty , literalOf (0 )))
276
+ .with (rootNode )
277
+ .mutate (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM ))).returning (rootNode )
278
+ .build ();
279
+
280
+ Statement updateIfExists = updateDecorator .apply (match (rootNode )
281
+ .where (rootNode .property (nameOfIdProperty ).isEqualTo (idParameter ))
282
+ .and (versionProperty .isEqualTo (parameter (Constants .NAME_OF_VERSION_PARAM ))) // Initial check
283
+ .set (versionProperty .to (versionProperty .add (literalOf (1 )))) // Acquire lock
284
+ .with (rootNode )
285
+ .where (versionProperty .isEqualTo (coalesce (parameter (Constants .NAME_OF_VERSION_PARAM ), literalOf (0 )).add (
286
+ literalOf (1 ))))
287
+ .mutate (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM )))
288
+ .returning (rootNode )
289
+ .build ();
279
290
return Cypher .union (createIfNew , updateIfExists );
280
291
281
292
} else {
282
293
return updateDecorator .apply (Cypher .merge (rootNode .withProperties (nameOfIdProperty , idParameter )).mutate (rootNode ,
283
- parameter (Constants .NAME_OF_PROPERTIES_PARAM ))).returning (rootNode . internalId () ).build ();
294
+ parameter (Constants .NAME_OF_PROPERTIES_PARAM ))).returning (rootNode ).build ();
284
295
}
285
296
} else {
286
297
String nameOfPossibleExistingNode = "hlp" ;
@@ -290,27 +301,36 @@ public Statement prepareSaveOf(NodeDescription<?> nodeDescription,
290
301
Statement updateIfExists ;
291
302
292
303
if (((Neo4jPersistentEntity ) nodeDescription ).hasVersionProperty ()) {
293
-
294
- PersistentProperty versionProperty = ((Neo4jPersistentEntity ) nodeDescription ).getRequiredVersionProperty ();
295
-
296
- createIfNew = updateDecorator
297
- .apply (optionalMatch (possibleExistingNode ).where (possibleExistingNode .internalId ().isEqualTo (idParameter ))
298
- .with (possibleExistingNode ).where (possibleExistingNode .isNull ()).create (rootNode )
299
- .set (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM )))
300
- .returning (rootNode .internalId ()).build ();
301
-
302
- updateIfExists = updateDecorator .apply (match (rootNode ).where (rootNode .internalId ().isEqualTo (idParameter ))
303
- .and (rootNode .property (versionProperty .getName ()).isEqualTo (parameter (Constants .NAME_OF_VERSION_PARAM )))
304
- .mutate (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM ))).returning (rootNode .internalId ()).build ();
304
+ Property versionProperty = rootNode .property (((Neo4jPersistentEntity ) nodeDescription ).getRequiredVersionProperty ().getName ());
305
+
306
+ createIfNew = updateDecorator .apply (optionalMatch (possibleExistingNode )
307
+ .where (possibleExistingNode .internalId ().isEqualTo (idParameter ))
308
+ .with (possibleExistingNode )
309
+ .where (possibleExistingNode .isNull ())
310
+ .create (rootNode .withProperties (versionProperty , literalOf (0 )))
311
+ .with (rootNode )
312
+ .mutate (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM )))
313
+ .returning (rootNode )
314
+ .build ();
315
+
316
+ updateIfExists = updateDecorator .apply (match (rootNode )
317
+ .where (rootNode .internalId ().isEqualTo (idParameter ))
318
+ .and (versionProperty .isEqualTo (parameter (Constants .NAME_OF_VERSION_PARAM ))) // Initial check
319
+ .set (versionProperty .to (versionProperty .add (literalOf (1 )))) // Acquire lock
320
+ .with (rootNode )
321
+ .where (versionProperty .isEqualTo (coalesce (parameter (Constants .NAME_OF_VERSION_PARAM ), literalOf (0 )).add (
322
+ literalOf (1 ))))
323
+ .mutate (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM )))
324
+ .returning (rootNode ).build ();
305
325
} else {
306
326
createIfNew = updateDecorator
307
327
.apply (optionalMatch (possibleExistingNode ).where (possibleExistingNode .internalId ().isEqualTo (idParameter ))
308
328
.with (possibleExistingNode ).where (possibleExistingNode .isNull ()).create (rootNode )
309
329
.set (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM )))
310
- .returning (rootNode . internalId () ).build ();
330
+ .returning (rootNode ).build ();
311
331
312
332
updateIfExists = updateDecorator .apply (match (rootNode ).where (rootNode .internalId ().isEqualTo (idParameter ))
313
- .mutate (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM ))).returning (rootNode . internalId () ).build ();
333
+ .mutate (rootNode , parameter (Constants .NAME_OF_PROPERTIES_PARAM ))).returning (rootNode ).build ();
314
334
}
315
335
316
336
return Cypher .union (createIfNew , updateIfExists );
0 commit comments