17
17
18
18
import static org .assertj .core .api .Assertions .assertThat ;
19
19
20
+ import java .util .AbstractMap ;
20
21
import java .util .Collection ;
22
+ import java .util .Map ;
21
23
22
24
import org .junit .jupiter .api .BeforeEach ;
23
25
import org .junit .jupiter .api .Test ;
24
26
import org .neo4j .driver .Driver ;
25
27
import org .neo4j .driver .Session ;
26
28
import org .neo4j .driver .Transaction ;
29
+ import org .neo4j .driver .Values ;
27
30
import org .springframework .beans .factory .annotation .Autowired ;
28
31
import org .springframework .context .annotation .Bean ;
29
32
import org .springframework .context .annotation .Configuration ;
33
+ import org .springframework .data .domain .Page ;
34
+ import org .springframework .data .domain .PageRequest ;
35
+ import org .springframework .data .domain .Pageable ;
36
+ import org .springframework .data .domain .Slice ;
37
+ import org .springframework .data .domain .Sort ;
30
38
import org .springframework .data .neo4j .config .AbstractNeo4jConfig ;
31
39
import org .springframework .data .neo4j .integration .shared .common .NamesOnly ;
32
40
import org .springframework .data .neo4j .integration .shared .common .NamesOnlyDto ;
40
48
41
49
/**
42
50
* @author Gerrit Meier
51
+ * @author Michael J. Simons
43
52
*/
44
53
@ Neo4jIntegrationTest
45
54
class ProjectionIT {
46
55
47
56
private static final String FIRST_NAME = "Hans" ;
57
+ private static final String FIRST_NAME2 = "Lieschen" ;
48
58
private static final String LAST_NAME = "Mueller" ;
49
59
private static final String CITY = "Braunschweig" ;
50
60
@@ -64,8 +74,15 @@ void setup() {
64
74
65
75
transaction .run ("MATCH (n) detach delete n" );
66
76
67
- transaction .run ("CREATE (:Person{firstName:'" + FIRST_NAME + "', lastName:'" + LAST_NAME + "'})" + "-[:LIVES_AT]->"
68
- + "(:Address{city:'" + CITY + "'})" );
77
+ for (Map .Entry <String , String > person : new Map .Entry [] {
78
+ new AbstractMap .SimpleEntry (FIRST_NAME , LAST_NAME ),
79
+ new AbstractMap .SimpleEntry (FIRST_NAME2 , LAST_NAME ),
80
+ }) {
81
+ transaction .run (" MERGE (address:Address{city: $city})"
82
+ + "CREATE (:Person{firstName: $firstName, lastName: $lastName})"
83
+ + "-[:LIVES_AT]-> (address)" ,
84
+ Values .parameters ("firstName" , person .getKey (), "lastName" , person .getValue (), "city" , CITY ));
85
+ }
69
86
70
87
transaction .commit ();
71
88
transaction .close ();
@@ -74,16 +91,14 @@ void setup() {
74
91
75
92
@ Test
76
93
void loadNamesOnlyProjection (@ Autowired ProjectionPersonRepository repository ) {
77
- Collection <NamesOnly > people = repository .findByLastName (LAST_NAME );
78
- assertThat (people ).hasSize (1 );
79
94
80
- NamesOnly person = people .iterator ().next ();
81
- assertThat (person .getFirstName ()).isEqualTo (FIRST_NAME );
82
- assertThat (person .getLastName ()).isEqualTo (LAST_NAME );
95
+ Collection <NamesOnly > people = repository .findByLastName (LAST_NAME );
96
+ assertThat (people ).hasSize (2 );
83
97
84
- String expectedFullName = FIRST_NAME + " " + LAST_NAME ;
85
- assertThat (person . getFullName ()). isEqualTo ( expectedFullName );
98
+ assertThat ( people ). extracting ( NamesOnly :: getFirstName ). containsExactlyInAnyOrder ( FIRST_NAME , FIRST_NAME2 ) ;
99
+ assertThat (people ). extracting ( NamesOnly :: getLastName ). containsOnly ( LAST_NAME );
86
100
101
+ assertThat (people ).extracting (NamesOnly ::getFullName ).containsExactlyInAnyOrder (FIRST_NAME + " " + LAST_NAME , FIRST_NAME2 + " " + LAST_NAME );
87
102
}
88
103
89
104
@ Test
@@ -153,10 +168,34 @@ void findDynamicProjectionForNamesOnlyDto(@Autowired ProjectionPersonRepository
153
168
154
169
}
155
170
171
+ @ Test // GH-2139
172
+ void projectionsShouldBePaginatable (@ Autowired ProjectionPersonRepository repository ) {
173
+
174
+ Page <NamesOnly > people = repository .findAllProjectedBy (PageRequest .of (1 , 1 , Sort .by ("firstName" ).descending ()));
175
+ assertThat (people .hasPrevious ()).isTrue ();
176
+ assertThat (people .hasNext ()).isFalse ();
177
+ assertThat (people ).hasSize (1 );
178
+ assertThat (people ).extracting (NamesOnly ::getFullName ).containsExactly (FIRST_NAME + " " + LAST_NAME );
179
+ }
180
+
181
+ @ Test // GH-2139
182
+ void projectionsShouldBeSliceable (@ Autowired ProjectionPersonRepository repository ) {
183
+
184
+ Slice <NamesOnly > people = repository .findSliceProjectedBy (PageRequest .of (1 , 1 , Sort .by ("firstName" ).descending ()));
185
+ assertThat (people .hasPrevious ()).isTrue ();
186
+ assertThat (people .hasNext ()).isFalse ();
187
+ assertThat (people ).hasSize (1 );
188
+ assertThat (people ).extracting (NamesOnly ::getFullName ).containsExactly (FIRST_NAME + " " + LAST_NAME );
189
+ }
190
+
156
191
interface ProjectionPersonRepository extends Neo4jRepository <Person , Long > {
157
192
158
193
Collection <NamesOnly > findByLastName (String lastName );
159
194
195
+ Page <NamesOnly > findAllProjectedBy (Pageable pageable );
196
+
197
+ Slice <NamesOnly > findSliceProjectedBy (Pageable pageable );
198
+
160
199
Collection <PersonSummary > findByFirstName (String firstName );
161
200
162
201
Collection <NamesOnlyDto > findByFirstNameAndLastName (String firstName , String lastName );
@@ -175,5 +214,4 @@ public Driver driver() {
175
214
}
176
215
177
216
}
178
-
179
217
}
0 commit comments