5353import org .springframework .data .neo4j .core .transaction .Neo4jTransactionManager ;
5454import org .springframework .data .neo4j .integration .shared .common .Person ;
5555import org .springframework .data .neo4j .integration .shared .common .PersonWithAllConstructor ;
56+ import org .springframework .data .neo4j .integration .shared .common .PersonWithAssignedId ;
5657import org .springframework .data .neo4j .integration .shared .common .ThingWithGeneratedId ;
5758import org .springframework .data .neo4j .test .BookmarkCapture ;
5859import org .springframework .data .neo4j .test .Neo4jExtension .Neo4jConnectionSupport ;
@@ -101,14 +102,14 @@ void setupData() {
101102 Values .parameters ("name" , TEST_PERSON2_NAME )).single ().get ("id" ).asLong ();
102103
103104 transaction .run ("CREATE (p:Person{firstName: 'A', lastName: 'LA'})" );
104- transaction
105- .run ("CREATE (p:Person{firstName: 'Michael', lastName: 'Siemons'})" +
105+ transaction .run ("CREATE (p:Person{firstName: 'Michael', lastName: 'Siemons'})" +
106106 " -[:LIVES_AT]-> (a:Address {city: 'Aachen'})" +
107107 " -[:BASED_IN]->(c:YetAnotherCountryEntity{name: 'Gemany', countryCode: 'DE'})" +
108108 " RETURN id(p)" );
109- transaction
110- . run ( "CREATE (p:Person{firstName: 'Helge', lastName: 'Schnitzel'}) -[:LIVES_AT]-> (a:Address {city: 'Mülheim an der Ruhr'}) RETURN id(p)" );
109+ transaction . run (
110+ "CREATE (p:Person{firstName: 'Helge', lastName: 'Schnitzel'}) -[:LIVES_AT]-> (a:Address {city: 'Mülheim an der Ruhr'}) RETURN id(p)" );
111111 transaction .run ("CREATE (p:Person{firstName: 'Bela', lastName: 'B.'})" );
112+ transaction .run ("CREATE (p:PersonWithAssignedId{id: 'x', firstName: 'John', lastName: 'Doe'})" );
112113
113114 transaction .commit ();
114115 bookmarkCapture .seedWith (session .lastBookmark ());
@@ -438,9 +439,9 @@ void saveAllAsWithOpenProjectionShouldWork() {
438439 p2 .setFirstName ("Helga" );
439440 p2 .setLastName ("Schneider" );
440441
441- List <OpenProjection > openProjection = neo4jTemplate .saveAllAs (Arrays .asList (p1 , p2 ), OpenProjection .class );
442+ List <OpenProjection > openProjections = neo4jTemplate .saveAllAs (Arrays .asList (p1 , p2 ), OpenProjection .class );
442443
443- assertThat (openProjection ).extracting (OpenProjection ::getFullName )
444+ assertThat (openProjections ).extracting (OpenProjection ::getFullName )
444445 .containsExactlyInAnyOrder ("Michael Simons" , "Helge Schneider" );
445446
446447 List <Person > people = neo4jTemplate .findAllById (Arrays .asList (p1 .getId (), p2 .getId ()), Person .class );
@@ -529,6 +530,105 @@ void saveAsWithClosedProjectionOnSecondLevelShouldWork() {
529530 assertThat (p .getAddress ().getStreet ()).isEqualTo ("Single Trail" );
530531 }
531532
533+ @ Test // GH-2407
534+ void saveAllAsWithClosedProjectionOnSecondLevelShouldWork () {
535+
536+ Person p = neo4jTemplate .findOne ("MATCH (p:Person {lastName: $lastName})-[r:LIVES_AT]-(a:Address) RETURN p, collect(r), collect(a)" ,
537+ Collections .singletonMap ("lastName" , "Siemons" ), Person .class ).get ();
538+
539+ p .setFirstName ("Klaus" );
540+ p .setLastName ("Simons" );
541+ p .getAddress ().setCity ("Braunschweig" );
542+ p .getAddress ().setStreet ("Single Trail" );
543+ List <ClosedProjectionWithEmbeddedProjection > projections = neo4jTemplate .saveAllAs (Collections .singletonList (p ), ClosedProjectionWithEmbeddedProjection .class );
544+
545+ assertThat (projections )
546+ .hasSize (1 ).first ()
547+ .satisfies (projection -> assertThat (projection .getAddress ().getStreet ()).isEqualTo ("Single Trail" ));
548+
549+ p = neo4jTemplate .findById (p .getId (), Person .class ).get ();
550+ assertThat (p .getFirstName ()).isEqualTo ("Michael" );
551+ assertThat (p .getLastName ()).isEqualTo ("Simons" );
552+ assertThat (p .getAddress ().getCity ()).isEqualTo ("Aachen" );
553+ assertThat (p .getAddress ().getStreet ()).isEqualTo ("Single Trail" );
554+ }
555+
556+ @ Test // GH-2407
557+ void shouldSaveNewProjectedThing () {
558+
559+ Person p = new Person ();
560+ p .setFirstName ("John" );
561+ p .setLastName ("Doe" );
562+
563+ ClosedProjection projection = neo4jTemplate .saveAs (p , ClosedProjection .class );
564+ List <Person > people = neo4jTemplate .findAll ("MATCH (p:Person {lastName: $lastName}) RETURN p" ,
565+ Collections .singletonMap ("lastName" , "Doe" ), Person .class );
566+ assertThat (people ).hasSize (1 )
567+ .first ().satisfies (person -> {
568+ assertThat (person .getFirstName ()).isNull ();
569+ assertThat (person .getLastName ()).isEqualTo (projection .getLastName ());
570+ });
571+ }
572+
573+ @ Test // GH-2407
574+ void shouldSaveAllNewProjectedThings () {
575+
576+ Person p = new Person ();
577+ p .setFirstName ("John" );
578+ p .setLastName ("Doe" );
579+
580+ List <ClosedProjection > projections = neo4jTemplate .saveAllAs (Collections .singletonList (p ),
581+ ClosedProjection .class );
582+ assertThat (projections ).hasSize (1 );
583+
584+ ClosedProjection projection = projections .get (0 );
585+ List <Person > people = neo4jTemplate .findAll ("MATCH (p:Person {lastName: $lastName}) RETURN p" ,
586+ Collections .singletonMap ("lastName" , "Doe" ), Person .class );
587+ assertThat (people ).hasSize (1 )
588+ .first ().satisfies (person -> {
589+ assertThat (person .getFirstName ()).isNull ();
590+ assertThat (person .getLastName ()).isEqualTo (projection .getLastName ());
591+ });
592+ }
593+
594+ @ Test // GH-2407
595+ void shouldSaveAllAsWithAssignedIdProjected () {
596+
597+ PersonWithAssignedId p = neo4jTemplate .findById ("x" , PersonWithAssignedId .class ).get ();
598+ p .setLastName ("modifiedLast" );
599+ p .setFirstName ("modifiedFirst" );
600+
601+ List <ClosedProjection > projections = neo4jTemplate .saveAllAs (Collections .singletonList (p ),
602+ ClosedProjection .class );
603+ assertThat (projections ).hasSize (1 );
604+
605+ ClosedProjection projection = projections .get (0 );
606+ List <PersonWithAssignedId > people = neo4jTemplate .findAll ("MATCH (p:PersonWithAssignedId {id: $id}) RETURN p" ,
607+ Collections .singletonMap ("id" , "x" ), PersonWithAssignedId .class );
608+ assertThat (people ).hasSize (1 )
609+ .first ().satisfies (person -> {
610+ assertThat (person .getFirstName ()).isEqualTo ("John" );
611+ assertThat (person .getLastName ()).isEqualTo (projection .getLastName ());
612+ });
613+ }
614+
615+ @ Test // GH-2407
616+ void shouldSaveAsWithAssignedIdProjected () {
617+
618+ PersonWithAssignedId p = neo4jTemplate .findById ("x" , PersonWithAssignedId .class ).get ();
619+ p .setLastName ("modifiedLast" );
620+ p .setFirstName ("modifiedFirst" );
621+
622+ ClosedProjection projection = neo4jTemplate .saveAs (p , ClosedProjection .class );
623+ List <PersonWithAssignedId > people = neo4jTemplate .findAll ("MATCH (p:PersonWithAssignedId {id: $id}) RETURN p" ,
624+ Collections .singletonMap ("id" , "x" ), PersonWithAssignedId .class );
625+ assertThat (people ).hasSize (1 )
626+ .first ().satisfies (person -> {
627+ assertThat (person .getFirstName ()).isEqualTo ("John" );
628+ assertThat (person .getLastName ()).isEqualTo (projection .getLastName ());
629+ });
630+ }
631+
532632 @ Test
533633 void saveAsWithClosedProjectionOnThreeLevelShouldWork () {
534634
@@ -548,6 +648,28 @@ void saveAsWithClosedProjectionOnThreeLevelShouldWork() {
548648 assertThat (savedCountry .getName ()).isEqualTo ("Germany" );
549649 }
550650
651+ @ Test // GH-2407
652+ void saveAllAsWithClosedProjectionOnThreeLevelShouldWork () {
653+
654+ Person p = neo4jTemplate .findOne ("MATCH (p:Person {lastName: $lastName})-[r:LIVES_AT]-(a:Address)-[r2:BASED_IN]->(c:YetAnotherCountryEntity) RETURN p, collect(r), collect(r2), collect(a), collect(c)" ,
655+ Collections .singletonMap ("lastName" , "Siemons" ), Person .class ).get ();
656+
657+ Person .Address .Country country = p .getAddress ().getCountry ();
658+ country .setName ("Germany" );
659+ country .setCountryCode ("AT" );
660+
661+ List <ClosedProjectionWithEmbeddedProjection > projections = neo4jTemplate .saveAllAs (Collections .singletonList (p ), ClosedProjectionWithEmbeddedProjection .class );
662+
663+ assertThat (projections )
664+ .hasSize (1 ).first ()
665+ .satisfies (projection -> assertThat (projection .getAddress ().getCountry ().getName ()).isEqualTo ("Germany" ));
666+
667+ p = neo4jTemplate .findById (p .getId (), Person .class ).get ();
668+ Person .Address .Country savedCountry = p .getAddress ().getCountry ();
669+ assertThat (savedCountry .getCountryCode ()).isEqualTo ("DE" );
670+ assertThat (savedCountry .getName ()).isEqualTo ("Germany" );
671+ }
672+
551673 @ Test
552674 void saveAllAsWithClosedProjectionShouldWork () {
553675
@@ -563,10 +685,10 @@ void saveAllAsWithClosedProjectionShouldWork() {
563685 p2 .setFirstName ("Helga" );
564686 p2 .setLastName ("Schneider" );
565687
566- List <ClosedProjection > openProjection = neo4jTemplate
688+ List <ClosedProjection > closedProjections = neo4jTemplate
567689 .saveAllAs (Arrays .asList (p1 , p2 ), ClosedProjection .class );
568690
569- assertThat (openProjection ).extracting (ClosedProjection ::getLastName )
691+ assertThat (closedProjections ).extracting (ClosedProjection ::getLastName )
570692 .containsExactlyInAnyOrder ("Simons" , "Schneider" );
571693
572694 List <Person > people = neo4jTemplate .findAllById (Arrays .asList (p1 .getId (), p2 .getId ()), Person .class );
0 commit comments