KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > dba > oracle > OracleLOBBatchAction


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.dba.oracle;
21
22 import java.io.OutputStream JavaDoc;
23 import java.io.Writer JavaDoc;
24 import java.lang.reflect.InvocationTargetException JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.sql.Blob JavaDoc;
27 import java.sql.Clob JavaDoc;
28 import java.sql.Connection JavaDoc;
29 import java.sql.PreparedStatement JavaDoc;
30 import java.sql.ResultSet JavaDoc;
31 import java.sql.SQLException JavaDoc;
32 import java.sql.Types JavaDoc;
33 import java.util.Collections JavaDoc;
34 import java.util.List JavaDoc;
35
36 import org.apache.cayenne.CayenneException;
37 import org.apache.cayenne.CayenneRuntimeException;
38 import org.apache.cayenne.access.OperationObserver;
39 import org.apache.cayenne.access.QueryLogger;
40 import org.apache.cayenne.access.trans.LOBBatchQueryBuilder;
41 import org.apache.cayenne.access.trans.LOBBatchQueryWrapper;
42 import org.apache.cayenne.access.trans.LOBInsertBatchQueryBuilder;
43 import org.apache.cayenne.access.trans.LOBUpdateBatchQueryBuilder;
44 import org.apache.cayenne.dba.DbAdapter;
45 import org.apache.cayenne.map.DbAttribute;
46 import org.apache.cayenne.query.BatchQuery;
47 import org.apache.cayenne.query.InsertBatchQuery;
48 import org.apache.cayenne.query.SQLAction;
49 import org.apache.cayenne.query.UpdateBatchQuery;
50 import org.apache.cayenne.util.Util;
51
52 /**
53  * @since 1.2
54  * @author Andrus Adamchik
55  */

56 class OracleLOBBatchAction implements SQLAction {
57
58     BatchQuery query;
59     DbAdapter adapter;
60
61     OracleLOBBatchAction(BatchQuery query, DbAdapter adapter) {
62         this.adapter = adapter;
63         this.query = query;
64     }
65
66     DbAdapter getAdapter() {
67         return adapter;
68     }
69
70     public void performAction(Connection JavaDoc connection, OperationObserver observer)
71             throws SQLException JavaDoc, Exception JavaDoc {
72
73         LOBBatchQueryBuilder queryBuilder;
74         if (query instanceof InsertBatchQuery) {
75             queryBuilder = new LOBInsertBatchQueryBuilder(getAdapter());
76         }
77         else if (query instanceof UpdateBatchQuery) {
78             queryBuilder = new LOBUpdateBatchQueryBuilder(getAdapter());
79         }
80         else {
81             throw new CayenneException(
82                     "Unsupported batch type for special LOB processing: " + query);
83         }
84
85         queryBuilder.setTrimFunction(OracleAdapter.TRIM_FUNCTION);
86         queryBuilder.setNewBlobFunction(OracleAdapter.NEW_BLOB_FUNCTION);
87         queryBuilder.setNewClobFunction(OracleAdapter.NEW_CLOB_FUNCTION);
88
89         // no batching is done, queries are translated
90
// for each batch set, since prepared statements
91
// may be different depending on whether LOBs are NULL or not..
92

93         LOBBatchQueryWrapper selectQuery = new LOBBatchQueryWrapper(query);
94         List JavaDoc qualifierAttributes = selectQuery.getDbAttributesForLOBSelectQualifier();
95
96      
97         boolean isLoggable = QueryLogger.isLoggable();
98
99         query.reset();
100         while (selectQuery.next()) {
101             int updated = 0;
102             String JavaDoc updateStr = queryBuilder.createSqlString(query);
103
104             // 1. run row update
105
QueryLogger.logQuery(updateStr, Collections.EMPTY_LIST);
106             PreparedStatement JavaDoc statement = connection.prepareStatement(updateStr);
107             try {
108
109                 if (isLoggable) {
110                     List JavaDoc bindings = queryBuilder.getValuesForLOBUpdateParameters(query);
111                     QueryLogger.logQueryParameters("bind", bindings);
112                 }
113
114                 queryBuilder.bindParameters(statement, query);
115                 updated = statement.executeUpdate();
116                 QueryLogger.logUpdateCount(updated);
117             }
118             finally {
119                 try {
120                     statement.close();
121                 }
122                 catch (Exception JavaDoc e) {
123                 }
124             }
125
126             // 2. run row LOB update (SELECT...FOR UPDATE and writing out LOBs)
127
processLOBRow(connection, queryBuilder, selectQuery, qualifierAttributes);
128
129             // finally, notify delegate that the row was updated
130
observer.nextCount(query, updated);
131         }
132     }
133
134     void processLOBRow(
135             Connection JavaDoc con,
136             LOBBatchQueryBuilder queryBuilder,
137             LOBBatchQueryWrapper selectQuery,
138             List JavaDoc qualifierAttributes) throws SQLException JavaDoc, Exception JavaDoc {
139
140         List JavaDoc lobAttributes = selectQuery.getDbAttributesForUpdatedLOBColumns();
141         if (lobAttributes.size() == 0) {
142             return;
143         }
144
145         boolean isLoggable = QueryLogger.isLoggable();
146
147         List JavaDoc qualifierValues = selectQuery.getValuesForLOBSelectQualifier();
148         List JavaDoc lobValues = selectQuery.getValuesForUpdatedLOBColumns();
149         int parametersSize = qualifierValues.size();
150         int lobSize = lobAttributes.size();
151
152         String JavaDoc selectStr = queryBuilder.createLOBSelectString(
153                 selectQuery.getQuery(),
154                 lobAttributes,
155                 qualifierAttributes);
156
157         if (isLoggable) {
158             QueryLogger.logQuery(selectStr, qualifierValues);
159             QueryLogger.logQueryParameters("write LOB", lobValues);
160         }
161
162         PreparedStatement JavaDoc selectStatement = con.prepareStatement(selectStr);
163         try {
164             for (int i = 0; i < parametersSize; i++) {
165                 Object JavaDoc value = qualifierValues.get(i);
166                 DbAttribute attribute = (DbAttribute) qualifierAttributes.get(i);
167
168                 adapter.bindParameter(
169                         selectStatement,
170                         value,
171                         i + 1,
172                         attribute.getType(),
173                         attribute.getScale());
174             }
175
176             ResultSet JavaDoc result = selectStatement.executeQuery();
177
178             try {
179                 if (!result.next()) {
180                     throw new CayenneRuntimeException("Missing LOB row.");
181                 }
182
183                 // read the only expected row
184

185                 for (int i = 0; i < lobSize; i++) {
186                     DbAttribute attribute = (DbAttribute) lobAttributes.get(i);
187                     int type = attribute.getType();
188
189                     if (type == Types.CLOB) {
190                         Clob JavaDoc clob = result.getClob(i + 1);
191                         Object JavaDoc clobVal = lobValues.get(i);
192
193                         if (clobVal instanceof char[]) {
194                             writeClob(clob, (char[]) clobVal);
195                         }
196                         else {
197                             writeClob(clob, clobVal.toString());
198                         }
199                     }
200                     else if (type == Types.BLOB) {
201                         Blob JavaDoc blob = result.getBlob(i + 1);
202
203                         Object JavaDoc blobVal = lobValues.get(i);
204                         if (blobVal instanceof byte[]) {
205                             writeBlob(blob, (byte[]) blobVal);
206                         }
207                         else {
208                             String JavaDoc className = (blobVal != null) ? blobVal
209                                     .getClass()
210                                     .getName() : null;
211                             throw new CayenneRuntimeException(
212                                     "Unsupported class of BLOB value: " + className);
213                         }
214                     }
215                     else {
216                         throw new CayenneRuntimeException(
217                                 "Only BLOB or CLOB is expected here, got: " + type);
218                     }
219                 }
220
221                 if (result.next()) {
222                     throw new CayenneRuntimeException("More than one LOB row found.");
223                 }
224             }
225             finally {
226                 try {
227                     result.close();
228                 }
229                 catch (Exception JavaDoc e) {
230                 }
231             }
232         }
233         finally {
234             try {
235                 selectStatement.close();
236             }
237             catch (Exception JavaDoc e) {
238             }
239         }
240     }
241
242     /**
243      * Writing of LOBs is not supported prior to JDBC 3.0 and has to be done using Oracle
244      * driver utilities, using reflection.
245      */

246     private void writeBlob(Blob JavaDoc blob, byte[] value) {
247
248         Method JavaDoc getBinaryStreamMethod = OracleAdapter.getOutputStreamFromBlobMethod();
249         try {
250             OutputStream JavaDoc out = (OutputStream JavaDoc) getBinaryStreamMethod.invoke(blob, null);
251             try {
252                 out.write(value);
253                 out.flush();
254             }
255             finally {
256                 out.close();
257             }
258         }
259         catch (InvocationTargetException JavaDoc e) {
260             throw new CayenneRuntimeException("Error processing BLOB.", Util
261                     .unwindException(e));
262         }
263         catch (Exception JavaDoc e) {
264             throw new CayenneRuntimeException("Error processing BLOB.", Util
265                     .unwindException(e));
266         }
267     }
268
269     /**
270      * Writing of LOBs is not supported prior to JDBC 3.0 and has to be done using Oracle
271      * driver utilities.
272      */

273     private void writeClob(Clob JavaDoc clob, char[] value) {
274         // obtain Writer and write CLOB
275
Method JavaDoc getWriterMethod = OracleAdapter.getWriterFromClobMethod();
276         try {
277
278             Writer JavaDoc out = (Writer JavaDoc) getWriterMethod.invoke(clob, null);
279             try {
280                 out.write(value);
281                 out.flush();
282             }
283             finally {
284                 out.close();
285             }
286
287         }
288         catch (InvocationTargetException JavaDoc e) {
289             throw new CayenneRuntimeException("Error processing BLOB.", Util
290                     .unwindException(e));
291         }
292         catch (Exception JavaDoc e) {
293             throw new CayenneRuntimeException("Error processing BLOB.", Util
294                     .unwindException(e));
295         }
296     }
297
298     /**
299      * Writing of LOBs is not supported prior to JDBC 3.0 and has to be done using Oracle
300      * driver utilities.
301      */

302     private void writeClob(Clob JavaDoc clob, String JavaDoc value) {
303         // obtain Writer and write CLOB
304
Method JavaDoc getWriterMethod = OracleAdapter.getWriterFromClobMethod();
305         try {
306
307             Writer JavaDoc out = (Writer JavaDoc) getWriterMethod.invoke(clob, null);
308             try {
309                 out.write(value);
310                 out.flush();
311             }
312             finally {
313                 out.close();
314             }
315
316         }
317         catch (InvocationTargetException JavaDoc e) {
318             throw new CayenneRuntimeException("Error processing BLOB.", Util
319                     .unwindException(e));
320         }
321         catch (Exception JavaDoc e) {
322             throw new CayenneRuntimeException("Error processing BLOB.", Util
323                     .unwindException(e));
324         }
325     }
326 }
327
Popular Tags