KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > access > jdbc > SQLTemplateAction


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.access.jdbc;
21
22 import java.sql.Connection JavaDoc;
23 import java.sql.PreparedStatement JavaDoc;
24 import java.sql.ResultSet JavaDoc;
25 import java.sql.SQLException JavaDoc;
26 import java.sql.Statement JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.Collections JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34
35 import org.apache.commons.collections.IteratorUtils;
36 import org.apache.cayenne.CayenneException;
37 import org.apache.cayenne.access.OperationObserver;
38 import org.apache.cayenne.access.QueryLogger;
39 import org.apache.cayenne.access.types.ExtendedTypeMap;
40 import org.apache.cayenne.dba.DbAdapter;
41 import org.apache.cayenne.query.SQLAction;
42 import org.apache.cayenne.query.SQLTemplate;
43 import org.apache.cayenne.util.Util;
44
45 /**
46  * Implements a strategy for execution of SQLTemplates.
47  *
48  * @author Andrus Adamchik
49  * @since 1.2 replaces SQLTemplateExecutionPlan
50  */

51 public class SQLTemplateAction implements SQLAction {
52
53     protected DbAdapter adapter;
54     protected SQLTemplate query;
55
56     public SQLTemplateAction(SQLTemplate query, DbAdapter adapter) {
57         this.query = query;
58         this.adapter = adapter;
59     }
60
61     /**
62      * Returns DbAdapter associated with this execution plan object.
63      */

64     public DbAdapter getAdapter() {
65         return adapter;
66     }
67
68     /**
69      * Runs a SQLTemplate query, collecting all results. If a callback expects an iterated
70      * result, result processing is stopped after the first ResultSet is encountered.
71      */

72     public void performAction(Connection JavaDoc connection, OperationObserver callback)
73             throws SQLException JavaDoc, Exception JavaDoc {
74
75         String JavaDoc template = extractTemplateString();
76
77         // sanity check - misconfigured templates
78
if (template == null) {
79             throw new CayenneException("No template string configured for adapter "
80                     + getAdapter().getClass().getName());
81         }
82
83         boolean loggable = QueryLogger.isLoggable();
84         int size = query.parametersSize();
85
86         SQLTemplateProcessor templateProcessor = new SQLTemplateProcessor();
87
88         // zero size indicates a one-shot query with no parameters
89
// so fake a single entry batch...
90
int batchSize = (size > 0) ? size : 1;
91
92         List JavaDoc counts = new ArrayList JavaDoc(batchSize);
93         Iterator JavaDoc it = (size > 0) ? query.parametersIterator() : IteratorUtils
94                 .singletonIterator(Collections.EMPTY_MAP);
95         for (int i = 0; i < batchSize; i++) {
96             Map JavaDoc nextParameters = (Map JavaDoc) it.next();
97
98             SQLStatement compiled = templateProcessor.processTemplate(
99                     template,
100                     nextParameters);
101
102             if (loggable) {
103                 QueryLogger.logQuery(compiled.getSql(), Arrays.asList(compiled
104                         .getBindings()));
105             }
106
107             execute(connection, callback, compiled, counts);
108         }
109
110         // notify of combined counts of all queries inside SQLTemplate multipled by the
111
// number of parameter sets...
112
if (counts != null) {
113             int[] ints = new int[counts.size()];
114             for (int i = 0; i < ints.length; i++) {
115                 ints[i] = ((Integer JavaDoc) counts.get(i)).intValue();
116             }
117
118             callback.nextBatchCount(query, ints);
119         }
120     }
121
122     protected void execute(
123             Connection JavaDoc connection,
124             OperationObserver callback,
125             SQLStatement compiled,
126             Collection JavaDoc updateCounts) throws SQLException JavaDoc, Exception JavaDoc {
127
128         long t1 = System.currentTimeMillis();
129         boolean iteratedResult = callback.isIteratedResult();
130         PreparedStatement JavaDoc statement = connection.prepareStatement(compiled.getSql());
131         try {
132             bind(statement, compiled.getBindings());
133
134             // process a mix of results
135
boolean isResultSet = statement.execute();
136             boolean firstIteration = true;
137             while (true) {
138
139                 if (firstIteration) {
140                     firstIteration = false;
141                 }
142                 else {
143                     isResultSet = statement.getMoreResults();
144                 }
145
146                 if (isResultSet) {
147
148                     ResultSet JavaDoc resultSet = statement.getResultSet();
149
150                     if (resultSet != null) {
151
152                         try {
153                             processSelectResult(
154                                     compiled,
155                                     connection,
156                                     statement,
157                                     resultSet,
158                                     callback,
159                                     t1);
160                         }
161                         finally {
162                             if (iteratedResult) {
163                                 break;
164                             }
165                             else {
166                                 resultSet.close();
167                             }
168                         }
169                     }
170                 }
171                 else {
172                     int updateCount = statement.getUpdateCount();
173                     if (updateCount == -1) {
174                         break;
175                     }
176
177                     updateCounts.add(new Integer JavaDoc(updateCount));
178                     QueryLogger.logUpdateCount(updateCount);
179                 }
180             }
181         }
182         finally {
183             if (!iteratedResult) {
184                 statement.close();
185             }
186         }
187     }
188
189     protected void processSelectResult(
190             SQLStatement compiled,
191             Connection JavaDoc connection,
192             Statement JavaDoc statement,
193             ResultSet JavaDoc resultSet,
194             OperationObserver callback,
195             long startTime) throws Exception JavaDoc {
196
197         boolean iteratedResult = callback.isIteratedResult();
198
199         ExtendedTypeMap types = adapter.getExtendedTypes();
200         RowDescriptor descriptor = (compiled.getResultColumns().length > 0)
201                 ? new RowDescriptor(compiled.getResultColumns(), types)
202                 : new RowDescriptor(resultSet, types);
203                 
204            if (query.getColumnNamesCapitalization() != null) {
205             if (SQLTemplate.LOWERCASE_COLUMN_NAMES.equals(query
206                     .getColumnNamesCapitalization())) {
207                 descriptor.forceLowerCaseColumnNames();
208             }
209             else if (SQLTemplate.UPPERCASE_COLUMN_NAMES.equals(query
210                     .getColumnNamesCapitalization())) {
211                 descriptor.forceUpperCaseColumnNames();
212             }
213         }
214
215         JDBCResultIterator result = new JDBCResultIterator(
216                 connection,
217                 statement,
218                 resultSet,
219                 descriptor,
220                 query.getFetchLimit());
221
222         if (!iteratedResult) {
223             List JavaDoc resultRows = result.dataRows(false);
224             QueryLogger.logSelectCount(resultRows.size(), System.currentTimeMillis()
225                     - startTime);
226
227             callback.nextDataRows(query, resultRows);
228         }
229         else {
230             try {
231                 result.setClosingConnection(true);
232                 callback.nextDataRows(query, result);
233             }
234             catch (Exception JavaDoc ex) {
235                 result.close();
236                 throw ex;
237             }
238         }
239     }
240
241     /**
242      * Extracts a template string from a SQLTemplate query. Exists mainly for the benefit
243      * of subclasses that can customize returned template.
244      *
245      * @since 1.2
246      */

247     protected String JavaDoc extractTemplateString() {
248         String JavaDoc sql = query.getTemplate(getAdapter().getClass().getName());
249
250         // note that we MUST convert line breaks to spaces. On some databases (DB2)
251
// queries with breaks simply won't run; the rest are affected by CAY-726.
252
return Util.stripLineBreaks(sql, " ");
253     }
254
255     /**
256      * Binds parameters to the PreparedStatement.
257      */

258     protected void bind(PreparedStatement JavaDoc preparedStatement, ParameterBinding[] bindings)
259             throws SQLException JavaDoc, Exception JavaDoc {
260         // bind parameters
261
if (bindings.length > 0) {
262             int len = bindings.length;
263             for (int i = 0; i < len; i++) {
264                 adapter.bindParameter(
265                         preparedStatement,
266                         bindings[i].getValue(),
267                         i + 1,
268                         bindings[i].getJdbcType(),
269                         bindings[i].getPrecision());
270             }
271         }
272     }
273
274     /**
275      * Always returns true.
276      *
277      * @deprecated since 3.0
278      */

279     public boolean isRemovingLineBreaks() {
280         return true;
281     }
282
283     /**
284      * @deprecated since 3.0 - does nothing
285      */

286     public void setRemovingLineBreaks(boolean removingLineBreaks) {
287
288     }
289
290     /**
291      * Returns a SQLTemplate for this action.
292      */

293     public SQLTemplate getQuery() {
294         return query;
295     }
296 }
297
Popular Tags