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