KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > accesslayer > StatementsForClassImpl


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

17
18 import java.sql.Connection JavaDoc;
19 import java.sql.PreparedStatement JavaDoc;
20 import java.sql.ResultSet JavaDoc;
21 import java.sql.SQLException JavaDoc;
22 import java.sql.Statement JavaDoc;
23
24 import org.apache.ojb.broker.PersistenceBrokerSQLException;
25 import org.apache.ojb.broker.accesslayer.sql.SqlGenerator;
26 import org.apache.ojb.broker.accesslayer.sql.SqlGeneratorFactory;
27 import org.apache.ojb.broker.core.proxy.ProxyHelper;
28 import org.apache.ojb.broker.metadata.ClassDescriptor;
29 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
30 import org.apache.ojb.broker.metadata.ConnectionPoolDescriptor;
31 import org.apache.ojb.broker.platforms.Platform;
32 import org.apache.ojb.broker.platforms.PlatformException;
33 import org.apache.ojb.broker.platforms.PlatformFactory;
34 import org.apache.ojb.broker.query.Query;
35 import org.apache.ojb.broker.util.logging.Logger;
36 import org.apache.ojb.broker.util.logging.LoggerFactory;
37 import org.apache.ojb.broker.util.ExceptionHelper;
38
39 /**
40  * This class serves as a cache for Statements that are
41  * used for persistence operations on a given class.
42  * @author Thomas Mahler
43  * @version $Id: StatementsForClassImpl.java,v 1.22.2.7 2005/10/27 17:33:23 arminw Exp $
44  */

45 public class StatementsForClassImpl implements StatementsForClassIF
46 {
47     private Logger log = LoggerFactory.getLogger(StatementsForClassImpl.class);
48
49     /**
50      * sets the escape processing mode
51      */

52     // protected static boolean ESCAPEPROCESSING = false;
53

54     protected final ClassDescriptor classDescriptor;
55     protected final SqlGenerator sqlGenerator;
56     protected final Platform platform;
57     protected final Class JavaDoc clazz;
58     protected final int fetchSize;
59     private String JavaDoc deleteSql;
60     private String JavaDoc insertSql;
61     private String JavaDoc updateSql;
62     private String JavaDoc selectByPKSql;
63
64     /**
65      * force use of JDBC 1.0 statement creation
66      */

67     protected boolean FORCEJDBC1_0 = false;
68
69     public StatementsForClassImpl(
70         final JdbcConnectionDescriptor jcd,
71         final ClassDescriptor classDescriptor)
72     {
73         this.classDescriptor = classDescriptor;
74         clazz = classDescriptor.getClassOfObject();
75         platform = PlatformFactory.getPlatformFor(jcd);
76         sqlGenerator = SqlGeneratorFactory.getInstance().createSqlGenerator(platform);
77
78         final ConnectionPoolDescriptor cpd = jcd.getConnectionPoolDescriptor();
79         fetchSize = cpd.getFetchSize();
80
81         // detect JDBC level
82
double level = jcd.getJdbcLevel();
83         FORCEJDBC1_0 = level == 1.0;
84     }
85
86     /**
87      * Answer true if a PreparedStatement has to be used
88      * <br>false for a CallableStatement
89      */

90     protected boolean usePreparedDeleteStatement()
91     {
92         return !(classDescriptor.getDeleteProcedure() != null &&
93                 classDescriptor.getDeleteProcedure().hasReturnValues());
94     }
95
96     public PreparedStatement JavaDoc getDeleteStmt(Connection JavaDoc con) throws SQLException JavaDoc
97     {
98         if (deleteSql == null)
99         {
100             deleteSql = sqlGenerator.getPreparedDeleteStatement(classDescriptor).getStatement();
101         }
102         try
103         {
104             return prepareStatement(con,
105                     deleteSql,
106                     Query.NOT_SCROLLABLE,
107                     usePreparedDeleteStatement(),
108                     StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE);
109         }
110         catch (SQLException JavaDoc ex)
111         {
112             log.error("Can't prepare delete statement: " + deleteSql, ex);
113             throw ex;
114         }
115     }
116
117     public Statement JavaDoc getGenericStmt(Connection JavaDoc con, boolean scrollable)
118         throws PersistenceBrokerSQLException
119     {
120         Statement JavaDoc stmt;
121         try
122         {
123             stmt = createStatement(con, scrollable,
124                     StatementManagerIF.FETCH_SIZE_NOT_EXPLICITLY_SET);
125         }
126         catch (SQLException JavaDoc ex)
127         {
128             throw ExceptionHelper.generateException("Can't prepare statement:", ex, null, log);
129         }
130         return stmt;
131     }
132
133     /**
134      * Answer true if a PreparedStatement has to be used
135      * <br>false for a CallableStatement
136      */

137     protected boolean usePreparedInsertStatement()
138     {
139         return !(classDescriptor.getInsertProcedure() != null &&
140                 classDescriptor.getInsertProcedure().hasReturnValues());
141     }
142
143     public PreparedStatement JavaDoc getInsertStmt(Connection JavaDoc con) throws SQLException JavaDoc
144     {
145         if (insertSql == null)
146         {
147             insertSql = sqlGenerator.getPreparedInsertStatement(classDescriptor).getStatement();
148         }
149         try
150         {
151             return prepareStatement(con,
152                     insertSql,
153                     Query.NOT_SCROLLABLE,
154                     usePreparedInsertStatement(),
155                     StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE);
156         }
157         catch (SQLException JavaDoc ex)
158         {
159             log.error("Can't prepare insert statement: " + insertSql, ex);
160             throw ex;
161         }
162     }
163
164     public PreparedStatement JavaDoc getPreparedStmt(Connection JavaDoc con, String JavaDoc sql,
165                                              boolean scrollable, int explicitFetchSizeHint, boolean callableStmt)
166         throws PersistenceBrokerSQLException
167     {
168         PreparedStatement JavaDoc stmt;
169         try
170         {
171             stmt = prepareStatement(con, sql, scrollable,
172                     !callableStmt, explicitFetchSizeHint);
173         }
174         catch (SQLException JavaDoc ex)
175         {
176             throw ExceptionHelper.generateException("Can't prepare statement:", ex, sql, log);
177         }
178         return stmt;
179     }
180
181     public PreparedStatement JavaDoc getSelectByPKStmt(Connection JavaDoc con) throws SQLException JavaDoc
182     {
183         if (selectByPKSql == null)
184         {
185             selectByPKSql = sqlGenerator.getPreparedSelectByPkStatement(classDescriptor).getStatement();
186         }
187         try
188         {
189             return prepareStatement(con, selectByPKSql, Query.NOT_SCROLLABLE, true, 1);
190         }
191         catch (SQLException JavaDoc ex)
192         {
193             log.error(ex);
194             throw ex;
195         }
196     }
197
198     /**
199      * Answer true if a PreparedStatement has to be used
200      * <br>false for a CallableStatement
201      */

202     protected boolean usePreparedUpdateStatement()
203     {
204         return !(classDescriptor.getUpdateProcedure() != null &&
205                 classDescriptor.getUpdateProcedure().hasReturnValues());
206     }
207
208     public PreparedStatement JavaDoc getUpdateStmt(Connection JavaDoc con) throws SQLException JavaDoc
209     {
210         if (updateSql == null)
211         {
212             updateSql = sqlGenerator.getPreparedUpdateStatement(classDescriptor).getStatement();
213         }
214         try
215         {
216             return prepareStatement(con,
217                     updateSql,
218                     Query.NOT_SCROLLABLE,
219                     usePreparedUpdateStatement(),
220                     StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE);
221         }
222         catch (SQLException JavaDoc ex)
223         {
224             log.error("Can't prepare update statement: " + updateSql, ex);
225             throw ex;
226         }
227     }
228
229     /**
230      * Prepares a statement with parameters that should work with most RDBMS.
231      *
232      * @param con the connection to utilize
233      * @param sql the sql syntax to use when creating the statement.
234      * @param scrollable determines if the statement will be scrollable.
235      * @param createPreparedStatement if <code>true</code>, then a
236      * {@link PreparedStatement} will be created. If <code>false</code>, then
237      * a {@link java.sql.CallableStatement} will be created.
238      * @param explicitFetchSizeHint will be used as fetchSize hint
239      * (if applicable) if > 0
240      *
241      * @return a statement that can be used to execute the syntax contained in
242      * the <code>sql</code> argument.
243      */

244     protected PreparedStatement JavaDoc prepareStatement(Connection JavaDoc con,
245                                                  String JavaDoc sql,
246                                                  boolean scrollable,
247                                                  boolean createPreparedStatement,
248                                                  int explicitFetchSizeHint)
249         throws SQLException JavaDoc
250     {
251         PreparedStatement JavaDoc result;
252
253         // if a JDBC1.0 driver is used the signature
254
// prepareStatement(String, int, int) is not defined.
255
// we then call the JDBC1.0 variant prepareStatement(String)
256
try
257         {
258             // if necessary use JDB1.0 methods
259
if (!FORCEJDBC1_0)
260             {
261                 if (createPreparedStatement)
262                 {
263                     result =
264                         con.prepareStatement(
265                             sql,
266                             scrollable
267                                 ? ResultSet.TYPE_SCROLL_INSENSITIVE
268                                 : ResultSet.TYPE_FORWARD_ONLY,
269                             ResultSet.CONCUR_READ_ONLY);
270                     afterJdbc2CapableStatementCreate(result, explicitFetchSizeHint);
271                 }
272                 else
273                 {
274                     result =
275                         con.prepareCall(
276                             sql,
277                             scrollable
278                                 ? ResultSet.TYPE_SCROLL_INSENSITIVE
279                                 : ResultSet.TYPE_FORWARD_ONLY,
280                             ResultSet.CONCUR_READ_ONLY);
281                 }
282             }
283             else
284             {
285                 if (createPreparedStatement)
286                 {
287                     result = con.prepareStatement(sql);
288                 }
289                 else
290                 {
291                     result = con.prepareCall(sql);
292                 }
293             }
294         }
295         catch (AbstractMethodError JavaDoc err)
296         {
297             // this exception is raised if Driver is not JDBC 2.0 compliant
298
log.warn("Used driver seems not JDBC 2.0 compatible, use the JDBC 1.0 mode", err);
299             if (createPreparedStatement)
300             {
301                 result = con.prepareStatement(sql);
302             }
303             else
304             {
305                 result = con.prepareCall(sql);
306             }
307             FORCEJDBC1_0 = true;
308         }
309         catch (SQLException JavaDoc eSql)
310         {
311             // there are JDBC Driver that nominally implement JDBC 2.0, but
312
// throw DriverNotCapableExceptions. If we catch one of these
313
// we force usage of JDBC 1.0
314
if (eSql
315                 .getClass()
316                 .getName()
317                 .equals("interbase.interclient.DriverNotCapableException"))
318             {
319                 log.warn("JDBC 2.0 problems with this interbase driver, we use the JDBC 1.0 mode");
320                 if (createPreparedStatement)
321                 {
322                     result = con.prepareStatement(sql);
323                 }
324                 else
325                 {
326                     result = con.prepareCall(sql);
327                 }
328                 FORCEJDBC1_0 = true;
329             }
330             else
331             {
332                 throw eSql;
333             }
334         }
335         try
336         {
337             if (!ProxyHelper.isNormalOjbProxy(result)) // tomdz: What about VirtualProxy
338
{
339                 platform.afterStatementCreate(result);
340             }
341         }
342         catch (PlatformException e)
343         {
344             log.error("Platform dependend failure", e);
345         }
346         return result;
347     }
348
349     /**
350      * Creates a statement with parameters that should work with most RDBMS.
351      */

352     private Statement JavaDoc createStatement(Connection JavaDoc con, boolean scrollable, int explicitFetchSizeHint)
353         throws java.sql.SQLException JavaDoc
354     {
355         Statement JavaDoc result;
356         try
357         {
358             // if necessary use JDBC1.0 methods
359
if (!FORCEJDBC1_0)
360             {
361                 result =
362                     con.createStatement(
363                         scrollable
364                             ? ResultSet.TYPE_SCROLL_INSENSITIVE
365                             : ResultSet.TYPE_FORWARD_ONLY,
366                         ResultSet.CONCUR_READ_ONLY);
367                 afterJdbc2CapableStatementCreate(result, explicitFetchSizeHint);
368             }
369             else
370             {
371                 result = con.createStatement();
372             }
373         }
374         catch (AbstractMethodError JavaDoc err)
375         {
376             // if a JDBC1.0 driver is used, the signature
377
// createStatement(int, int) is not defined.
378
// we then call the JDBC1.0 variant createStatement()
379
log.warn("Used driver seems not JDBC 2.0 compatible, use the JDBC 1.0 mode", err);
380             result = con.createStatement();
381             FORCEJDBC1_0 = true;
382         }
383         catch (SQLException JavaDoc eSql)
384         {
385             // there are JDBC Driver that nominally implement JDBC 2.0, but
386
// throw DriverNotCapableExceptions. If we catch one of these
387
// we force usage of JDBC 1.0
388
if (eSql.getClass().getName()
389                 .equals("interbase.interclient.DriverNotCapableException"))
390             {
391                 log.warn("JDBC 2.0 problems with this interbase driver, we use the JDBC 1.0 mode");
392                 FORCEJDBC1_0 = true;
393                 result = con.createStatement();
394             }
395             else
396             {
397                 throw eSql;
398             }
399         }
400         try
401         {
402             platform.afterStatementCreate(result);
403         }
404         catch (PlatformException e)
405         {
406             log.error("Platform dependend failure", e);
407         }
408         return result;
409     }
410
411     private void afterJdbc2CapableStatementCreate(Statement JavaDoc stmt, int explicitFetchSizeHint)
412             throws SQLException JavaDoc
413     {
414         if (stmt != null)
415         {
416             final int fetchSizeHint;
417             if (explicitFetchSizeHint == StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE)
418             {
419                 fetchSizeHint = StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE;
420             }
421             else if (explicitFetchSizeHint != StatementManagerIF.FETCH_SIZE_NOT_EXPLICITLY_SET)
422             {
423                 fetchSizeHint = explicitFetchSizeHint; // specific for this Statement
424
}
425             else
426             {
427                 fetchSizeHint = fetchSize; // connection pool default
428
}
429             if (fetchSizeHint > 0)
430             {
431                 stmt.setFetchSize(fetchSize);
432             }
433         }
434     }
435
436 }
437
Popular Tags