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 | |
} |