16
16
17
17
package org .springframework .batch .extensions .neo4j ;
18
18
19
- import java .util .ArrayList ;
20
- import java .util .Iterator ;
21
- import java .util .Map ;
22
-
23
19
import org .apache .commons .logging .Log ;
24
20
import org .apache .commons .logging .LogFactory ;
25
- import org .neo4j .ogm . session . Session ;
26
- import org .neo4j .ogm . session . SessionFactory ;
27
-
21
+ import org .neo4j .cypherdsl . core . Statement ;
22
+ import org .neo4j .cypherdsl . core . StatementBuilder ;
23
+ import org . neo4j . cypherdsl . core . renderer . Renderer ;
28
24
import org .springframework .batch .item .ItemReader ;
29
25
import org .springframework .batch .item .data .AbstractPaginatedDataItemReader ;
30
26
import org .springframework .beans .factory .InitializingBean ;
27
+ import org .springframework .data .neo4j .core .Neo4jTemplate ;
31
28
import org .springframework .util .Assert ;
32
- import org .springframework .util .StringUtils ;
29
+
30
+ import java .util .Iterator ;
31
+ import java .util .Map ;
33
32
34
33
/**
35
34
* <p>
38
37
* </p>
39
38
*
40
39
* <p>
41
- * It executes cypher queries built from the statement fragments provided to
40
+ * It executes cypher queries built from the statement provided to
42
41
* retrieve the requested data. The query is executed using paged requests of
43
42
* a size specified in {@link #setPageSize(int)}. Additional pages are requested
44
43
* as needed when the {@link #read()} method is called. On restart, the reader
45
44
* will begin again at the same number item it left off at.
46
45
* </p>
47
46
*
48
47
* <p>
49
- * Performance is dependent on your Neo4J configuration (embedded or remote) as
48
+ * Performance is dependent on your Neo4j configuration as
50
49
* well as page size. Setting a fairly large page size and using a commit
51
50
* interval that matches the page size should provide better performance.
52
51
* </p>
58
57
* environment (no restart available).
59
58
* </p>
60
59
*
60
+ * @param <T> type of entity to load
61
+ *
61
62
* @author Michael Minella
62
63
* @author Mahmoud Ben Hassine
64
+ * @author Gerrit Meier
63
65
*/
64
66
public class Neo4jItemReader <T > extends AbstractPaginatedDataItemReader <T > implements InitializingBean {
65
67
66
- protected Log logger = LogFactory .getLog (getClass ());
68
+ private final Log logger = LogFactory .getLog (getClass ());
67
69
68
- private SessionFactory sessionFactory ;
70
+ private Neo4jTemplate neo4jTemplate ;
69
71
70
- private String startStatement ;
71
- private String returnStatement ;
72
- private String matchStatement ;
73
- private String whereStatement ;
74
- private String orderByStatement ;
72
+ private StatementBuilder .OngoingReadingAndReturn statement ;
75
73
76
74
private Class <T > targetType ;
77
75
@@ -86,76 +84,23 @@ public void setParameterValues(Map<String, Object> parameterValues) {
86
84
this .parameterValues = parameterValues ;
87
85
}
88
86
89
- protected final Map <String , Object > getParameterValues () {
90
- return this .parameterValues ;
91
- }
92
-
93
- /**
94
- * The start segment of the cypher query. START is prepended
95
- * to the statement provided and should <em>not</em> be
96
- * included.
97
- *
98
- * @param startStatement the start fragment of the cypher query.
99
- */
100
- public void setStartStatement (String startStatement ) {
101
- this .startStatement = startStatement ;
102
- }
103
-
104
- /**
105
- * The return statement of the cypher query. RETURN is prepended
106
- * to the statement provided and should <em>not</em> be
107
- * included
108
- *
109
- * @param returnStatement the return fragment of the cypher query.
110
- */
111
- public void setReturnStatement (String returnStatement ) {
112
- this .returnStatement = returnStatement ;
113
- }
114
-
115
87
/**
116
- * An optional match fragment of the cypher query. MATCH is
117
- * prepended to the statement provided and should <em>not</em>
118
- * be included.
88
+ * Cypher-DSL's {@link org.neo4j.cypherdsl.core.StatementBuilder.OngoingReadingAndReturn} statement
89
+ * without skip and limit segments. Those will get added by the pagination mechanism later.
119
90
*
120
- * @param matchStatement the match fragment of the cypher query
91
+ * @param statement the Cypher-DSL statement-in-construction.
121
92
*/
122
- public void setMatchStatement ( String matchStatement ) {
123
- this .matchStatement = matchStatement ;
93
+ public void setStatement ( StatementBuilder . OngoingReadingAndReturn statement ) {
94
+ this .statement = statement ;
124
95
}
125
96
126
97
/**
127
- * An optional where fragment of the cypher query. WHERE is
128
- * prepended to the statement provided and should <em>not</em>
129
- * be included.
98
+ * Establish the Neo4jTemplate for the reader.
130
99
*
131
- * @param whereStatement where fragment of the cypher query
100
+ * @param neo4jTemplate the template to use for the reader.
132
101
*/
133
- public void setWhereStatement (String whereStatement ) {
134
- this .whereStatement = whereStatement ;
135
- }
136
-
137
- /**
138
- * A list of properties to order the results by. This is
139
- * required so that subsequent page requests pull back the
140
- * segment of results correctly. ORDER BY is prepended to
141
- * the statement provided and should <em>not</em> be included.
142
- *
143
- * @param orderByStatement order by fragment of the cypher query.
144
- */
145
- public void setOrderByStatement (String orderByStatement ) {
146
- this .orderByStatement = orderByStatement ;
147
- }
148
-
149
- protected SessionFactory getSessionFactory () {
150
- return sessionFactory ;
151
- }
152
-
153
- /**
154
- * Establish the session factory for the reader.
155
- * @param sessionFactory the factory to use for the reader.
156
- */
157
- public void setSessionFactory (SessionFactory sessionFactory ) {
158
- this .sessionFactory = sessionFactory ;
102
+ public void setNeo4jTemplate (Neo4jTemplate neo4jTemplate ) {
103
+ this .neo4jTemplate = neo4jTemplate ;
159
104
}
160
105
161
106
/**
@@ -167,28 +112,16 @@ public void setTargetType(Class<T> targetType) {
167
112
this .targetType = targetType ;
168
113
}
169
114
170
- protected final Class <T > getTargetType () {
171
- return this .targetType ;
172
- }
173
-
174
- protected String generateLimitCypherQuery () {
175
- StringBuilder query = new StringBuilder (128 );
176
-
177
- query .append ("START " ).append (startStatement );
178
- query .append (matchStatement != null ? " MATCH " + matchStatement : "" );
179
- query .append (whereStatement != null ? " WHERE " + whereStatement : "" );
180
- query .append (" RETURN " ).append (returnStatement );
181
- query .append (" ORDER BY " ).append (orderByStatement );
182
- query .append (" SKIP " + (pageSize * page ));
183
- query .append (" LIMIT " + pageSize );
184
-
185
- String resultingQuery = query .toString ();
186
-
115
+ private Statement generateStatement () {
116
+ Statement builtStatement = statement
117
+ .skip (page * pageSize )
118
+ .limit (pageSize )
119
+ .build ();
187
120
if (logger .isDebugEnabled ()) {
188
- logger .debug (resultingQuery );
121
+ logger .debug (Renderer . getDefaultRenderer (). render ( builtStatement ) );
189
122
}
190
123
191
- return resultingQuery ;
124
+ return builtStatement ;
192
125
}
193
126
194
127
/**
@@ -197,28 +130,15 @@ protected String generateLimitCypherQuery() {
197
130
* @see InitializingBean#afterPropertiesSet()
198
131
*/
199
132
@ Override
200
- public void afterPropertiesSet () throws Exception {
201
- Assert .state (sessionFactory != null ,"A SessionFactory is required" );
133
+ public void afterPropertiesSet () {
134
+ Assert .state (neo4jTemplate != null , "A Neo4jTemplate is required" );
202
135
Assert .state (targetType != null , "The type to be returned is required" );
203
- Assert .state (StringUtils .hasText (startStatement ), "A START statement is required" );
204
- Assert .state (StringUtils .hasText (returnStatement ), "A RETURN statement is required" );
205
- Assert .state (StringUtils .hasText (orderByStatement ), "A ORDER BY statement is required" );
136
+ Assert .state (statement != null , "A statement is required" );
206
137
}
207
138
208
139
@ SuppressWarnings ("unchecked" )
209
140
@ Override
210
141
protected Iterator <T > doPageRead () {
211
- Session session = getSessionFactory ().openSession ();
212
-
213
- Iterable <T > queryResults = session .query (getTargetType (),
214
- generateLimitCypherQuery (),
215
- getParameterValues ());
216
-
217
- if (queryResults != null ) {
218
- return queryResults .iterator ();
219
- }
220
- else {
221
- return new ArrayList <T >().iterator ();
222
- }
142
+ return neo4jTemplate .findAll (generateStatement (), parameterValues , targetType ).iterator ();
223
143
}
224
144
}
0 commit comments