KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > jdbc > core > PreparedStatementCreatorFactory


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.jdbc.core;
18
19 import java.sql.Connection JavaDoc;
20 import java.sql.PreparedStatement JavaDoc;
21 import java.sql.ResultSet JavaDoc;
22 import java.sql.SQLException JavaDoc;
23 import java.sql.Types JavaDoc;
24 import java.util.Arrays JavaDoc;
25 import java.util.Collection JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.LinkedList JavaDoc;
29 import java.util.List JavaDoc;
30
31 import org.springframework.dao.InvalidDataAccessApiUsageException;
32 import org.springframework.dao.InvalidDataAccessResourceUsageException;
33 import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
34 import org.springframework.util.Assert;
35
36 /**
37  * Helper class that can efficiently create multiple PreparedStatementCreator
38  * objects with different parameters based on a SQL statement and a single
39  * set of parameter declarations.
40  *
41  * @author Rod Johnson
42  * @author Juergen Hoeller
43  */

44 public class PreparedStatementCreatorFactory {
45
46     /** The SQL, which won't change when the parameters change */
47     private final String JavaDoc sql;
48
49     /** List of SqlParameter objects. May not be <code>null</code>. */
50     private final List JavaDoc declaredParameters;
51
52     private int resultSetType = ResultSet.TYPE_FORWARD_ONLY;
53
54     private boolean updatableResults = false;
55
56     private boolean returnGeneratedKeys = false;
57
58     private String JavaDoc[] generatedKeysColumnNames = null;
59
60     private NativeJdbcExtractor nativeJdbcExtractor;
61
62     private String JavaDoc sqlToUse = null;
63
64
65     /**
66      * Create a new factory. Will need to add parameters
67      * via the addParameter() method or have no parameters.
68      */

69     public PreparedStatementCreatorFactory(String JavaDoc sql) {
70         this.sql = sql;
71         this.declaredParameters = new LinkedList JavaDoc();
72     }
73
74     /**
75      * Create a new factory with the given SQL and JDBC types.
76      * @param sql SQL to execute
77      * @param types int array of JDBC types
78      */

79     public PreparedStatementCreatorFactory(String JavaDoc sql, int[] types) {
80         this.sql = sql;
81         this.declaredParameters = SqlParameter.sqlTypesToAnonymousParameterList(types);
82     }
83
84     /**
85      * Create a new factory with the given SQL and parameters.
86      * @param sql SQL
87      * @param declaredParameters list of SqlParameter objects
88      * @see SqlParameter
89      */

90     public PreparedStatementCreatorFactory(String JavaDoc sql, List JavaDoc declaredParameters) {
91         this.sql = sql;
92         this.declaredParameters = declaredParameters;
93     }
94
95
96     /**
97      * Add a new declared parameter.
98      * Order of parameter addition is significant.
99      */

100     public void addParameter(SqlParameter param) {
101         this.declaredParameters.add(param);
102     }
103
104     /**
105      * Set whether to use prepared statements that return a
106      * specific type of ResultSet.
107      * @param resultSetType the ResultSet type
108      * @see java.sql.ResultSet#TYPE_FORWARD_ONLY
109      * @see java.sql.ResultSet#TYPE_SCROLL_INSENSITIVE
110      * @see java.sql.ResultSet#TYPE_SCROLL_SENSITIVE
111      */

112     public void setResultSetType(int resultSetType) {
113         this.resultSetType = resultSetType;
114     }
115
116     /**
117      * Set whether to use prepared statements capable of returning
118      * updatable ResultSets.
119      */

120     public void setUpdatableResults(boolean updatableResults) {
121         this.updatableResults = updatableResults;
122     }
123
124     /**
125      * Set whether prepared statements should be capable of returning
126      * auto-generated keys.
127      */

128     public void setReturnGeneratedKeys(boolean returnGeneratedKeys) {
129         this.returnGeneratedKeys = returnGeneratedKeys;
130     }
131
132     /**
133      * Set the column names of the auto-generated keys.
134      */

135     public void setGeneratedKeysColumnNames(String JavaDoc[] names) {
136         this.generatedKeysColumnNames = names;
137     }
138
139     /**
140      * Specify the NativeJdbcExtractor to use for unwrapping
141      * PreparedStatements, if any.
142      */

143     public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
144         this.nativeJdbcExtractor = nativeJdbcExtractor;
145     }
146
147     /**
148      * The SQL statement parsed with named parameters expanded.
149      */

150     public void setSqlToUse(String JavaDoc sqlToUse) {
151         this.sqlToUse = sqlToUse;
152     }
153
154
155     /**
156      * Return a new PreparedStatementSetter for the given parameters.
157      * @param params List of parameters. May be <code>null</code>.
158      */

159     public PreparedStatementSetter newPreparedStatementSetter(List JavaDoc params) {
160         return new PreparedStatementCreatorImpl(params != null ? params : Collections.EMPTY_LIST);
161     }
162
163     /**
164      * Return a new PreparedStatementSetter for the given parameters.
165      * @param params parameter array. May be <code>null</code>.
166      */

167     public PreparedStatementSetter newPreparedStatementSetter(Object JavaDoc[] params) {
168         return new PreparedStatementCreatorImpl(params != null ? Arrays.asList(params) : Collections.EMPTY_LIST);
169     }
170
171     /**
172      * Return a new PreparedStatementCreator for the given parameters.
173      * @param params List of parameters. May be <code>null</code>.
174      */

175     public PreparedStatementCreator newPreparedStatementCreator(List JavaDoc params) {
176         return new PreparedStatementCreatorImpl(params != null ? params : Collections.EMPTY_LIST);
177     }
178
179     /**
180      * Return a new PreparedStatementCreator for the given parameters.
181      * @param params parameter array. May be <code>null</code>.
182      */

183     public PreparedStatementCreator newPreparedStatementCreator(Object JavaDoc[] params) {
184         return new PreparedStatementCreatorImpl(params != null ? Arrays.asList(params) : Collections.EMPTY_LIST);
185     }
186
187     /**
188      * Return a new PreparedStatementCreator for the given parameters.
189      * @param sqlToUse the actual SQL statement to use (if different from
190      * the factory's, for example because of named parameter expanding)
191      * @param params parameter array. May be <code>null</code>.
192      */

193     public PreparedStatementCreator newPreparedStatementCreator(String JavaDoc sqlToUse, Object JavaDoc[] params) {
194         return new PreparedStatementCreatorImpl(
195                 sqlToUse, params != null ? Arrays.asList(params) : Collections.EMPTY_LIST);
196     }
197
198
199     /**
200      * PreparedStatementCreator implementation returned by this class.
201      */

202     private class PreparedStatementCreatorImpl
203             implements PreparedStatementCreator, PreparedStatementSetter, SqlProvider, ParameterDisposer {
204
205         private final String JavaDoc actualSql;
206
207         private final List JavaDoc parameters;
208
209         public PreparedStatementCreatorImpl(List JavaDoc parameters) {
210             this((sqlToUse != null ? sqlToUse : sql), parameters);
211         }
212
213         public PreparedStatementCreatorImpl(String JavaDoc actualSql, List JavaDoc parameters) {
214             this.actualSql = actualSql;
215             Assert.notNull(parameters, "Parameters List must not be null");
216             this.parameters = parameters;
217             if (this.parameters.size() != declaredParameters.size())
218                 throw new InvalidDataAccessApiUsageException(
219                         "SQL [" + sql + "]: given " + this.parameters.size() +
220                         " parameters but expected " + declaredParameters.size());
221         }
222
223         public PreparedStatement JavaDoc createPreparedStatement(Connection JavaDoc con) throws SQLException JavaDoc {
224             PreparedStatement JavaDoc ps = null;
225             if (generatedKeysColumnNames != null || returnGeneratedKeys) {
226                 try {
227                     if (generatedKeysColumnNames != null) {
228                         ps = con.prepareStatement(this.actualSql, generatedKeysColumnNames);
229                     }
230                     else {
231                         ps = con.prepareStatement(this.actualSql, PreparedStatement.RETURN_GENERATED_KEYS);
232                     }
233                 }
234                 catch (AbstractMethodError JavaDoc ex) {
235                     throw new InvalidDataAccessResourceUsageException(
236                             "The JDBC driver is not compliant to JDBC 3.0 and thus " +
237                             "does not support retrieval of auto-generated keys", ex);
238                 }
239             }
240             else if (resultSetType == ResultSet.TYPE_FORWARD_ONLY && !updatableResults) {
241                 ps = con.prepareStatement(this.actualSql);
242             }
243             else {
244                 ps = con.prepareStatement(this.actualSql, resultSetType,
245                     updatableResults ? ResultSet.CONCUR_UPDATABLE : ResultSet.CONCUR_READ_ONLY);
246             }
247             setValues(ps);
248             return ps;
249         }
250
251         public void setValues(PreparedStatement JavaDoc ps) throws SQLException JavaDoc {
252             // Determine PreparedStatement to pass to custom types.
253
PreparedStatement JavaDoc psToUse = ps;
254             if (nativeJdbcExtractor != null) {
255                 psToUse = nativeJdbcExtractor.getNativePreparedStatement(ps);
256             }
257
258             // Set arguments: Does nothing if there are no parameters.
259
int sqlColIndx = 1;
260             for (int i = 0; i < this.parameters.size(); i++) {
261                 SqlParameter declaredParameter = (SqlParameter) declaredParameters.get(i);
262                 Object JavaDoc in = this.parameters.get(i);
263                 if (in instanceof Collection JavaDoc && declaredParameter.getSqlType() != Types.ARRAY) {
264                     Collection JavaDoc entries = (Collection JavaDoc) in;
265                     for (Iterator JavaDoc it = entries.iterator(); it.hasNext();) {
266                         Object JavaDoc entry = it.next();
267                         StatementCreatorUtils.setParameterValue(psToUse, sqlColIndx++, declaredParameter, entry);
268                     }
269                 }
270                 else {
271                     StatementCreatorUtils.setParameterValue(psToUse, sqlColIndx++, declaredParameter, in);
272                 }
273             }
274         }
275
276         public String JavaDoc getSql() {
277             return sql;
278         }
279
280         public void cleanupParameters() {
281             StatementCreatorUtils.cleanupParameters(this.parameters);
282         }
283
284         public String JavaDoc toString() {
285             StringBuffer JavaDoc buf = new StringBuffer JavaDoc("PreparedStatementCreatorFactory.PreparedStatementCreatorImpl: sql=[");
286             buf.append(sql).append("]; parameters=").append(this.parameters);
287             return buf.toString();
288         }
289     }
290
291 }
292
Popular Tags