abstractbatcher.java
来自「hibernate-3.0.5 中文文档」· Java 代码 · 共 504 行
JAVA
504 行
//$Id: AbstractBatcher.java,v 1.25 2005/05/11 13:26:26 steveebersole Exp $package org.hibernate.jdbc;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.HashSet;import java.util.Iterator;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.hibernate.AssertionFailure;import org.hibernate.HibernateException;import org.hibernate.ScrollMode;import org.hibernate.dialect.Dialect;import org.hibernate.engine.SessionFactoryImplementor;import org.hibernate.exception.JDBCExceptionHelper;import org.hibernate.util.GetGeneratedKeysHelper;import org.hibernate.util.JDBCExceptionReporter;/** * Manages prepared statements and batching. * * @author Gavin King */public abstract class AbstractBatcher implements Batcher { private static int globalOpenPreparedStatementCount; private static int globalOpenResultSetCount; private int openPreparedStatementCount; private int openResultSetCount; protected static final Log log = LogFactory.getLog(AbstractBatcher.class); protected static final Log SQL_LOG = LogFactory.getLog("org.hibernate.SQL"); private final ConnectionManager connectionManager; private final SessionFactoryImplementor factory; private PreparedStatement batchUpdate; private String batchUpdateSQL; private HashSet statementsToClose = new HashSet(); private HashSet resultSetsToClose = new HashSet(); private PreparedStatement lastQuery; private boolean releasing = false; public AbstractBatcher(ConnectionManager connectionManager) { this.connectionManager = connectionManager; this.factory = connectionManager.getFactory(); } protected PreparedStatement getStatement() { return batchUpdate; } public CallableStatement prepareCallableStatement(String sql) throws SQLException, HibernateException { executeBatch(); logOpenPreparedStatement(); return getCallableStatement( connectionManager.getConnection(), sql, false); } public PreparedStatement prepareStatement(String sql) throws SQLException, HibernateException { return prepareStatement(sql, false); } public PreparedStatement prepareStatement(String sql, boolean getGeneratedKeys) throws SQLException, HibernateException { executeBatch(); logOpenPreparedStatement(); return getPreparedStatement( connectionManager.getConnection(), sql, false, getGeneratedKeys, null, false ); } public PreparedStatement prepareSelectStatement(String sql) throws SQLException, HibernateException { logOpenPreparedStatement(); return getPreparedStatement( connectionManager.getConnection(), sql, false, false, null, false ); } public PreparedStatement prepareQueryStatement(String sql, boolean scrollable, ScrollMode scrollMode) throws SQLException, HibernateException { logOpenPreparedStatement(); PreparedStatement ps = getPreparedStatement( connectionManager.getConnection(), sql, scrollable, scrollMode ); setStatementFetchSize(ps); statementsToClose.add(ps); lastQuery=ps; return ps; } public CallableStatement prepareCallableQueryStatement(String sql, boolean scrollable, ScrollMode scrollMode) throws SQLException, HibernateException { logOpenPreparedStatement(); CallableStatement ps = (CallableStatement) getPreparedStatement(connectionManager.getConnection(), sql, scrollable, false, scrollMode, true); setStatementFetchSize(ps); statementsToClose.add(ps); lastQuery=ps; return ps; } public void abortBatch(SQLException sqle) { try { if (batchUpdate!=null) closeStatement(batchUpdate); } catch (SQLException e) { //noncritical, swallow and let the other propagate! JDBCExceptionReporter.logExceptions(e); } finally { batchUpdate=null; batchUpdateSQL=null; } } public ResultSet getResultSet(PreparedStatement ps) throws SQLException { ResultSet rs = ps.executeQuery(); resultSetsToClose.add(rs); logOpenResults(); return rs; } public ResultSet getResultSet(CallableStatement ps, Dialect dialect) throws SQLException { ResultSet rs = dialect.getResultSet(ps); resultSetsToClose.add(rs); logOpenResults(); return rs; } public void closeQueryStatement(PreparedStatement ps, ResultSet rs) throws SQLException { statementsToClose.remove(ps); if (rs!=null) resultSetsToClose.remove(rs); try { if (rs!=null) { logCloseResults(); rs.close(); } } finally { closeQueryStatement(ps); } } public PreparedStatement prepareBatchStatement(String sql) throws SQLException, HibernateException { if ( !sql.equals(batchUpdateSQL) ) { batchUpdate=prepareStatement(sql); // calls executeBatch() batchUpdateSQL=sql; } else { log.debug("reusing prepared statement"); log(sql); } return batchUpdate; } public CallableStatement prepareBatchCallableStatement(String sql) throws SQLException, HibernateException { if ( !sql.equals(batchUpdateSQL) ) { // TODO: what if batchUpdate is a callablestatement ? batchUpdate=prepareCallableStatement(sql); // calls executeBatch() batchUpdateSQL=sql; } return (CallableStatement)batchUpdate; } public void executeBatch() throws HibernateException { if (batchUpdate!=null) { try { try { doExecuteBatch(batchUpdate); } finally { closeStatement(batchUpdate); } } catch (SQLException sqle) { throw JDBCExceptionHelper.convert( factory.getSQLExceptionConverter(), sqle, "Could not execute JDBC batch update", batchUpdateSQL ); } finally { batchUpdate=null; batchUpdateSQL=null; } } } public void closeStatement(PreparedStatement ps) throws SQLException { logClosePreparedStatement(); closePreparedStatement(ps); } private void closeQueryStatement(PreparedStatement ps) throws SQLException { try { //work around a bug in all known connection pools.... if ( ps.getMaxRows()!=0 ) ps.setMaxRows(0); if ( ps.getQueryTimeout()!=0 ) ps.setQueryTimeout(0); } catch (Exception e) { log.warn("exception clearing maxRows/queryTimeout", e);// ps.close(); //just close it; do NOT try to return it to the pool! return; //NOTE: early exit! } finally { closeStatement(ps); } if ( lastQuery==ps ) lastQuery = null; } /** * Actually releases the batcher, allowing it to cleanup internally held * resources. */ public void closeStatements() { try { releasing = true; try { if (batchUpdate!=null) batchUpdate.close(); } catch (SQLException sqle) { //no big deal log.warn("Could not close a JDBC prepared statement", sqle); } batchUpdate=null; batchUpdateSQL=null; Iterator iter = resultSetsToClose.iterator(); while ( iter.hasNext() ) { try { logCloseResults(); ( (ResultSet) iter.next() ).close(); } catch (SQLException e) { // no big deal log.warn("Could not close a JDBC result set", e); } } resultSetsToClose.clear(); iter = statementsToClose.iterator(); while ( iter.hasNext() ) { try { closeQueryStatement( (PreparedStatement) iter.next() ); } catch (SQLException e) { // no big deal log.warn("Could not close a JDBC statement", e); } } statementsToClose.clear(); } finally { releasing = false; } } protected abstract void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException; private String preparedStatementCountsToString() { return " (open PreparedStatements: " + openPreparedStatementCount + ", globally: " + globalOpenPreparedStatementCount + ")"; } private String resultSetCountsToString() { return " (open ResultSets: " + openResultSetCount + ", globally: " + globalOpenResultSetCount + ")"; } private void logOpenPreparedStatement() { if ( log.isDebugEnabled() ) { log.debug( "about to open PreparedStatement" + preparedStatementCountsToString() ); openPreparedStatementCount++; globalOpenPreparedStatementCount++; } } private void logClosePreparedStatement() { if ( log.isDebugEnabled() ) { log.debug( "about to close PreparedStatement" + preparedStatementCountsToString() ); openPreparedStatementCount--; globalOpenPreparedStatementCount--; } } private void logOpenResults() { if ( log.isDebugEnabled() ) { log.debug( "about to open ResultSet" + resultSetCountsToString() ); openResultSetCount++; globalOpenResultSetCount++; } } private void logCloseResults() { if ( log.isDebugEnabled() ) { log.debug( "about to close ResultSet" + resultSetCountsToString() ); openResultSetCount--; globalOpenResultSetCount--; } } protected SessionFactoryImplementor getFactory() { return factory; } private void log(String sql) { SQL_LOG.debug(sql); if ( factory.getSettings().isShowSqlEnabled() ) System.out.println("Hibernate: " + sql); } private PreparedStatement getPreparedStatement( final Connection conn, final String sql, final boolean scrollable, final ScrollMode scrollMode) throws SQLException { return getPreparedStatement(conn, sql, scrollable, false, scrollMode, false); } private CallableStatement getCallableStatement( final Connection conn, final String sql, boolean scrollable) throws SQLException { if ( scrollable && !factory.getSettings().isScrollableResultSetsEnabled() ) { throw new AssertionFailure("scrollable result sets are not enabled"); } log(sql); log.trace("preparing callable statement"); if (scrollable) { return conn.prepareCall(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); } else { return conn.prepareCall(sql); } } private PreparedStatement getPreparedStatement( final Connection conn, final String sql, boolean scrollable, final boolean useGetGeneratedKeys, final ScrollMode scrollMode, final boolean callable) throws SQLException { if ( scrollable && !factory.getSettings().isScrollableResultSetsEnabled() ) { throw new AssertionFailure("scrollable result sets are not enabled"); } if ( useGetGeneratedKeys && !factory.getSettings().isGetGeneratedKeysEnabled() ) { throw new AssertionFailure("getGeneratedKeys() support is not enabled"); } log(sql); try { log.trace("preparing statement"); PreparedStatement result; if (scrollable) { if (callable) { result = conn.prepareCall( sql, scrollMode.toResultSetType(), ResultSet.CONCUR_READ_ONLY ); } else { result = conn.prepareStatement( sql, scrollMode.toResultSetType(), ResultSet.CONCUR_READ_ONLY ); } } else if (useGetGeneratedKeys) { result = GetGeneratedKeysHelper.prepareStatement(conn, sql); } else { if (callable) { result = conn.prepareCall(sql); } else { result = conn.prepareStatement(sql); } } if ( factory.getStatistics().isStatisticsEnabled() ) { factory.getStatisticsImplementor().prepareStatement(); } return result; } catch (SQLException sqle) { JDBCExceptionReporter.logExceptions(sqle); throw sqle; } } private void closePreparedStatement(PreparedStatement ps) throws SQLException { try { log.trace("closing statement"); ps.close(); if ( factory.getStatistics().isStatisticsEnabled() ) { factory.getStatisticsImplementor().closeStatement(); } } finally { if ( !releasing ) { // If we are in the process of releasing, no sense // checking for aggressive-release possibility. connectionManager.afterStatement(); } } } private void setStatementFetchSize(PreparedStatement statement) throws SQLException { Integer statementFetchSize = factory.getSettings().getJdbcFetchSize(); if ( statementFetchSize!=null ) { statement.setFetchSize( statementFetchSize.intValue() ); } } public Connection openConnection() throws HibernateException { log.debug("opening JDBC connection"); try { return factory.getConnectionProvider().getConnection(); } catch (SQLException sqle) { throw JDBCExceptionHelper.convert( factory.getSQLExceptionConverter(), sqle, "Cannot open connection" ); } } public void closeConnection(Connection conn) throws HibernateException { if ( log.isDebugEnabled() ) { log.debug( "closing JDBC connection" + preparedStatementCountsToString() + resultSetCountsToString() ); } try { if ( !conn.isClosed() ) { JDBCExceptionReporter.logAndClearWarnings(conn); } factory.getConnectionProvider().closeConnection(conn); } catch (SQLException sqle) { throw JDBCExceptionHelper.convert( factory.getSQLExceptionConverter(), sqle, "Cannot close connection" ); } } public void cancelLastQuery() throws HibernateException { try { if (lastQuery!=null) lastQuery.cancel(); } catch (SQLException sqle) { throw JDBCExceptionHelper.convert( factory.getSQLExceptionConverter(), sqle, "Cannot cancel query" ); } } public boolean hasOpenResources() { return resultSetsToClose.size() != 0 && statementsToClose.size() != 0; } public String openResourceStatsAsString() { return preparedStatementCountsToString() + resultSetCountsToString(); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?