KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > jdbc > AbstractBatcher


1 //$Id: AbstractBatcher.java,v 1.27 2005/07/06 21:25:52 oneovthafew Exp $
2
package org.hibernate.jdbc;
3
4 import java.sql.CallableStatement JavaDoc;
5 import java.sql.Connection JavaDoc;
6 import java.sql.PreparedStatement JavaDoc;
7 import java.sql.ResultSet JavaDoc;
8 import java.sql.SQLException JavaDoc;
9 import java.util.HashSet JavaDoc;
10 import java.util.Iterator JavaDoc;
11
12 import org.apache.commons.logging.Log;
13 import org.apache.commons.logging.LogFactory;
14 import org.hibernate.AssertionFailure;
15 import org.hibernate.HibernateException;
16 import org.hibernate.ScrollMode;
17 import org.hibernate.dialect.Dialect;
18 import org.hibernate.engine.SessionFactoryImplementor;
19 import org.hibernate.exception.JDBCExceptionHelper;
20 import org.hibernate.util.GetGeneratedKeysHelper;
21 import org.hibernate.util.JDBCExceptionReporter;
22
23 /**
24  * Manages prepared statements and batching.
25  *
26  * @author Gavin King
27  */

28 public abstract class AbstractBatcher implements Batcher {
29
30     private static int globalOpenPreparedStatementCount;
31     private static int globalOpenResultSetCount;
32
33     private int openPreparedStatementCount;
34     private int openResultSetCount;
35
36     protected static final Log log = LogFactory.getLog(AbstractBatcher.class);
37     protected static final Log SQL_LOG = LogFactory.getLog("org.hibernate.SQL");
38
39     private final ConnectionManager connectionManager;
40     private final SessionFactoryImplementor factory;
41
42     private PreparedStatement JavaDoc batchUpdate;
43     private String JavaDoc batchUpdateSQL;
44
45     private HashSet JavaDoc statementsToClose = new HashSet JavaDoc();
46     private HashSet JavaDoc resultSetsToClose = new HashSet JavaDoc();
47     private PreparedStatement JavaDoc lastQuery;
48
49     private boolean releasing = false;
50
51     public AbstractBatcher(ConnectionManager connectionManager) {
52         this.connectionManager = connectionManager;
53         this.factory = connectionManager.getFactory();
54     }
55
56     protected PreparedStatement JavaDoc getStatement() {
57         return batchUpdate;
58     }
59
60     public CallableStatement JavaDoc prepareCallableStatement(String JavaDoc sql)
61     throws SQLException JavaDoc, HibernateException {
62         executeBatch();
63         logOpenPreparedStatement();
64         return getCallableStatement( connectionManager.getConnection(), sql, false);
65     }
66
67     public PreparedStatement JavaDoc prepareStatement(String JavaDoc sql)
68     throws SQLException JavaDoc, HibernateException {
69         return prepareStatement(sql, false);
70     }
71
72     public PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, boolean getGeneratedKeys)
73     throws SQLException JavaDoc, HibernateException {
74         executeBatch();
75         logOpenPreparedStatement();
76         return getPreparedStatement( connectionManager.getConnection(), sql, false, getGeneratedKeys, null, false );
77     }
78
79     public PreparedStatement JavaDoc prepareSelectStatement(String JavaDoc sql)
80     throws SQLException JavaDoc, HibernateException {
81         logOpenPreparedStatement();
82         return getPreparedStatement( connectionManager.getConnection(), sql, false, false, null, false );
83     }
84
85     public PreparedStatement JavaDoc prepareQueryStatement(String JavaDoc sql, boolean scrollable, ScrollMode scrollMode)
86     throws SQLException JavaDoc, HibernateException {
87         logOpenPreparedStatement();
88         PreparedStatement JavaDoc ps = getPreparedStatement( connectionManager.getConnection(), sql, scrollable, scrollMode );
89         setStatementFetchSize(ps);
90         statementsToClose.add(ps);
91         lastQuery=ps;
92         return ps;
93     }
94
95     public CallableStatement JavaDoc prepareCallableQueryStatement(String JavaDoc sql, boolean scrollable, ScrollMode scrollMode)
96     throws SQLException JavaDoc, HibernateException {
97         logOpenPreparedStatement();
98         CallableStatement JavaDoc ps = (CallableStatement JavaDoc) getPreparedStatement(connectionManager.getConnection(), sql, scrollable, false, scrollMode, true);
99         setStatementFetchSize(ps);
100         statementsToClose.add(ps);
101         lastQuery=ps;
102         return ps;
103     }
104
105     public void abortBatch(SQLException JavaDoc sqle) {
106         try {
107             if (batchUpdate!=null) closeStatement(batchUpdate);
108         }
109         catch (SQLException JavaDoc e) {
110             //noncritical, swallow and let the other propagate!
111
JDBCExceptionReporter.logExceptions(e);
112         }
113         finally {
114             batchUpdate=null;
115             batchUpdateSQL=null;
116         }
117     }
118
119     public ResultSet JavaDoc getResultSet(PreparedStatement JavaDoc ps) throws SQLException JavaDoc {
120         ResultSet JavaDoc rs = ps.executeQuery();
121         resultSetsToClose.add(rs);
122         logOpenResults();
123         return rs;
124     }
125
126     public ResultSet JavaDoc getResultSet(CallableStatement JavaDoc ps, Dialect dialect) throws SQLException JavaDoc {
127         ResultSet JavaDoc rs = dialect.getResultSet(ps);
128         resultSetsToClose.add(rs);
129         logOpenResults();
130         return rs;
131         
132     }
133     public void closeQueryStatement(PreparedStatement JavaDoc ps, ResultSet JavaDoc rs) throws SQLException JavaDoc {
134         statementsToClose.remove(ps);
135         if (rs!=null) resultSetsToClose.remove(rs);
136         try {
137             if (rs!=null) {
138                 logCloseResults();
139                 rs.close();
140             }
141         }
142         finally {
143             closeQueryStatement(ps);
144         }
145     }
146
147     public PreparedStatement JavaDoc prepareBatchStatement(String JavaDoc sql)
148     throws SQLException JavaDoc, HibernateException {
149         if ( !sql.equals(batchUpdateSQL) ) {
150             batchUpdate=prepareStatement(sql); // calls executeBatch()
151
batchUpdateSQL=sql;
152         }
153         else {
154             log.debug("reusing prepared statement");
155             log(sql);
156         }
157         return batchUpdate;
158     }
159
160     public CallableStatement JavaDoc prepareBatchCallableStatement(String JavaDoc sql)
161     throws SQLException JavaDoc, HibernateException {
162         if ( !sql.equals(batchUpdateSQL) ) { // TODO: what if batchUpdate is a callablestatement ?
163
batchUpdate=prepareCallableStatement(sql); // calls executeBatch()
164
batchUpdateSQL=sql;
165         }
166         return (CallableStatement JavaDoc)batchUpdate;
167     }
168
169
170     public void executeBatch() throws HibernateException {
171         if (batchUpdate!=null) {
172             try {
173                 try {
174                     doExecuteBatch(batchUpdate);
175                 }
176                 finally {
177                     closeStatement(batchUpdate);
178                 }
179             }
180             catch (SQLException JavaDoc sqle) {
181                 throw JDBCExceptionHelper.convert(
182                         factory.getSQLExceptionConverter(),
183                         sqle,
184                         "Could not execute JDBC batch update",
185                         batchUpdateSQL
186                     );
187             }
188             finally {
189                 batchUpdate=null;
190                 batchUpdateSQL=null;
191             }
192         }
193     }
194
195     public void closeStatement(PreparedStatement JavaDoc ps) throws SQLException JavaDoc {
196         logClosePreparedStatement();
197         closePreparedStatement(ps);
198     }
199
200     private void closeQueryStatement(PreparedStatement JavaDoc ps) throws SQLException JavaDoc {
201
202         try {
203             //work around a bug in all known connection pools....
204
if ( ps.getMaxRows()!=0 ) ps.setMaxRows(0);
205             if ( ps.getQueryTimeout()!=0 ) ps.setQueryTimeout(0);
206         }
207         catch (Exception JavaDoc e) {
208             log.warn("exception clearing maxRows/queryTimeout", e);
209 // ps.close(); //just close it; do NOT try to return it to the pool!
210
return; //NOTE: early exit!
211
}
212         finally {
213             closeStatement(ps);
214         }
215
216         if ( lastQuery==ps ) lastQuery = null;
217         
218     }
219
220     /**
221      * Actually releases the batcher, allowing it to cleanup internally held
222      * resources.
223      */

224     public void closeStatements() {
225         try {
226             releasing = true;
227
228             try {
229                 if (batchUpdate!=null) batchUpdate.close();
230             }
231             catch (SQLException JavaDoc sqle) {
232                 //no big deal
233
log.warn("Could not close a JDBC prepared statement", sqle);
234             }
235             batchUpdate=null;
236             batchUpdateSQL=null;
237
238             Iterator JavaDoc iter = resultSetsToClose.iterator();
239             while ( iter.hasNext() ) {
240                 try {
241                     logCloseResults();
242                     ( (ResultSet JavaDoc) iter.next() ).close();
243                 }
244                 catch (SQLException JavaDoc e) {
245                     // no big deal
246
log.warn("Could not close a JDBC result set", e);
247                 }
248             }
249             resultSetsToClose.clear();
250
251             iter = statementsToClose.iterator();
252             while ( iter.hasNext() ) {
253                 try {
254                     closeQueryStatement( (PreparedStatement JavaDoc) iter.next() );
255                 }
256                 catch (SQLException JavaDoc e) {
257                     // no big deal
258
log.warn("Could not close a JDBC statement", e);
259                 }
260             }
261             statementsToClose.clear();
262         }
263         finally {
264             releasing = false;
265         }
266     }
267
268     protected abstract void doExecuteBatch(PreparedStatement JavaDoc ps) throws SQLException JavaDoc, HibernateException;
269     
270     private String JavaDoc preparedStatementCountsToString() {
271         return
272                 " (open PreparedStatements: " +
273                 openPreparedStatementCount +
274                 ", globally: " +
275                 globalOpenPreparedStatementCount +
276                 ")";
277     }
278
279     private String JavaDoc resultSetCountsToString() {
280         return
281                 " (open ResultSets: " +
282                 openResultSetCount +
283                 ", globally: " +
284                 globalOpenResultSetCount +
285                 ")";
286     }
287
288     private void logOpenPreparedStatement() {
289         if ( log.isDebugEnabled() ) {
290             log.debug( "about to open PreparedStatement" + preparedStatementCountsToString() );
291             openPreparedStatementCount++;
292             globalOpenPreparedStatementCount++;
293         }
294     }
295
296     private void logClosePreparedStatement() {
297         if ( log.isDebugEnabled() ) {
298             log.debug( "about to close PreparedStatement" + preparedStatementCountsToString() );
299             openPreparedStatementCount--;
300             globalOpenPreparedStatementCount--;
301         }
302     }
303
304     private void logOpenResults() {
305         if ( log.isDebugEnabled() ) {
306             log.debug( "about to open ResultSet" + resultSetCountsToString() );
307             openResultSetCount++;
308             globalOpenResultSetCount++;
309         }
310     }
311     private void logCloseResults() {
312         if ( log.isDebugEnabled() ) {
313             log.debug( "about to close ResultSet" + resultSetCountsToString() );
314             openResultSetCount--;
315             globalOpenResultSetCount--;
316         }
317     }
318
319     protected SessionFactoryImplementor getFactory() {
320         return factory;
321     }
322     
323     private void log(String JavaDoc sql) {
324         SQL_LOG.debug(sql);
325         if ( factory.getSettings().isShowSqlEnabled() ) System.out.println("Hibernate: " + sql);
326     }
327
328     private PreparedStatement JavaDoc getPreparedStatement(
329             final Connection JavaDoc conn,
330             final String JavaDoc sql,
331             final boolean scrollable,
332             final ScrollMode scrollMode)
333     throws SQLException JavaDoc {
334         return getPreparedStatement(conn, sql, scrollable, false, scrollMode, false);
335     }
336
337     private CallableStatement JavaDoc getCallableStatement( final Connection JavaDoc conn,
338             final String JavaDoc sql,
339             boolean scrollable)
340     throws SQLException JavaDoc {
341
342         if ( scrollable && !factory.getSettings().isScrollableResultSetsEnabled() ) {
343             throw new AssertionFailure("scrollable result sets are not enabled");
344         }
345
346         log(sql);
347         
348         log.trace("preparing callable statement");
349         if (scrollable) {
350             return conn.prepareCall(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
351         }
352         else {
353             return conn.prepareCall(sql);
354         }
355
356     }
357
358     private PreparedStatement JavaDoc getPreparedStatement(
359             final Connection JavaDoc conn,
360             final String JavaDoc sql,
361             boolean scrollable,
362             final boolean useGetGeneratedKeys,
363             final ScrollMode scrollMode,
364             final boolean callable)
365     throws SQLException JavaDoc {
366
367         if ( scrollable && !factory.getSettings().isScrollableResultSetsEnabled() ) {
368             throw new AssertionFailure("scrollable result sets are not enabled");
369         }
370
371         if ( useGetGeneratedKeys && !factory.getSettings().isGetGeneratedKeysEnabled() ) {
372             throw new AssertionFailure("getGeneratedKeys() support is not enabled");
373         }
374
375         log(sql);
376
377         log.trace("preparing statement");
378         PreparedStatement JavaDoc result;
379         if (scrollable) {
380             if (callable) {
381                 result = conn.prepareCall( sql, scrollMode.toResultSetType(), ResultSet.CONCUR_READ_ONLY );
382             }
383             else {
384                 result = conn.prepareStatement( sql, scrollMode.toResultSetType(), ResultSet.CONCUR_READ_ONLY );
385             }
386         }
387         else if (useGetGeneratedKeys) {
388             result = GetGeneratedKeysHelper.prepareStatement(conn, sql);
389         }
390         else {
391             if (callable) {
392                 result = conn.prepareCall(sql);
393             }
394             else {
395                 result = conn.prepareStatement(sql);
396             }
397         }
398         
399         if ( factory.getStatistics().isStatisticsEnabled() ) {
400             factory.getStatisticsImplementor().prepareStatement();
401         }
402         
403         return result;
404
405     }
406
407     private void closePreparedStatement(PreparedStatement JavaDoc ps) throws SQLException JavaDoc {
408         try {
409             log.trace("closing statement");
410             ps.close();
411             if ( factory.getStatistics().isStatisticsEnabled() ) {
412                 factory.getStatisticsImplementor().closeStatement();
413             }
414         }
415         finally {
416             if ( !releasing ) {
417                 // If we are in the process of releasing, no sense
418
// checking for aggressive-release possibility.
419
connectionManager.afterStatement();
420             }
421         }
422     }
423
424     private void setStatementFetchSize(PreparedStatement JavaDoc statement) throws SQLException JavaDoc {
425         Integer JavaDoc statementFetchSize = factory.getSettings().getJdbcFetchSize();
426         if ( statementFetchSize!=null ) {
427             statement.setFetchSize( statementFetchSize.intValue() );
428         }
429     }
430
431     public Connection JavaDoc openConnection() throws HibernateException {
432         log.debug("opening JDBC connection");
433         try {
434             return factory.getConnectionProvider().getConnection();
435         }
436         catch (SQLException JavaDoc sqle) {
437             throw JDBCExceptionHelper.convert(
438                     factory.getSQLExceptionConverter(),
439                     sqle,
440                     "Cannot open connection"
441                 );
442         }
443     }
444
445     public void closeConnection(Connection JavaDoc conn) throws HibernateException {
446         if ( log.isDebugEnabled() ) {
447             log.debug(
448                     "closing JDBC connection" +
449                     preparedStatementCountsToString() +
450                     resultSetCountsToString()
451                 );
452         }
453
454         try {
455             if ( !conn.isClosed() ) {
456                 JDBCExceptionReporter.logAndClearWarnings(conn);
457             }
458             factory.getConnectionProvider().closeConnection(conn);
459         }
460         catch (SQLException JavaDoc sqle) {
461             throw JDBCExceptionHelper.convert(
462                     factory.getSQLExceptionConverter(),
463                     sqle,
464                     "Cannot close connection"
465                 );
466         }
467     }
468
469     public void cancelLastQuery() throws HibernateException {
470         try {
471             if (lastQuery!=null) lastQuery.cancel();
472         }
473         catch (SQLException JavaDoc sqle) {
474             throw JDBCExceptionHelper.convert(
475                     factory.getSQLExceptionConverter(),
476                     sqle,
477                     "Cannot cancel query"
478                 );
479         }
480     }
481
482     public boolean hasOpenResources() {
483         return resultSetsToClose.size() != 0 && statementsToClose.size() != 0;
484     }
485
486     public String JavaDoc openResourceStatsAsString() {
487         return preparedStatementCountsToString() + resultSetCountsToString();
488     }
489
490 }
491
492
493
494
495
496
497
Popular Tags