20
20
import java .util .AbstractMap ;
21
21
import java .util .Collection ;
22
22
import java .util .Map ;
23
+ import java .util .Optional ;
23
24
24
25
import org .junit .jupiter .api .BeforeEach ;
25
26
import org .junit .jupiter .api .Test ;
26
27
import org .neo4j .driver .Driver ;
28
+ import org .neo4j .driver .Record ;
27
29
import org .neo4j .driver .Session ;
28
30
import org .neo4j .driver .Transaction ;
29
31
import org .neo4j .driver .Values ;
40
42
import org .springframework .data .neo4j .integration .shared .common .NamesOnlyDto ;
41
43
import org .springframework .data .neo4j .integration .shared .common .Person ;
42
44
import org .springframework .data .neo4j .integration .shared .common .PersonSummary ;
45
+ import org .springframework .data .neo4j .integration .shared .common .ProjectionTestRoot ;
43
46
import org .springframework .data .neo4j .repository .Neo4jRepository ;
44
47
import org .springframework .data .neo4j .repository .config .EnableNeo4jRepositories ;
45
48
import org .springframework .data .neo4j .test .Neo4jExtension ;
@@ -61,6 +64,8 @@ class ProjectionIT {
61
64
private static Neo4jExtension .Neo4jConnectionSupport neo4jConnectionSupport ;
62
65
63
66
private final Driver driver ;
67
+ private Long projectionTestRootId ;
68
+ private Long projectionTestLevel1Id ;
64
69
65
70
@ Autowired
66
71
ProjectionIT (Driver driver ) {
@@ -69,24 +74,39 @@ class ProjectionIT {
69
74
70
75
@ BeforeEach
71
76
void setup () {
72
- Session session = driver .session ();
73
- Transaction transaction = session .beginTransaction ();
74
-
75
- transaction .run ("MATCH (n) detach delete n" );
76
-
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
- }
86
77
87
- transaction .commit ();
88
- transaction .close ();
89
- session .close ();
78
+ try (Session session = driver .session ();
79
+ Transaction transaction = session .beginTransaction ();) {
80
+
81
+ transaction .run ("MATCH (n) detach delete n" );
82
+
83
+ for (Map .Entry <String , String > person : new Map .Entry [] {
84
+ new AbstractMap .SimpleEntry (FIRST_NAME , LAST_NAME ),
85
+ new AbstractMap .SimpleEntry (FIRST_NAME2 , LAST_NAME ),
86
+ }) {
87
+ transaction .run (" MERGE (address:Address{city: $city})"
88
+ + "CREATE (:Person{firstName: $firstName, lastName: $lastName})"
89
+ + "-[:LIVES_AT]-> (address)" ,
90
+ Values .parameters ("firstName" , person .getKey (), "lastName" , person .getValue (), "city" , CITY ));
91
+ }
92
+
93
+ Record result = transaction .run ("create (r:ProjectionTestRoot {name: 'root'}) \n "
94
+ + "create (l11:ProjectionTestLevel1 {name: 'level11'})\n "
95
+ + "create (l12:ProjectionTestLevel1 {name: 'level12'})\n "
96
+ + "create (l21:ProjectionTestLevel2 {name: 'level21'})\n "
97
+ + "create (l22:ProjectionTestLevel2 {name: 'level22'})\n "
98
+ + "create (l23:ProjectionTestLevel2 {name: 'level23'})\n "
99
+ + "create (r) - [:LEVEL_1] -> (l11)\n "
100
+ + "create (r) - [:LEVEL_1] -> (l12)\n "
101
+ + "create (l11) - [:LEVEL_2] -> (l21)\n "
102
+ + "create (l11) - [:LEVEL_2] -> (l22)\n "
103
+ + "create (l12) - [:LEVEL_2] -> (l23)\n "
104
+ + "return id(r), id(l11)" ).single ();
105
+
106
+ projectionTestRootId = result .get (0 ).asLong ();
107
+ projectionTestLevel1Id = result .get (1 ).asLong ();
108
+ transaction .commit ();
109
+ }
90
110
}
91
111
92
112
@ Test
@@ -188,6 +208,29 @@ void projectionsShouldBeSliceable(@Autowired ProjectionPersonRepository reposito
188
208
assertThat (people ).extracting (NamesOnly ::getFullName ).containsExactly (FIRST_NAME + " " + LAST_NAME );
189
209
}
190
210
211
+ @ Test // GH-2164
212
+ void findByIdWithProjectionShouldWork (@ Autowired TreestructureRepository repository ) {
213
+
214
+ Optional <SimpleProjection > optionalProjection = repository
215
+ .findById (projectionTestRootId , SimpleProjection .class );
216
+ assertThat (optionalProjection ).map (SimpleProjection ::getName ).hasValue ("root" );
217
+ }
218
+
219
+ @ Test // GH-2164
220
+ void findByIdInDerivedFinderMethodInRelatedObjectShouldWork (@ Autowired TreestructureRepository repository ) {
221
+
222
+ Optional <ProjectionTestRoot > optionalProjection = repository .findOneByLevel1Id (projectionTestLevel1Id );
223
+ assertThat (optionalProjection ).map (ProjectionTestRoot ::getName ).hasValue ("root" );
224
+ }
225
+
226
+ @ Test // GH-2164
227
+ void findByIdInDerivedFinderMethodInRelatedObjectWithProjectionShouldWork (
228
+ @ Autowired TreestructureRepository repository ) {
229
+
230
+ Optional <SimpleProjection > optionalProjection = repository .findOneByLevel1Id (projectionTestLevel1Id , SimpleProjection .class );
231
+ assertThat (optionalProjection ).map (SimpleProjection ::getName ).hasValue ("root" );
232
+ }
233
+
191
234
interface ProjectionPersonRepository extends Neo4jRepository <Person , Long > {
192
235
193
236
Collection <NamesOnly > findByLastName (String lastName );
@@ -203,6 +246,20 @@ interface ProjectionPersonRepository extends Neo4jRepository<Person, Long> {
203
246
<T > Collection <T > findByLastNameAndFirstName (String lastName , String firstName , Class <T > projectionClass );
204
247
}
205
248
249
+ interface TreestructureRepository extends Neo4jRepository <ProjectionTestRoot , Long > {
250
+
251
+ <T > Optional <T > findById (Long id , Class <T > typeOfProjection );
252
+
253
+ Optional <ProjectionTestRoot > findOneByLevel1Id (Long idOfLevel1 );
254
+
255
+ <T > Optional <T > findOneByLevel1Id (Long idOfLevel1 , Class <T > typeOfProjection );
256
+ }
257
+
258
+ interface SimpleProjection {
259
+
260
+ String getName ();
261
+ }
262
+
206
263
@ Configuration
207
264
@ EnableNeo4jRepositories (considerNestedRepositories = true )
208
265
@ EnableTransactionManagement
0 commit comments