1 package org.apache.ojb.broker.accesslayer;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import java.sql.Connection;
19 import java.sql.PreparedStatement;
20 import java.sql.ResultSet;
21 import java.sql.SQLException;
22 import java.sql.Statement;
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
41
42
43
44
45 public class StatementsForClassImpl implements StatementsForClassIF
46 {
47 private Logger log = LoggerFactory.getLogger(StatementsForClassImpl.class);
48
49
50
51
52
53
54 protected final ClassDescriptor classDescriptor;
55 protected final SqlGenerator sqlGenerator;
56 protected final Platform platform;
57 protected final Class clazz;
58 protected final int fetchSize;
59 private String deleteSql;
60 private String insertSql;
61 private String updateSql;
62 private String selectByPKSql;
63
64
65
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
82 double level = jcd.getJdbcLevel();
83 FORCEJDBC1_0 = level == 1.0;
84 }
85
86
87
88
89
90 protected boolean usePreparedDeleteStatement()
91 {
92 return !(classDescriptor.getDeleteProcedure() != null &&
93 classDescriptor.getDeleteProcedure().hasReturnValues());
94 }
95
96 public PreparedStatement getDeleteStmt(Connection con) throws SQLException
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 ex)
111 {
112 log.error("Can't prepare delete statement: " + deleteSql, ex);
113 throw ex;
114 }
115 }
116
117 public Statement getGenericStmt(Connection con, boolean scrollable)
118 throws PersistenceBrokerSQLException
119 {
120 Statement stmt;
121 try
122 {
123 stmt = createStatement(con, scrollable,
124 StatementManagerIF.FETCH_SIZE_NOT_EXPLICITLY_SET);
125 }
126 catch (SQLException ex)
127 {
128 throw ExceptionHelper.generateException("Can't prepare statement:", ex, null, log);
129 }
130 return stmt;
131 }
132
133
134
135
136
137 protected boolean usePreparedInsertStatement()
138 {
139 return !(classDescriptor.getInsertProcedure() != null &&
140 classDescriptor.getInsertProcedure().hasReturnValues());
141 }
142
143 public PreparedStatement getInsertStmt(Connection con) throws SQLException
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 ex)
158 {
159 log.error("Can't prepare insert statement: " + insertSql, ex);
160 throw ex;
161 }
162 }
163
164 public PreparedStatement getPreparedStmt(Connection con, String sql,
165 boolean scrollable, int explicitFetchSizeHint, boolean callableStmt)
166 throws PersistenceBrokerSQLException
167 {
168 PreparedStatement stmt;
169 try
170 {
171 stmt = prepareStatement(con, sql, scrollable,
172 !callableStmt, explicitFetchSizeHint);
173 }
174 catch (SQLException ex)
175 {
176 throw ExceptionHelper.generateException("Can't prepare statement:", ex, sql, log);
177 }
178 return stmt;
179 }
180
181 public PreparedStatement getSelectByPKStmt(Connection con) throws SQLException
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 ex)
192 {
193 log.error(ex);
194 throw ex;
195 }
196 }
197
198
199
200
201
202 protected boolean usePreparedUpdateStatement()
203 {
204 return !(classDescriptor.getUpdateProcedure() != null &&
205 classDescriptor.getUpdateProcedure().hasReturnValues());
206 }
207
208 public PreparedStatement getUpdateStmt(Connection con) throws SQLException
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 ex)
223 {
224 log.error("Can't prepare update statement: " + updateSql, ex);
225 throw ex;
226 }
227 }
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244 protected PreparedStatement prepareStatement(Connection con,
245 String sql,
246 boolean scrollable,
247 boolean createPreparedStatement,
248 int explicitFetchSizeHint)
249 throws SQLException
250 {
251 PreparedStatement result;
252
253
254
255
256 try
257 {
258
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 err)
296 {
297
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 eSql)
310 {
311
312
313
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))
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
351
352 private Statement createStatement(Connection con, boolean scrollable, int explicitFetchSizeHint)
353 throws java.sql.SQLException
354 {
355 Statement result;
356 try
357 {
358
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 err)
375 {
376
377
378
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 eSql)
384 {
385
386
387
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 stmt, int explicitFetchSizeHint)
412 throws SQLException
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;
424 }
425 else
426 {
427 fetchSizeHint = fetchSize;
428 }
429 if (fetchSizeHint > 0)
430 {
431 stmt.setFetchSize(fetchSize);
432 }
433 }
434 }
435
436 }