[hibernate-commits] Hibernate SVN: r13931 - in sandbox/trunk/jdbc-proxy/src: main/java/org/hibernate/jdbc/batch and 2 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri Aug 17 00:04:34 EDT 2007


Author: steve.ebersole at jboss.com
Date: 2007-08-17 00:04:34 -0400 (Fri, 17 Aug 2007)
New Revision: 13931

Added:
   sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/
   sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/AbstractBatchImpl.java
   sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/Batch.java
   sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchBuilder.java
   sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchObserver.java
   sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchingBatch.java
   sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/NonBatchingBatch.java
   sandbox/trunk/jdbc-proxy/src/test/java/org/hibernate/jdbc/batch/
   sandbox/trunk/jdbc-proxy/src/test/java/org/hibernate/jdbc/batch/BasicBatchTest.java
   sandbox/trunk/jdbc-proxy/src/test/java/org/hibernate/jdbc/batch/TestingServiceImpl.java
Log:
initial batch support on top of proxies

Added: sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/AbstractBatchImpl.java
===================================================================
--- sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/AbstractBatchImpl.java	                        (rev 0)
+++ sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/AbstractBatchImpl.java	2007-08-17 04:04:34 UTC (rev 13931)
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.jdbc.batch;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.jdbc.JDBCServices;
+import org.hibernate.jdbc.impl.LogicalConnectionImplementor;
+import org.hibernate.jdbc.proxy.ProxyBuilder;
+
+/**
+ * AbstractBatchImpl implementation
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractBatchImpl implements Batch {
+	private static final Logger log = LoggerFactory.getLogger( AbstractBatchImpl.class );
+
+	private Object key;
+	private LogicalConnectionImplementor logicalConnection;
+	private Connection connectionProxy;
+	private LinkedHashMap statements = new LinkedHashMap();
+	private LinkedHashSet observers = new LinkedHashSet();
+
+	protected AbstractBatchImpl(Object key, LogicalConnectionImplementor logicalConnection) {
+		this.key = key;
+		this.logicalConnection = logicalConnection;
+		this.connectionProxy = ProxyBuilder.buildConnection( logicalConnection );
+	}
+
+	protected abstract void doExecuteBatch();
+
+	protected JDBCServices getJdbcServices() {
+		return logicalConnection.getJdbcServices();
+	}
+
+	protected LinkedHashMap getStatements() {
+		return statements;
+	}
+
+	public final Object getKey() {
+		return key;
+	}
+
+	public final PreparedStatement getBatchStatement(String sql, boolean callable) {
+		PreparedStatement statement = ( PreparedStatement ) statements.get( sql );
+		if ( statement == null ) {
+			statement = buildBatchStatement( sql, callable );
+			statements.put( sql, statement );
+		}
+		else {
+			log.debug( "reusing batch statement" );
+			logicalConnection.getJdbcServices().getSqlStatementLogger().logStatement( sql );
+		}
+		return statement;
+	}
+
+	private PreparedStatement buildBatchStatement(String sql, boolean callable) {
+		try {
+			if ( callable ) {
+				return connectionProxy.prepareCall( sql );
+			}
+			else {
+				return connectionProxy.prepareStatement( sql );
+			}
+		}
+		catch ( SQLException sqle ) {
+			log.error( "sqlexception escaped proxy", sqle );
+			throw logicalConnection.getJdbcServices().getExceptionHelper().convert( sqle, "could not prepare batch statement", sql );
+		}
+	}
+
+	public final void execute() {
+		notifyObserversExplicitExecution();
+		if ( statements.isEmpty() ) {
+			return;
+		}
+		try {
+			try {
+				doExecuteBatch();
+			}
+			finally {
+				releaseStatements();
+			}
+		}
+		finally {
+			statements.clear();
+		}
+	}
+
+	private void releaseStatements() {
+		Iterator itr = getStatements().entrySet().iterator();
+		while ( itr.hasNext() ) {
+			final Map.Entry entry = ( Map.Entry ) itr.next();
+			try {
+				final PreparedStatement statement = ( PreparedStatement ) entry.getValue();
+				statement.close();
+			}
+			catch ( SQLException e ) {
+				log.error( "unable to release batch statement..." );
+				log.error( "sqlexception escaped proxy", e );
+			}
+		}
+	}
+
+	public void addObserver(BatchObserver observer) {
+		observers.add( observer );
+	}
+
+	private void notifyObserversExplicitExecution() {
+		Iterator itr = observers.iterator();
+		while ( itr.hasNext() ) {
+			( ( BatchObserver ) itr.next() ).batchExplicitlyExecuted();
+		}
+	}
+
+	protected void notifyObserversImplicitExecution() {
+		Iterator itr = observers.iterator();
+		while ( itr.hasNext() ) {
+			( ( BatchObserver ) itr.next() ).batchImplicitlyExecuted();
+		}
+	}
+}

Added: sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/Batch.java
===================================================================
--- sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/Batch.java	                        (rev 0)
+++ sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/Batch.java	2007-08-17 04:04:34 UTC (rev 13931)
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.jdbc.batch;
+
+import java.sql.PreparedStatement;
+
+import org.hibernate.jdbc.Expectation;
+
+/**
+ * Conceptually models a batch, but unlike directly in JDBC, here we add the ability to
+ * batch together multiple statements at a time.
+ *
+ * @author Steve Ebersole
+ */
+public interface Batch {
+	public Object getKey();
+	public void addObserver(BatchObserver observer);
+	public PreparedStatement getBatchStatement(String sql, boolean callable);
+	public void addToBatch(Expectation expectation);
+	public void execute();
+}

Added: sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchBuilder.java
===================================================================
--- sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchBuilder.java	                        (rev 0)
+++ sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchBuilder.java	2007-08-17 04:04:34 UTC (rev 13931)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.jdbc.batch;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.jdbc.impl.LogicalConnectionImplementor;
+
+/**
+ * BatchBuilder implementation
+ *
+ * @author Steve Ebersole
+ */
+public class BatchBuilder {
+	private static final Logger log = LoggerFactory.getLogger( BatchBuilder.class );
+
+	// todo : eventually have this take the Settings; this form is needed for testing because Settings is final :(
+
+	private int size;
+
+	public BatchBuilder() {
+	}
+
+	public BatchBuilder(int size) {
+		this.size = size;
+	}
+
+	public void setSize(int size) {
+		this.size = size;
+	}
+
+	public Batch buildBatch(Object key, LogicalConnectionImplementor logicalConnection) {
+		log.trace( "building batch [size={}]", size );
+		return size > 1
+				? new BatchingBatch( key, logicalConnection, size )
+				: new NonBatchingBatch( key, logicalConnection );
+	}
+}

Added: sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchObserver.java
===================================================================
--- sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchObserver.java	                        (rev 0)
+++ sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchObserver.java	2007-08-17 04:04:34 UTC (rev 13931)
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.jdbc.batch;
+
+/**
+ * BatchObserver contract
+ *
+ * @author Steve Ebersole
+ */
+public interface BatchObserver {
+	public void batchExplicitlyExecuted();
+	public void batchImplicitlyExecuted();
+}

Added: sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchingBatch.java
===================================================================
--- sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchingBatch.java	                        (rev 0)
+++ sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/BatchingBatch.java	2007-08-17 04:04:34 UTC (rev 13931)
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.jdbc.batch;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.jdbc.Expectation;
+import org.hibernate.jdbc.impl.LogicalConnectionImplementor;
+import org.hibernate.HibernateException;
+
+/**
+ * BatchingBatch implementation
+ *
+ * @author Steve Ebersole
+ */
+public class BatchingBatch extends AbstractBatchImpl {
+	private static final Logger log = LoggerFactory.getLogger( BatchingBatch.class );
+
+	private final int batchSize;
+	private Expectation[] expectations;
+	private int batchPosition;
+
+	public BatchingBatch(Object key, LogicalConnectionImplementor logicalConnection, int batchSize) {
+		super( key, logicalConnection );
+		this.batchSize = batchSize;
+		this.expectations = new Expectation[ batchSize ];
+	}
+
+	public void addToBatch(Expectation expectation) {
+		if ( !expectation.canBeBatched() ) {
+			throw new HibernateException( "attempting to batch an operation which cannot be batched" );
+		}
+		Iterator itr = getStatements().entrySet().iterator();
+		while ( itr.hasNext() ) {
+			final Map.Entry entry = ( Map.Entry ) itr.next();
+			try {
+				final PreparedStatement statement = ( PreparedStatement ) entry.getValue();
+				statement.addBatch();
+			}
+			catch ( SQLException e ) {
+				log.error( "sqlexception escaped proxy", e );
+				throw getJdbcServices().getExceptionHelper()
+						.convert( e, "could not perform addBatch", ( String ) entry.getKey() );
+			}
+		}
+		expectations[ batchPosition++ ] = expectation;
+		if ( batchPosition == batchSize ) {
+			notifyObserversImplicitExecution();
+			doExecuteBatch();
+		}
+	}
+
+	protected void doExecuteBatch() {
+		if ( batchPosition == 0 ) {
+			log.debug( "no batched statements to execute" );
+		}
+		else {
+			if ( log.isDebugEnabled() ) {
+				log.debug( "Executing batch size: " + batchPosition );
+			}
+
+			try {
+				Iterator itr = getStatements().entrySet().iterator();
+				while ( itr.hasNext() ) {
+					final Map.Entry entry = ( Map.Entry ) itr.next();
+					try {
+						final PreparedStatement statement = ( PreparedStatement ) entry.getValue();
+						checkRowCounts( statement.executeBatch(), statement );
+					}
+					catch ( SQLException e ) {
+						log.error( "sqlexception escaped proxy", e );
+						throw getJdbcServices().getExceptionHelper()
+								.convert( e, "could not perform addBatch", ( String ) entry.getKey() );
+					}
+				}
+			}
+			catch ( RuntimeException re ) {
+				log.error( "Exception executing batch [{}]", re.getMessage() );
+				throw re;
+			}
+			finally {
+				batchPosition = 0;
+			}
+
+		}
+	}
+
+	private void checkRowCounts(int[] rowCounts, PreparedStatement ps) throws SQLException, HibernateException {
+		int numberOfRowCounts = rowCounts.length;
+		if ( numberOfRowCounts != batchPosition ) {
+			log.warn( "JDBC driver did not return the expected number of row counts" );
+		}
+		for ( int i = 0; i < numberOfRowCounts; i++ ) {
+			expectations[i].verifyOutcome( rowCounts[i], ps, i );
+		}
+	}
+
+}

Added: sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/NonBatchingBatch.java
===================================================================
--- sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/NonBatchingBatch.java	                        (rev 0)
+++ sandbox/trunk/jdbc-proxy/src/main/java/org/hibernate/jdbc/batch/NonBatchingBatch.java	2007-08-17 04:04:34 UTC (rev 13931)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.jdbc.batch;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.jdbc.Expectation;
+import org.hibernate.jdbc.impl.LogicalConnectionImplementor;
+
+/**
+ * NonBatchingBatch implementation
+ *
+ * @author Steve Ebersole
+ */
+public class NonBatchingBatch extends AbstractBatchImpl {
+	private static final Logger log = LoggerFactory.getLogger( NonBatchingBatch.class );
+
+	protected NonBatchingBatch(Object key, LogicalConnectionImplementor logicalConnection) {
+		super( key, logicalConnection );
+	}
+
+	public void addToBatch(Expectation expectation) {
+		notifyObserversImplicitExecution();
+		Iterator itr = getStatements().entrySet().iterator();
+		while ( itr.hasNext() ) {
+			final Map.Entry entry = ( Map.Entry ) itr.next();
+			try {
+				final PreparedStatement statement = ( PreparedStatement ) entry.getValue();
+				final int rowCount = statement.executeUpdate();
+				expectation.verifyOutcome( rowCount, statement, 0 );
+			}
+			catch ( SQLException e ) {
+				log.error( "sqlexception escaped proxy", e );
+				throw getJdbcServices().getExceptionHelper()
+						.convert( e, "could not execute batch statement", ( String ) entry.getKey() );
+			}
+		}
+	}
+
+	protected void doExecuteBatch() {
+		// nothing to do
+	}
+}

Added: sandbox/trunk/jdbc-proxy/src/test/java/org/hibernate/jdbc/batch/BasicBatchTest.java
===================================================================
--- sandbox/trunk/jdbc-proxy/src/test/java/org/hibernate/jdbc/batch/BasicBatchTest.java	                        (rev 0)
+++ sandbox/trunk/jdbc-proxy/src/test/java/org/hibernate/jdbc/batch/BasicBatchTest.java	2007-08-17 04:04:34 UTC (rev 13931)
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.jdbc.batch;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import static org.testng.Assert.*;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.jdbc.Expectations;
+import org.hibernate.jdbc.impl.LogicalConnectionImpl;
+import org.hibernate.jdbc.proxy.ProxyBuilder;
+
+/**
+ * BasicBatchTest implementation
+ *
+ * @author Steve Ebersole
+ */
+public class BasicBatchTest {
+	private static final Logger log = LoggerFactory.getLogger( BasicBatchTest.class );
+
+	private TestingServiceImpl services = new TestingServiceImpl();
+
+	private static class BatchCounter implements BatchObserver {
+		public int explicitBatchCount;
+		public int implicitBatchCount;
+
+		public void batchExplicitlyExecuted() {
+			explicitBatchCount++;
+		}
+
+		public void batchImplicitlyExecuted() {
+			implicitBatchCount++;
+		}
+	}
+
+	@BeforeClass
+	protected void create() {
+		services.prepare( false );
+	}
+
+	@AfterClass
+	protected void destroy() {
+		services.release();
+	}
+
+	@BeforeMethod
+	protected void setUpSchema() throws SQLException {
+		log.debug( "starting @BeforeMethod" );
+		Connection connection = null;
+		Statement stmnt = null;
+		try {
+			connection = services.getConnectionProvider().getConnection();
+			stmnt = connection.createStatement();
+			stmnt.execute( "drop table SANDBOX_JDBC_TST if exists" );
+			stmnt.execute( "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" );
+		}
+		finally {
+			if ( stmnt != null ) {
+				try {
+					stmnt.close();
+				}
+				catch ( SQLException ignore ) {
+					log.warn( "could not close statement used to set up schema", ignore );
+				}
+			}
+			if ( connection != null ) {
+				try {
+					connection.close();
+				}
+				catch ( SQLException ignore ) {
+					log.warn( "could not close connection used to set up schema", ignore );
+				}
+			}
+		}
+	}
+
+	@AfterMethod
+	protected void tearDownSchema() throws SQLException {
+		Connection connection = null;
+		Statement stmnt = null;
+		try {
+			connection = services.getConnectionProvider().getConnection();
+			stmnt = connection.createStatement();
+			stmnt.execute( "drop table SANDBOX_JDBC_TST if exists" );
+		}
+		finally {
+			if ( stmnt != null ) {
+				try {
+					stmnt.close();
+				}
+				catch ( SQLException ignore ) {
+					log.warn( "could not close statement used to set up schema", ignore );
+				}
+			}
+			if ( connection != null ) {
+				try {
+					connection.close();
+				}
+				catch ( SQLException ignore ) {
+					log.warn( "could not close connection used to set up schema", ignore );
+				}
+			}
+		}
+	}
+
+	@Test
+	public void testBatchingBatches() throws SQLException {
+		LogicalConnectionImpl lc = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_TRANSACTION, services );
+		BatchBuilder batchBuilder = new BatchBuilder( 2 );
+
+		// test an explicit batch execution...
+		Batch batch = batchBuilder.buildBatch( this, lc );
+		BatchCounter counter = new BatchCounter();
+		batch.addObserver( counter );
+		PreparedStatement ps = batch.getBatchStatement( "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )", false );
+		ps.setLong( 1, 1 );
+		ps.setString( 2, "name" );
+		batch.addToBatch( Expectations.BASIC );
+		assertTrue( lc.getJdbcContainer().hasRegisteredResources() );
+		assertEquals( 0, counter.explicitBatchCount );
+		assertEquals( 0, counter.implicitBatchCount );
+		batch.execute();
+		assertEquals( 1, getRowCount() );
+		assertFalse( lc.getJdbcContainer().hasRegisteredResources() );
+		assertEquals( 1, counter.explicitBatchCount );
+		assertEquals( 0, counter.implicitBatchCount );
+
+		lc.close();
+		lc = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_TRANSACTION, services );
+
+		// test an implicit batch execution...
+		batch = batchBuilder.buildBatch( this, lc );
+		counter = new BatchCounter();
+		batch.addObserver( counter );
+		ps = batch.getBatchStatement( "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )", false );
+		ps.setLong( 1, 2 );
+		ps.setString( 2, "me" );
+		assertTrue( lc.getJdbcContainer().hasRegisteredResources() );
+		batch.addToBatch( Expectations.BASIC );
+		assertTrue( lc.getJdbcContainer().hasRegisteredResources() );
+		assertEquals( 0, counter.explicitBatchCount );
+		assertEquals( 0, counter.implicitBatchCount );
+		ps.setLong( 1, 3 );
+		ps.setString( 2, "you" );
+		// this should force execution of the batch...
+		batch.addToBatch( Expectations.BASIC );
+		assertEquals( 3, getRowCount() );
+		assertEquals( 0, counter.explicitBatchCount );
+		assertEquals( 1, counter.implicitBatchCount );
+		batch.execute();
+		assertEquals( 3, getRowCount() );
+		assertFalse( lc.getJdbcContainer().hasRegisteredResources() );
+		assertEquals( 1, counter.explicitBatchCount );
+		assertEquals( 1, counter.implicitBatchCount );
+		lc.close();
+	}
+
+	private int getRowCount() throws SQLException {
+		LogicalConnectionImpl lc = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_TRANSACTION, services );
+		try {
+			Connection conn = ProxyBuilder.buildConnection( lc );
+			ResultSet rs = conn.createStatement().executeQuery( "select count(*) from SANDBOX_JDBC_TST" );
+			assert true == rs.next();
+			return rs.getInt( 1 );
+		}
+		finally {
+			lc.close();
+		}
+	}
+
+	@Test
+	public void testNonBatchingBatches() throws SQLException {
+		LogicalConnectionImpl lc = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_TRANSACTION, services );
+		BatchBuilder batchBuilder = new BatchBuilder( -1 );
+
+		Batch batch = batchBuilder.buildBatch( this, lc );
+		BatchCounter counter = new BatchCounter();
+		batch.addObserver( counter );
+		PreparedStatement ps = batch.getBatchStatement( "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )", false );
+		ps.setLong( 1, 1 );
+		ps.setString( 2, "name" );
+		batch.addToBatch( Expectations.BASIC );
+		assertEquals( 1, getRowCount() );
+		assertTrue( lc.getJdbcContainer().hasRegisteredResources() );
+		assertEquals( 0, counter.explicitBatchCount );
+		assertEquals( 1, counter.implicitBatchCount );
+		batch.execute();
+		assertEquals( 1, getRowCount() );
+		assertFalse( lc.getJdbcContainer().hasRegisteredResources() );
+		assertEquals( 1, counter.explicitBatchCount );
+		assertEquals( 1, counter.implicitBatchCount );
+		lc.close();
+	}
+}

Copied: sandbox/trunk/jdbc-proxy/src/test/java/org/hibernate/jdbc/batch/TestingServiceImpl.java (from rev 13928, sandbox/trunk/jdbc-proxy/src/test/java/org/hibernate/jdbc/proxy/TestingServiceImpl.java)
===================================================================
--- sandbox/trunk/jdbc-proxy/src/test/java/org/hibernate/jdbc/batch/TestingServiceImpl.java	                        (rev 0)
+++ sandbox/trunk/jdbc-proxy/src/test/java/org/hibernate/jdbc/batch/TestingServiceImpl.java	2007-08-17 04:04:34 UTC (rev 13931)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.jdbc.batch;
+
+import java.sql.SQLException;
+
+import org.hibernate.cfg.Settings;
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.exception.SQLStateConverter;
+import org.hibernate.exception.ViolatedConstraintNameExtracter;
+import org.hibernate.jdbc.ConnectionProviderBuilder;
+import org.hibernate.jdbc.JDBCContainer;
+import org.hibernate.jdbc.JDBCContainerBuilder;
+import org.hibernate.jdbc.JDBCServices;
+import org.hibernate.jdbc.proxy.ProxyJDBCContainer;
+import org.hibernate.jdbc.util.ExceptionHelper;
+import org.hibernate.jdbc.util.SQLStatementLogger;
+
+/**
+ * TestingServiceImpl implementation
+ *
+ * @author Steve Ebersole
+ */
+public class TestingServiceImpl implements JDBCServices {
+	private ConnectionProvider connectionProvider;
+	private SQLStatementLogger sqlStatementLogger;
+	private JDBCContainerBuilder jdbcContainerBuilder;
+	private ExceptionHelper exceptionHelper;
+
+	public void prepare(boolean allowAggressiveRelease) {
+		connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease );
+		sqlStatementLogger = new SQLStatementLogger( true );
+		exceptionHelper = new ExceptionHelper(
+				new SQLStateConverter(
+						new ViolatedConstraintNameExtracter() {
+							public String extractConstraintName(SQLException e) {
+								return null;
+							}
+						}
+				)
+		);
+		jdbcContainerBuilder = new JDBCContainerBuilder() {
+			public JDBCContainer buildJdbcContainer() {
+				return new ProxyJDBCContainer( exceptionHelper );
+			}
+		};
+	}
+
+	public void release() {
+		connectionProvider.close();
+	}
+
+	public ConnectionProvider getConnectionProvider() {
+		return connectionProvider;
+	}
+
+	public JDBCContainerBuilder getJdbcContainerBuilder() {
+		return jdbcContainerBuilder;
+	}
+
+	public SQLStatementLogger getSqlStatementLogger() {
+		return sqlStatementLogger;
+	}
+
+	public ExceptionHelper getExceptionHelper() {
+		return exceptionHelper;
+	}
+}
\ No newline at end of file




More information about the hibernate-commits mailing list