KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > jdbc > object > BatchSqlUpdate


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16
17 package org.springframework.jdbc.object;
18
19 import java.sql.PreparedStatement JavaDoc;
20 import java.sql.SQLException JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.LinkedList JavaDoc;
24 import java.util.List JavaDoc;
25
26 import javax.sql.DataSource JavaDoc;
27
28 import org.springframework.dao.DataAccessException;
29 import org.springframework.jdbc.core.BatchPreparedStatementSetter;
30
31 /**
32  * SqlUpdate subclass that performs batch update operations. Encapsulates
33  * queuing up records to be updated, and adds them as a single batch once
34  * <code>flush</code> is called or the given batch size has been met.
35  *
36  * <p>Note that this class is a <b>non-thread-safe object</b>, in contrast
37  * to all other JDBC operations objects in this package. You need to create
38  * a new instance of it for each use, or call <code>reset</code> before
39  * reuse within the same thread.
40  *
41  * @author Keith Donald
42  * @author Juergen Hoeller
43  * @since 1.1
44  * @see #flush
45  * @see #reset
46  */

47 public class BatchSqlUpdate extends SqlUpdate {
48
49     /**
50      * Default number of inserts to accumulate before commiting a batch (5000).
51      */

52     public static int DEFAULT_BATCH_SIZE = 5000;
53
54
55     private int batchSize = DEFAULT_BATCH_SIZE;
56
57     private boolean trackRowsAffected = true;
58
59     private final LinkedList JavaDoc parameterQueue = new LinkedList JavaDoc();
60
61     private final List JavaDoc rowsAffected = new ArrayList JavaDoc();
62
63
64     /**
65      * Constructor to allow use as a JavaBean. DataSource and SQL
66      * must be supplied before compilation and use.
67      * @see #setDataSource
68      * @see #setSql
69      */

70     public BatchSqlUpdate() {
71         super();
72     }
73
74     /**
75      * Construct an update object with a given DataSource and SQL.
76      * @param ds DataSource to use to obtain connections
77      * @param sql SQL statement to execute
78      */

79     public BatchSqlUpdate(DataSource JavaDoc ds, String JavaDoc sql) {
80         super(ds, sql);
81     }
82
83     /**
84      * Construct an update object with a given DataSource, SQL
85      * and anonymous parameters.
86      * @param ds DataSource to use to obtain connections
87      * @param sql SQL statement to execute
88      * @param types SQL types of the parameters, as defined in the
89      * <code>java.sql.Types</code> class
90      * @see java.sql.Types
91      */

92     public BatchSqlUpdate(DataSource JavaDoc ds, String JavaDoc sql, int[] types) {
93         super(ds, sql, types);
94     }
95
96     /**
97      * Construct an update object with a given DataSource, SQL,
98      * anonymous parameters and specifying the maximum number of rows
99      * that may be affected.
100      * @param ds DataSource to use to obtain connections
101      * @param sql SQL statement to execute
102      * @param types SQL types of the parameters, as defined in the
103      * <code>java.sql.Types</code> class
104      * @param batchSize the number of statements that will trigger
105      * an automatic intermediate flush
106      * @see java.sql.Types
107      */

108     public BatchSqlUpdate(DataSource JavaDoc ds, String JavaDoc sql, int[] types, int batchSize) {
109         super(ds, sql, types);
110         setBatchSize(batchSize);
111     }
112
113
114     /**
115      * Set the number of statements that will trigger an automatic intermediate
116      * flush. <code>update</code> calls or the given statement parameters will
117      * be queued until the batch size is met, at which point it will empty the
118      * queue and execute the batch.
119      * <p>You can also flush already queued statements with an explicit
120      * <code>flush</code> call. Note that you need to this after queueing
121      * all parameters to guarantee that all statements have been flushed.
122      */

123     public void setBatchSize(int batchSize) {
124         this.batchSize = batchSize;
125     }
126
127     /**
128      * Set whether to track the rows affected by batch updates performed
129      * by this operation object.
130      * <p>Default is "true". Turn this off to save the memory needed for
131      * the list of row counts.
132      * @see #getRowsAffected()
133      */

134     public void setTrackRowsAffected(boolean trackRowsAffected) {
135         this.trackRowsAffected = trackRowsAffected;
136     }
137
138     /**
139      * BatchSqlUpdate does not support BLOB or CLOB parameters.
140      */

141     protected boolean supportsLobParameters() {
142         return false;
143     }
144
145
146     /**
147      * Overridden version of <code>update</code> that adds the given statement
148      * parameters to the queue rather than executing them immediately.
149      * All other <code>update</code> methods of the SqlUpdate base class go
150      * through this method and will thus behave similarly.
151      * <p>You need to call <code>flush</code> to actually execute the batch.
152      * If the specified batch size is reached, an implicit flush will happen;
153      * you still need to finally call <code>flush</code> to flush all statements.
154      * @param params array of parameter objects
155      * @return the number of rows affected by the update (always -1,
156      * meaning "not applicable", as the statement is not actually
157      * executed by this method)
158      * @see #flush
159      */

160     public int update(Object JavaDoc[] params) throws DataAccessException {
161         validateParameters(params);
162         this.parameterQueue.add(params.clone());
163
164         if (this.parameterQueue.size() == this.batchSize) {
165             if (logger.isDebugEnabled()) {
166                 logger.debug("Triggering auto-flush because queue reached batch size of " + this.batchSize);
167             }
168             flush();
169         }
170
171         return -1;
172     }
173
174     /**
175      * Trigger any queued update operations to be added as a final batch.
176      * @return an array of the number of rows affected by each statement
177      */

178     public int[] flush() {
179         if (this.parameterQueue.isEmpty()) {
180             return new int[0];
181         }
182         
183         int[] rowsAffected = getJdbcTemplate().batchUpdate(
184                 getSql(),
185                 new BatchPreparedStatementSetter() {
186                     public int getBatchSize() {
187                         return parameterQueue.size();
188                     }
189                     public void setValues(PreparedStatement JavaDoc ps, int index) throws SQLException JavaDoc {
190                         Object JavaDoc[] params = (Object JavaDoc[]) parameterQueue.removeFirst();
191                         newPreparedStatementSetter(params).setValues(ps);
192                     }
193                 });
194
195         if (this.trackRowsAffected) {
196             for (int i = 0; i < rowsAffected.length; i++) {
197                 this.rowsAffected.add(new Integer JavaDoc(rowsAffected[i]));
198             }
199         }
200         for (int i = 0; i < rowsAffected.length; i++) {
201             checkRowsAffected(rowsAffected[i]);
202         }
203         return rowsAffected;
204     }
205
206     /**
207      * Return the current number of statements or statement parameters
208      * in the queue.
209      */

210     public int getQueueCount() {
211         return this.parameterQueue.size();
212     }
213
214     /**
215      * Return the number of already executed statements.
216      */

217     public int getExecutionCount() {
218         return this.rowsAffected.size();
219     }
220
221     /**
222      * Return the number of affected rows for all already executed statements.
223      * Accumulates all of <code>flush</code>'s return values until
224      * <code>reset</code> is invoked.
225      * @return an array of the number of rows affected by each statement
226      * @see #reset
227      */

228     public int[] getRowsAffected() {
229         int[] result = new int[this.rowsAffected.size()];
230         int i = 0;
231         for (Iterator JavaDoc it = this.rowsAffected.iterator(); it.hasNext(); i++) {
232             Integer JavaDoc rowCount = (Integer JavaDoc) it.next();
233             result[i] = rowCount.intValue();
234         }
235         return result;
236     }
237
238     /**
239      * Reset the statement parameter queue, the rows affected cache,
240      * and the execution count.
241      */

242     public void reset() {
243         this.parameterQueue.clear();
244         this.rowsAffected.clear();
245     }
246
247 }
248
Popular Tags