15
15
*/
16
16
package org .springframework .data .neo4j .core ;
17
17
18
- import java .lang .reflect .InvocationHandler ;
19
- import java .lang .reflect .InvocationTargetException ;
20
- import java .lang .reflect .Method ;
21
- import java .lang .reflect .Proxy ;
22
18
import java .util .Collection ;
23
19
import java .util .Map ;
24
20
import java .util .Optional ;
28
24
import java .util .stream .Collectors ;
29
25
30
26
import org .neo4j .driver .Driver ;
27
+ import org .neo4j .driver .Query ;
31
28
import org .neo4j .driver .QueryRunner ;
32
29
import org .neo4j .driver .Record ;
33
30
import org .neo4j .driver .Result ;
34
31
import org .neo4j .driver .Session ;
32
+ import org .neo4j .driver .Value ;
35
33
import org .neo4j .driver .summary .ResultSummary ;
36
34
import org .neo4j .driver .types .TypeSystem ;
37
35
import org .springframework .core .convert .ConversionService ;
@@ -71,49 +69,57 @@ class DefaultNeo4jClient implements Neo4jClient {
71
69
new Neo4jConversions ().registerConvertersIn ((ConverterRegistry ) conversionService );
72
70
}
73
71
74
- AutoCloseableQueryRunner getQueryRunner (@ Nullable final String targetDatabase ) {
72
+ DelegatingQueryRunner getQueryRunner (@ Nullable final String targetDatabase ) {
75
73
76
74
QueryRunner queryRunner = Neo4jTransactionManager .retrieveTransaction (driver , targetDatabase );
77
75
if (queryRunner == null ) {
78
76
queryRunner = driver .session (Neo4jTransactionUtils .defaultSessionConfig (targetDatabase ));
79
77
}
80
78
81
- return (AutoCloseableQueryRunner ) Proxy .newProxyInstance (this .getClass ().getClassLoader (),
82
- new Class <?>[] { AutoCloseableQueryRunner .class }, new AutoCloseableQueryRunnerHandler (queryRunner ));
79
+ return new DelegatingQueryRunner (queryRunner );
83
80
}
84
81
85
- /**
86
- * Makes a query runner automatically closeable and aware whether it's session or a transaction
87
- */
88
- interface AutoCloseableQueryRunner extends QueryRunner , AutoCloseable {
82
+ static class DelegatingQueryRunner implements QueryRunner , AutoCloseable {
83
+
84
+ private final QueryRunner delegate ;
85
+
86
+ DelegatingQueryRunner (QueryRunner delegate ) {
87
+ this .delegate = delegate ;
88
+ }
89
89
90
90
@ Override
91
- void close ();
92
- }
91
+ public void close () {
93
92
94
- static class AutoCloseableQueryRunnerHandler implements InvocationHandler {
93
+ // We're only going to close sessions we have acquired inside the client, not something that
94
+ // has been retrieved from the tx manager.
95
+ if (this .delegate instanceof Session ) {
96
+ ((Session ) this .delegate ).close ();
97
+ }
98
+ }
95
99
96
- private final QueryRunner target ;
100
+ @ Override
101
+ public Result run (String s , Value value ) {
102
+ return delegate .run (s , value );
103
+ }
97
104
98
- AutoCloseableQueryRunnerHandler (QueryRunner target ) {
99
- this .target = target ;
105
+ @ Override
106
+ public Result run (String s , Map <String , Object > map ) {
107
+ return delegate .run (s , map );
100
108
}
101
109
102
110
@ Override
103
- public Object invoke (Object proxy , Method method , Object [] args ) throws Throwable {
111
+ public Result run (String s , Record record ) {
112
+ return delegate .run (s , record );
113
+ }
104
114
105
- if ("close" .equals (method .getName ())) {
106
- if (this .target instanceof Session ) {
107
- ((Session ) this .target ).close ();
108
- }
109
- return null ;
110
- } else {
111
- try {
112
- return method .invoke (target , args );
113
- } catch (InvocationTargetException ite ) {
114
- throw ite .getCause ();
115
- }
116
- }
115
+ @ Override
116
+ public Result run (String s ) {
117
+ return delegate .run (s );
118
+ }
119
+
120
+ @ Override
121
+ public Result run (Query query ) {
122
+ return delegate .run (query );
117
123
}
118
124
}
119
125
@@ -158,7 +164,7 @@ class RunnableStatement {
158
164
159
165
private final NamedParameters parameters ;
160
166
161
- protected final Result runWith (AutoCloseableQueryRunner statementRunner ) {
167
+ protected final Result runWith (QueryRunner statementRunner ) {
162
168
String statementTemplate = cypherSupplier .get ();
163
169
164
170
if (cypherLog .isDebugEnabled ()) {
@@ -256,7 +262,7 @@ public RecordFetchSpec<Map<String, Object>> fetch() {
256
262
@ Override
257
263
public ResultSummary run () {
258
264
259
- try (AutoCloseableQueryRunner statementRunner = getQueryRunner (this .targetDatabase )) {
265
+ try (DelegatingQueryRunner statementRunner = getQueryRunner (this .targetDatabase )) {
260
266
Result result = runnableStatement .runWith (statementRunner );
261
267
return ResultSummaries .process (result .consume ());
262
268
} catch (RuntimeException e ) {
@@ -305,7 +311,7 @@ public RecordFetchSpec<T> mappedBy(
305
311
@ Override
306
312
public Optional <T > one () {
307
313
308
- try (AutoCloseableQueryRunner statementRunner = getQueryRunner (this .targetDatabase )) {
314
+ try (DelegatingQueryRunner statementRunner = getQueryRunner (this .targetDatabase )) {
309
315
Result result = runnableStatement .runWith (statementRunner );
310
316
Optional <T > optionalValue = result .hasNext () ?
311
317
Optional .ofNullable (mappingFunction .apply (typeSystem , result .single ())) :
@@ -320,7 +326,7 @@ public Optional<T> one() {
320
326
@ Override
321
327
public Optional <T > first () {
322
328
323
- try (AutoCloseableQueryRunner statementRunner = getQueryRunner (this .targetDatabase )) {
329
+ try (DelegatingQueryRunner statementRunner = getQueryRunner (this .targetDatabase )) {
324
330
Result result = runnableStatement .runWith (statementRunner );
325
331
Optional <T > optionalValue = result .stream ().map (partialMappingFunction (typeSystem )).findFirst ();
326
332
ResultSummaries .process (result .consume ());
@@ -333,7 +339,7 @@ public Optional<T> first() {
333
339
@ Override
334
340
public Collection <T > all () {
335
341
336
- try (AutoCloseableQueryRunner statementRunner = getQueryRunner (this .targetDatabase )) {
342
+ try (DelegatingQueryRunner statementRunner = getQueryRunner (this .targetDatabase )) {
337
343
Result result = runnableStatement .runWith (statementRunner );
338
344
Collection <T > values = result .stream ().map (partialMappingFunction (typeSystem )).collect (Collectors .toList ());
339
345
ResultSummaries .process (result .consume ());
@@ -376,8 +382,10 @@ public RunnableDelegation in(@Nullable @SuppressWarnings("HiddenField") String t
376
382
377
383
@ Override
378
384
public Optional <T > run () {
379
- try (AutoCloseableQueryRunner queryRunner = getQueryRunner (targetDatabase )) {
385
+ try (DelegatingQueryRunner queryRunner = getQueryRunner (targetDatabase )) {
380
386
return callback .apply (queryRunner );
387
+ } catch (RuntimeException e ) {
388
+ throw potentiallyConvertRuntimeException (e , persistenceExceptionTranslator );
381
389
}
382
390
}
383
391
}
0 commit comments