/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.test.jdbc.internal; import java.sql.PreparedStatement; import java.sql.Statement; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.batch.internal.BatchBuilderImpl; import org.hibernate.engine.jdbc.batch.internal.BatchingBatch; import org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch; import org.hibernate.engine.jdbc.batch.spi.Batch; import org.hibernate.engine.jdbc.batch.spi.BatchBuilder; import org.hibernate.engine.jdbc.batch.spi.BatchKey; import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectations; import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.test.common.JournalingBatchObserver; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; /** * @author Steve Ebersole * @author Brett Meyer */ public class BatchingTest extends BaseCoreFunctionalTestCase implements BatchKey { @Override public int getBatchedStatementCount() { return 1; } @Override public Expectation getExpectation() { return Expectations.BASIC; } @Test public void testNonBatchingUsage() throws Exception { Session session = openSession(); SessionImplementor sessionImpl = (SessionImplementor) session; final JdbcCoordinator jdbcCoordinator = sessionImpl.getJdbcCoordinator(); LogicalConnectionImplementor logicalConnection = jdbcCoordinator.getLogicalConnection(); // set up some tables to use Statement statement = jdbcCoordinator.getStatementPreparer().createStatement(); String dropSql = getDialect().getDropTableString( "SANDBOX_JDBC_TST" ); try { jdbcCoordinator.getResultSetReturn().execute( statement, dropSql ); } catch ( Exception e ) { // ignore if the DB doesn't support "if exists" and the table doesn't exist } jdbcCoordinator.getResultSetReturn().execute( statement, "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" ); assertTrue( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); assertTrue( logicalConnection.isPhysicallyConnected() ); jdbcCoordinator.getResourceRegistry().release( statement ); assertFalse( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); assertTrue( logicalConnection.isPhysicallyConnected() ); // after_transaction specified // ok, now we can get down to it... Transaction txn = session.getTransaction(); // same as Session#getTransaction txn.begin(); final String insertSql = "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )"; final BatchBuilder batchBuilder = new BatchBuilderImpl( -1 ); final BatchKey batchKey = new BasicBatchKey( "this", Expectations.BASIC ); final Batch insertBatch = batchBuilder.buildBatch( batchKey, jdbcCoordinator ); final JournalingBatchObserver batchObserver = new JournalingBatchObserver(); insertBatch.addObserver( batchObserver ); assertTrue( "unexpected Batch impl", NonBatchingBatch.class.isInstance( insertBatch ) ); PreparedStatement insert = insertBatch.getBatchStatement( insertSql, false ); insert.setLong( 1, 1 ); insert.setString( 2, "name" ); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 0, batchObserver.getImplicitExecutionCount() ); insertBatch.addToBatch(); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 1, batchObserver.getImplicitExecutionCount() ); assertFalse( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); insertBatch.execute(); assertEquals( 1, batchObserver.getExplicitExecutionCount() ); assertEquals( 1, batchObserver.getImplicitExecutionCount() ); assertFalse( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); insertBatch.release(); txn.commit(); session.close(); } @Test public void testBatchingUsage() throws Exception { Session session = openSession(); SessionImplementor sessionImpl = (SessionImplementor) session; final JdbcCoordinator jdbcCoordinator = sessionImpl.getJdbcCoordinator(); LogicalConnectionImplementor logicalConnection = jdbcCoordinator.getLogicalConnection(); // set up some tables to use Statement statement = jdbcCoordinator.getStatementPreparer().createStatement(); String dropSql = getDialect().getDropTableString( "SANDBOX_JDBC_TST" ); try { jdbcCoordinator.getResultSetReturn().execute( statement, dropSql ); } catch ( Exception e ) { // ignore if the DB doesn't support "if exists" and the table doesn't exist } jdbcCoordinator.getResultSetReturn().execute( statement, "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" ); assertTrue( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); assertTrue( logicalConnection.isPhysicallyConnected() ); jdbcCoordinator.getResourceRegistry().release( statement ); assertFalse( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); assertTrue( logicalConnection.isPhysicallyConnected() ); // after_transaction specified // ok, now we can get down to it... Transaction txn = session.getTransaction(); // same as Session#getTransaction txn.begin(); final BatchBuilder batchBuilder = new BatchBuilderImpl( 2 ); final BatchKey batchKey = new BasicBatchKey( "this", Expectations.BASIC ); final Batch insertBatch = batchBuilder.buildBatch( batchKey, jdbcCoordinator ); assertTrue( "unexpected Batch impl", BatchingBatch.class.isInstance( insertBatch ) ); final JournalingBatchObserver batchObserver = new JournalingBatchObserver(); insertBatch.addObserver( batchObserver ); final String insertSql = "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )"; PreparedStatement insert = insertBatch.getBatchStatement( insertSql, false ); insert.setLong( 1, 1 ); insert.setString( 2, "name" ); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 0, batchObserver.getImplicitExecutionCount() ); insertBatch.addToBatch(); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 0, batchObserver.getImplicitExecutionCount() ); assertTrue( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); PreparedStatement insert2 = insertBatch.getBatchStatement( insertSql, false ); assertSame( insert, insert2 ); insert = insert2; insert.setLong( 1, 2 ); insert.setString( 2, "another name" ); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 0, batchObserver.getImplicitExecutionCount() ); insertBatch.addToBatch(); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 1, batchObserver.getImplicitExecutionCount() ); assertTrue( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); insertBatch.execute(); assertEquals( 1, batchObserver.getExplicitExecutionCount() ); assertEquals( 1, batchObserver.getImplicitExecutionCount() ); assertFalse( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); insertBatch.release(); txn.commit(); session.close(); } @Test public void testSessionBatchingUsage() throws Exception { Session session = openSession(); session.setJdbcBatchSize( 3 ); SessionImplementor sessionImpl = (SessionImplementor) session; final JdbcCoordinator jdbcCoordinator = sessionImpl.getJdbcCoordinator(); LogicalConnectionImplementor logicalConnection = jdbcCoordinator.getLogicalConnection(); // set up some tables to use Statement statement = jdbcCoordinator.getStatementPreparer().createStatement(); String dropSql = getDialect().getDropTableString( "SANDBOX_JDBC_TST" ); try { jdbcCoordinator.getResultSetReturn().execute( statement, dropSql ); } catch ( Exception e ) { // ignore if the DB doesn't support "if exists" and the table doesn't exist } jdbcCoordinator.getResultSetReturn().execute( statement, "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" ); assertTrue( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); assertTrue( logicalConnection.isPhysicallyConnected() ); jdbcCoordinator.getResourceRegistry().release( statement ); assertFalse( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); assertTrue( logicalConnection.isPhysicallyConnected() ); // after_transaction specified // ok, now we can get down to it... Transaction txn = session.getTransaction(); // same as Session#getTransaction txn.begin(); final BatchBuilder batchBuilder = new BatchBuilderImpl( 2 ); final BatchKey batchKey = new BasicBatchKey( "this", Expectations.BASIC ); final Batch insertBatch = batchBuilder.buildBatch( batchKey, jdbcCoordinator ); assertTrue( "unexpected Batch impl", BatchingBatch.class.isInstance( insertBatch ) ); final JournalingBatchObserver batchObserver = new JournalingBatchObserver(); insertBatch.addObserver( batchObserver ); final String insertSql = "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )"; PreparedStatement insert = insertBatch.getBatchStatement( insertSql, false ); insert.setLong( 1, 1 ); insert.setString( 2, "name" ); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 0, batchObserver.getImplicitExecutionCount() ); insertBatch.addToBatch(); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 0, batchObserver.getImplicitExecutionCount() ); assertTrue( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); PreparedStatement insert2 = insertBatch.getBatchStatement( insertSql, false ); assertSame( insert, insert2 ); insert = insert2; insert.setLong( 1, 2 ); insert.setString( 2, "another name" ); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 0, batchObserver.getImplicitExecutionCount() ); insertBatch.addToBatch(); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 0, batchObserver.getImplicitExecutionCount() ); assertTrue( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); PreparedStatement insert3 = insertBatch.getBatchStatement( insertSql, false ); assertSame( insert, insert3 ); insert = insert3; insert.setLong( 1, 3 ); insert.setString( 2, "yet another name" ); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 0, batchObserver.getImplicitExecutionCount() ); insertBatch.addToBatch(); assertEquals( 0, batchObserver.getExplicitExecutionCount() ); assertEquals( 1, batchObserver.getImplicitExecutionCount() ); assertTrue( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); insertBatch.execute(); assertEquals( 1, batchObserver.getExplicitExecutionCount() ); assertEquals( 1, batchObserver.getImplicitExecutionCount() ); assertFalse( jdbcCoordinator.getResourceRegistry().hasRegisteredResources() ); insertBatch.release(); txn.commit(); session.close(); } @Override protected void cleanupTest() throws Exception { try (Session session = openSession()) { session.doWork( connection -> { final Statement stmnt = connection.createStatement(); stmnt.execute( getDialect().getDropTableString( "SANDBOX_JDBC_TST" ) ); } ); } } }