From: <one...@us...> - 2002-10-31 16:58:51
|
Update of /cvsroot/hibernate/Hibernate/cirrus/hibernate/impl In directory usw-pr-cvs1:/tmp/cvs-serv13818/cirrus/hibernate/impl Modified Files: SessionImpl.java Added Files: BatcherImpl.java BatchingBatcher.java NonBatchingBatcher.java Log Message: Batcher hierarchy enforces seperation of concerns --- NEW FILE: BatcherImpl.java --- //$Id: BatcherImpl.java,v 1.1 2002/10/31 16:58:13 oneovthafew Exp $ package cirrus.hibernate.impl; import java.sql.PreparedStatement; 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 cirrus.hibernate.HibernateException; import cirrus.hibernate.engine.Batcher; import cirrus.hibernate.engine.SessionFactoryImplementor; import cirrus.hibernate.engine.SessionImplementor; /** * Manages prepared statements and batching. Class exists to enforce seperation of concerns. */ public abstract class BatcherImpl implements Batcher { protected static final Log log = LogFactory.getLog(BatcherImpl.class); protected final SessionImplementor session; protected final SessionFactoryImplementor factory; private PreparedStatement batchUpdate; private String batchUpdateSQL; private HashSet statementsToClose = new HashSet(); public BatcherImpl(SessionImplementor session) { this.session = session; this.factory = session.getFactory(); } protected PreparedStatement getStatement() { return batchUpdate; } public PreparedStatement prepareStatement(String sql) throws SQLException, HibernateException { executeBatch(); return factory.getPreparedStatement( session.connection(), sql, false ); } public PreparedStatement prepareQueryStatement(String sql, boolean scrollable) throws SQLException, HibernateException { PreparedStatement ps = factory.getPreparedStatement( session.connection(), sql, scrollable ); factory.setFetchSize(ps); statementsToClose.add(ps); return ps; } public void closeQueryStatement(PreparedStatement ps) throws SQLException { statementsToClose.remove(ps); factory.closePreparedStatement(ps); } public void closeStatement(PreparedStatement ps) throws SQLException { factory.closePreparedStatement(ps); } public PreparedStatement prepareBatchStatement(String sql) throws SQLException, HibernateException { if ( !sql.equals(batchUpdateSQL) ) { batchUpdate=prepareStatement(sql); // calls executeBatch() batchUpdateSQL=sql; } return batchUpdate; } public void executeBatch() throws SQLException, HibernateException { if (batchUpdate!=null) { final PreparedStatement ps = batchUpdate; batchUpdate=null; batchUpdateSQL=null; try { doExecuteBatch(ps); } finally { closeStatement(ps); } } } public void closeStatements() { Iterator iter = statementsToClose.iterator(); while ( iter.hasNext() ) { try { closeStatement( (PreparedStatement) iter.next() ); } catch (SQLException e) { // no big deal log.warn("Could not close a JDBC statement", e); } iter.remove(); } statementsToClose.clear(); } protected abstract void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException; } --- NEW FILE: BatchingBatcher.java --- //$Id: BatchingBatcher.java,v 1.1 2002/10/31 16:58:14 oneovthafew Exp $ package cirrus.hibernate.impl; import java.sql.PreparedStatement; import java.sql.SQLException; import cirrus.hibernate.HibernateException; import cirrus.hibernate.engine.SessionImplementor; import cirrus.hibernate.helpers.JDBCExceptionReporter; /** * An implementation of the <tt>Batcher</tt> interface that actually uses batching */ public class BatchingBatcher extends BatcherImpl { private int batchSize; public BatchingBatcher(SessionImplementor session) { super(session); } public void addToBatch(int expectedRowCount) throws SQLException, HibernateException { log.trace("Adding to batch"); PreparedStatement batchUpdate = getStatement(); batchUpdate.addBatch(); batchSize++; if ( batchSize==factory.getJdbcBatchSize() ) { try { doExecuteBatch(batchUpdate); } catch (SQLException sqle) { closeStatement(batchUpdate); throw sqle; } catch (HibernateException he) { closeStatement(batchUpdate); throw he; } } } protected void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException { if ( log.isDebugEnabled() ) log.debug("Executing batch size: " + batchSize ); try { if (batchSize!=0) { final int[] results = ps.executeBatch(); // check return codes for ( int i=0; i<batchSize; i++ ) { if ( results[i]==-3 ) throw new HibernateException("Batch update failed"); } } } catch(SQLException sqle) { JDBCExceptionReporter.logExceptions(sqle); throw sqle; } catch(RuntimeException re) { log.error("Exception executing batch: ", re); throw re; } finally { batchSize=0; //ps.clearBatch(); } } } --- NEW FILE: NonBatchingBatcher.java --- //$Id: NonBatchingBatcher.java,v 1.1 2002/10/31 16:58:14 oneovthafew Exp $ package cirrus.hibernate.impl; import java.sql.PreparedStatement; import java.sql.SQLException; import cirrus.hibernate.HibernateException; import cirrus.hibernate.engine.SessionImplementor; /** * An implementation of the <tt>Batcher</tt> interface that does no batching */ public class NonBatchingBatcher extends BatcherImpl { public NonBatchingBatcher(SessionImplementor session) { super(session); } public void addToBatch(int expectedRowCount) throws SQLException, HibernateException { int rowCount = getStatement().executeUpdate(); //negative expected row count means we don't know how many rows to expect if ( expectedRowCount>0 && expectedRowCount!=rowCount ) throw new HibernateException("SQL update or deletion failed (row not found)"); } protected void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException { } } Index: SessionImpl.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate/cirrus/hibernate/impl/SessionImpl.java,v retrieving revision 1.144 retrieving revision 1.145 diff -C2 -d -r1.144 -r1.145 *** SessionImpl.java 29 Oct 2002 07:50:40 -0000 1.144 --- SessionImpl.java 31 Oct 2002 16:58:14 -0000 1.145 *************** *** 13,17 **** import java.sql.SQLException; import java.sql.Connection; - import java.sql.PreparedStatement; import java.util.Collection; import java.util.Iterator; --- 13,16 ---- *************** *** 65,69 **** * NOT THREADSAFE */ ! public final class SessionImpl implements SessionImplementor, Batcher { private static final Log log = LogFactory.getLog(SessionImpl.class); --- 64,68 ---- * NOT THREADSAFE */ ! public final class SessionImpl implements SessionImplementor { private static final Log log = LogFactory.getLog(SessionImpl.class); *************** *** 92,96 **** private transient Connection connection; private transient boolean connect; - private transient HashSet statementsToClose; // We keep scheduled insertions, deletions and updates in collections --- 91,94 ---- *************** *** 121,124 **** --- 119,124 ---- private transient int dontFlushFromFind = 0; private transient boolean reentrantCallback = false; + + private transient Batcher batcher; static final class Status implements Serializable { *************** *** 335,339 **** public Batcher getBatcher() { ! return this; } --- 335,343 ---- public Batcher getBatcher() { ! if (batcher==null) batcher = factory.useJdbcBatch() ? ! (Batcher) new BatchingBatcher(this) : ! (Batcher) new NonBatchingBatcher(this); ! ! return batcher; } *************** *** 388,408 **** } - private void closeStatements() { - Iterator iter = statementsToClose.iterator(); - while ( iter.hasNext() ) { - try { - closeStatement( (PreparedStatement) iter.next() ); - } - catch (SQLException e) { - // no big deal - log.warn("Could not close a JDBC statement", e); - } - iter.remove(); - } - statementsToClose.clear(); - } - private void initTransientCollections() { - statementsToClose = new HashSet(); insertions = new ArrayList(20); deletions = new ArrayList(20); --- 392,396 ---- *************** *** 734,743 **** ); - - } - - - private static Integer increment(Integer integer) { - return new Integer( integer.intValue() + 1 ); } --- 722,725 ---- *************** *** 1719,1723 **** iter.remove(); } ! executeBatch(); } --- 1701,1705 ---- iter.remove(); } ! if ( batcher!=null ) batcher.executeBatch(); } *************** *** 2389,2493 **** } - // Connections and Prepared Statements /////////////////////////////////////////////////// - - public PreparedStatement prepareStatement(String sql) throws SQLException, HibernateException { - executeBatch(); - return factory.getPreparedStatement( connection(), sql, false ); - } - public PreparedStatement prepareQueryStatement(String sql, boolean scrollable) throws SQLException, HibernateException { - PreparedStatement ps = factory.getPreparedStatement( connection(), sql, scrollable ); - factory.setFetchSize(ps); - statementsToClose.add(ps); - return ps; - } - - public void closeQueryStatement(PreparedStatement ps) throws SQLException { - statementsToClose.remove(ps); - factory.closePreparedStatement(ps); - } - - public void closeStatement(PreparedStatement ps) throws SQLException { - factory.closePreparedStatement(ps); - } - - private transient PreparedStatement batchUpdate; - private transient String batchUpdateSQL; - private transient int batchSize; - - public PreparedStatement prepareBatchStatement(String sql) throws SQLException, HibernateException { - if ( !sql.equals(batchUpdateSQL) ) { - batchUpdate=prepareStatement(sql); // calls executeBatch() - batchUpdateSQL=sql; - } - return batchUpdate; - } - - public void addToBatch(int expectedRowCount) throws SQLException, HibernateException { - if ( !factory.useJdbcBatch() ) { //ie. not using batches - int rowCount = batchUpdate.executeUpdate(); - if (expectedRowCount>0 && expectedRowCount!=rowCount) throw new HibernateException("SQL update or deletion failed (row not found)"); - } - else { - log.trace("Adding to batch"); - batchUpdate.addBatch(); - batchSize++; - if ( batchSize==factory.getJdbcBatchSize() ) { - try { - doExecuteBatch(batchUpdate); - } - catch (SQLException sqle) { - closeStatement(batchUpdate); - throw sqle; - } - catch (HibernateException he) { - closeStatement(batchUpdate); - throw he; - } - } - } - } - - private void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException { - if ( log.isDebugEnabled() ) - log.debug("Executing batch size: " + batchSize ); - - try { - if (batchSize!=0) { - final int[] results = ps.executeBatch(); - // check return codes - for ( int i=0; i<batchSize; i++ ) { - if ( results[i]==-3 ) throw new HibernateException("Batch update failed"); - } - } - } - catch(SQLException sqle) { - JDBCExceptionReporter.logExceptions(sqle); - throw sqle; - } - catch(RuntimeException re) { - log.error("Exception executing batch: ", re); - throw re; - } - finally { - batchSize=0; - //ps.clearBatch(); - } - } - - - public void executeBatch() throws SQLException, HibernateException { - if (batchUpdate!=null) { - final PreparedStatement ps = batchUpdate; - batchUpdate=null; - batchUpdateSQL=null; - try { - if ( factory.useJdbcBatch() ) doExecuteBatch(ps); - } - finally { - closeStatement(ps); - } - } - } - public Connection connection() throws HibernateException, SQLException { if (connection==null) { --- 2371,2374 ---- *************** *** 2521,2525 **** if (connection==null) throw new HibernateException("Session already disconnected"); ! closeStatements(); Connection c = connection; connection=null; --- 2402,2406 ---- if (connection==null) throw new HibernateException("Session already disconnected"); ! if (batcher!=null) batcher.closeStatements(); Connection c = connection; connection=null; |