HHH-5765 : Refactor JDBCContext/ConnectionManager spi/impl and to use new proxies

This commit is contained in:
Gail Badner 2010-12-08 17:23:44 -08:00
parent cc4055d50c
commit b006a6c3c5
72 changed files with 1327 additions and 1177 deletions
hibernate-core/src
main/java/org/hibernate
cfg
context
dialect/lock
engine
hql/ast/exec
id
impl
jdbc
loader
persister
transaction
type
test
hibernate-entitymanager/src/main/java/org/hibernate/ejb/transaction
hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy

View File

@ -30,6 +30,7 @@ import org.hibernate.EntityMode;
import org.hibernate.cache.QueryCacheFactory;
import org.hibernate.cache.RegionFactory;
import org.hibernate.engine.jdbc.JdbcSupport;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilder;
import org.hibernate.hql.QueryTranslatorFactory;
import org.hibernate.jdbc.BatcherFactory;
import org.hibernate.jdbc.util.SQLStatementLogger;
@ -78,6 +79,7 @@ public final class Settings {
private TransactionFactory transactionFactory;
private TransactionManagerLookup transactionManagerLookup;
private BatcherFactory batcherFactory;
private BatchBuilder batchBuilder;
private QueryTranslatorFactory queryTranslatorFactory;
private boolean wrapResultSetsEnabled;
private boolean orderUpdatesEnabled;
@ -230,6 +232,10 @@ public final class Settings {
return batcherFactory;
}
public BatchBuilder getBatchBuilder() {
return batchBuilder;
}
public boolean isAutoCloseSessionEnabled() {
return autoCloseSessionEnabled;
}
@ -417,6 +423,10 @@ public final class Settings {
this.batcherFactory = batcher;
}
void setBatcherBuilder(BatchBuilder batchBuilder) {
this.batchBuilder = batchBuilder;
}
void setAutoCloseSessionEnabled(boolean autoCloseSessionEnabled) {
this.autoCloseSessionEnabled = autoCloseSessionEnabled;
}

View File

@ -39,6 +39,7 @@ import org.hibernate.cache.QueryCacheFactory;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.impl.NoCachingRegionFactory;
import org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilder;
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.hql.QueryTranslatorFactory;
@ -115,6 +116,7 @@ public class SettingsFactory implements Serializable {
if (batchSize>0) log.info("JDBC batch updates for versioned data: " + enabledDisabled(jdbcBatchVersionedData) );
settings.setJdbcBatchVersionedData(jdbcBatchVersionedData);
settings.setBatcherFactory( createBatcherFactory(properties, batchSize) );
settings.setBatcherBuilder( createBatchBuilder(properties, batchSize) );
boolean useScrollableResultSets = ConfigurationHelper.getBoolean(Environment.USE_SCROLLABLE_RESULTSET, properties, meta.supportsScrollableResults());
log.info("Scrollable result sets: " + enabledDisabled(useScrollableResultSets) );
@ -350,20 +352,45 @@ public class SettingsFactory implements Serializable {
protected BatcherFactory createBatcherFactory(Properties properties, int batchSize) {
String batcherClass = properties.getProperty(Environment.BATCH_STRATEGY);
BatcherFactory batcherFactory = null;
if (batcherClass==null) {
return batchSize == 0
batcherFactory = batchSize == 0
? new NonBatchingBatcherFactory()
: new BatchingBatcherFactory();
: new BatchingBatcherFactory( );
}
else {
log.info("Batcher factory: " + batcherClass);
try {
return (BatcherFactory) ReflectHelper.classForName(batcherClass).newInstance();
batcherFactory = (BatcherFactory) ReflectHelper.classForName(batcherClass).newInstance();
}
catch (Exception cnfe) {
throw new HibernateException("could not instantiate BatcherFactory: " + batcherClass, cnfe);
}
}
batcherFactory.setJdbcBatchSize( batchSize );
return batcherFactory;
}
protected BatchBuilder createBatchBuilder(Properties properties, int batchSize) {
//FIXME: uncomment to use BatchBuilder
/*
String batchBuilderClass = properties.getProperty(Environment.BATCH_STRATEGY);
if (batchBuilderClass==null) {
return batchSize > 0
? new BatchBuilder( batchSize )
: new BatchBuilder();
}
else {
log.info("Batcher factory: " + batchBuilderClass);
try {
return (BatchBuilder) ReflectHelper.classForName(batchBuilderClass).newInstance();
}
catch (Exception cnfe) {
throw new HibernateException("could not instantiate BatchBuilder: " + batchBuilderClass, cnfe);
}
}
*/
return null;
}
protected TransactionFactory createTransactionFactory(Properties properties) {

View File

@ -76,7 +76,7 @@ public class ThreadLocalSessionContext implements CurrentSessionContext {
private static final Class[] SESS_PROXY_INTERFACES = new Class[] {
org.hibernate.classic.Session.class,
org.hibernate.engine.SessionImplementor.class,
org.hibernate.jdbc.JDBCContext.Context.class,
org.hibernate.engine.jdbc.spi.JDBCContext.Context.class,
org.hibernate.event.EventSource.class
};

View File

@ -29,7 +29,6 @@ import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.sql.SimpleSelect;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.LockMode;
import org.hibernate.StaleObjectStateException;
import org.hibernate.JDBCException;
@ -79,7 +78,7 @@ public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingS
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
@ -106,7 +105,7 @@ public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingS
}
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}

View File

@ -29,7 +29,6 @@ import java.sql.SQLException;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.Update;
@ -95,7 +94,7 @@ public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
}
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
@ -115,7 +114,7 @@ public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}

View File

@ -33,7 +33,6 @@ import org.hibernate.LockMode;
import org.hibernate.PessimisticLockException;
import org.hibernate.sql.SimpleSelect;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.exception.JDBCExceptionHelper;
import java.io.Serializable;
import java.sql.PreparedStatement;
@ -79,7 +78,7 @@ public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLocking
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
@ -106,7 +105,7 @@ public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLocking
}
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}

View File

@ -29,7 +29,6 @@ import java.sql.SQLException;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.Update;
@ -95,7 +94,7 @@ public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
}
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
@ -115,7 +114,7 @@ public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}

View File

@ -32,7 +32,6 @@ import org.hibernate.JDBCException;
import org.hibernate.LockMode;
import org.hibernate.sql.SimpleSelect;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.exception.JDBCExceptionHelper;
import java.io.Serializable;
import java.sql.PreparedStatement;
@ -74,7 +73,7 @@ public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
@ -101,7 +100,7 @@ public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
}
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}

View File

@ -33,7 +33,6 @@ import org.hibernate.LockMode;
import org.hibernate.StaleObjectStateException;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.Update;
@ -93,7 +92,7 @@ public class UpdateLockingStrategy implements LockingStrategy {
// todo : should we additionally check the current isolation mode explicitly?
SessionFactoryImplementor factory = session.getFactory();
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
@ -113,7 +112,7 @@ public class UpdateLockingStrategy implements LockingStrategy {
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}

View File

@ -265,7 +265,7 @@ public class ActionQueue {
execute( ( Executable ) list.get( i ) );
}
list.clear();
session.getBatcher().executeBatch();
session.getJDBCContext().getConnectionManager().executeBatch();
}
public void execute(Executable executable) {

View File

@ -29,7 +29,6 @@ import java.sql.Connection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.CacheMode;
import org.hibernate.EntityMode;
@ -40,13 +39,11 @@ import org.hibernate.Query;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Transaction;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.event.EventListeners;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.jdbc.Batcher;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.loader.custom.CustomQuery;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.Type;
@ -116,11 +113,7 @@ public interface SessionImplementor extends Serializable {
* Get the creating <tt>SessionFactoryImplementor</tt>
*/
public SessionFactoryImplementor getFactory();
/**
* Get the prepared statement <tt>Batcher</tt> for this session
*/
public Batcher getBatcher();
/**
* Execute a <tt>find()</tt> query
*/

View File

@ -22,23 +22,32 @@
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.jdbc;
package org.hibernate.engine.jdbc.internal;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.AssertionFailure;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.ScrollMode;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
import org.hibernate.engine.jdbc.spi.ConnectionManager;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.jdbc.spi.LogicalConnection;
import org.hibernate.jdbc.Batcher;
import org.hibernate.jdbc.Expectation;
/**
* Encapsulates JDBC Connection management logic needed by Hibernate.
@ -48,92 +57,71 @@ import org.hibernate.engine.jdbc.spi.ConnectionObserver;
*
* @author Steve Ebersole
*/
public class ConnectionManager implements Serializable {
public class ConnectionManagerImpl implements ConnectionManager {
private static final Logger log = LoggerFactory.getLogger( ConnectionManager.class );
private static final Logger log = LoggerFactory.getLogger( ConnectionManagerImpl.class );
// TODO: check if it's ok to change the method names in Callback
public static interface Callback extends ConnectionObserver {
public boolean isTransactionInProgress();
}
// TODO: check if it's ok to change the method names in Callback
private transient SessionFactoryImplementor factory;
private transient Connection proxiedConnection;
private transient Interceptor interceptor;
private final Callback callback;
private transient LogicalConnectionImpl connection;
private transient Batcher batcher;
private transient Interceptor interceptor;
private transient LogicalConnectionImpl logicalConnection;
/**
* Constructs a ConnectionManager.
* <p/>
* This is the form used internally.
*
* @param factory The SessionFactory.
* @param callback An observer for internal state change.
* @param releaseMode The mode by which to release JDBC connections.
* @param connection An externally supplied connection.
* @param suppliedConnection An externally supplied connection.
*/
public ConnectionManager(
public ConnectionManagerImpl(
SessionFactoryImplementor factory,
Callback callback,
ConnectionReleaseMode releaseMode,
Connection connection,
Connection suppliedConnection,
Interceptor interceptor) {
this.factory = factory;
this.callback = callback;
this.interceptor = interceptor;
this.batcher = factory.getSettings().getBatcherFactory().createBatcher( this, interceptor );
setupConnection( connection, releaseMode );
this( factory,
callback,
interceptor,
new LogicalConnectionImpl(
suppliedConnection,
releaseMode,
factory.getJdbcServices(),
factory.getStatistics() != null ? factory.getStatisticsImplementor() : null,
factory.getSettings().getBatcherFactory()
)
);
}
/**
* Private constructor used exclusively from custom serialization
*/
private ConnectionManager(
private ConnectionManagerImpl(
SessionFactoryImplementor factory,
Callback callback,
ConnectionReleaseMode releaseMode,
Interceptor interceptor
Interceptor interceptor,
LogicalConnectionImpl logicalConnection
) {
this.factory = factory;
this.callback = callback;
this.interceptor = interceptor;
this.batcher = factory.getSettings().getBatcherFactory().createBatcher( this, interceptor );
setupConnection( logicalConnection );
}
private void setupConnection(Connection suppliedConnection,
ConnectionReleaseMode releaseMode
) {
connection =
new LogicalConnectionImpl(
suppliedConnection,
releaseMode,
factory.getJdbcServices()
);
connection.addObserver( callback );
}
/**
* The session factory.
*
* @return the session factory.
*/
public SessionFactoryImplementor getFactory() {
return factory;
}
/**
* The batcher managed by this ConnectionManager.
*
* @return The batcher.
*/
public Batcher getBatcher() {
return batcher;
private void setupConnection(LogicalConnectionImpl logicalConnection) {
this.logicalConnection = logicalConnection;
this.logicalConnection.addObserver( callback );
proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
}
/**
@ -148,21 +136,24 @@ public class ConnectionManager implements Serializable {
* @throws HibernateException Indicates a connection is currently not
* available (we are currently manually disconnected).
*/
@Override
public Connection getConnection() throws HibernateException {
return connection.getConnection();
return logicalConnection.getConnection();
}
@Override
public boolean hasBorrowedConnection() {
// used from testsuite
return connection.hasBorrowedConnection();
return logicalConnection.hasBorrowedConnection();
}
public Connection borrowConnection() {
return connection.borrowConnection();
return logicalConnection.borrowConnection();
}
@Override
public void releaseBorrowedConnection() {
connection.releaseBorrowedConnection();
logicalConnection.releaseBorrowedConnection();
}
/**
@ -174,10 +165,10 @@ public class ConnectionManager implements Serializable {
* @throws SQLException Can be thrown by the Connection.isAutoCommit() check.
*/
public boolean isAutoCommit() throws SQLException {
return connection == null ||
! connection.isOpen() ||
! connection.isPhysicallyConnected() ||
connection.getConnection().getAutoCommit();
return logicalConnection == null ||
! logicalConnection.isOpen() ||
! logicalConnection.isPhysicallyConnected() ||
logicalConnection.getConnection().getAutoCommit();
}
/**
@ -194,10 +185,10 @@ public class ConnectionManager implements Serializable {
* @return True if the connections will be released after each statement; false otherwise.
*/
public boolean isAggressiveRelease() {
if ( connection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_STATEMENT ) {
if ( logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_STATEMENT ) {
return true;
}
else if ( connection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION ) {
else if ( logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION ) {
boolean inAutoCommitState;
try {
inAutoCommitState = isAutoCommit() && ! callback.isTransactionInProgress();
@ -223,7 +214,7 @@ public class ConnectionManager implements Serializable {
* @return True if the connections will be released after each statement; false otherwise.
*/
private boolean isAggressiveReleaseNoTransactionCheck() {
if ( connection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_STATEMENT ) {
if ( logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_STATEMENT ) {
return true;
}
else {
@ -235,7 +226,7 @@ public class ConnectionManager implements Serializable {
// assume we are in an auto-commit state
inAutoCommitState = true;
}
return connection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION && inAutoCommitState;
return logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION && inAutoCommitState;
}
}
@ -246,18 +237,9 @@ public class ConnectionManager implements Serializable {
*
* @return True if logically connected; false otherwise.
*/
@Override
public boolean isCurrentlyConnected() {
if ( connection != null ) {
if ( connection.isUserSuppliedConnection() ) {
return connection.isPhysicallyConnected();
}
else {
return connection.isOpen();
}
}
else {
return false;
}
return logicalConnection != null && logicalConnection.isLogicallyConnected();
}
/**
@ -265,14 +247,10 @@ public class ConnectionManager implements Serializable {
* conditionally release the JDBC connection aggressively if
* the configured release mode indicates.
*/
@Override
public void afterStatement() {
if ( isAggressiveRelease() ) {
if ( batcher.hasOpenResources() ) {
log.debug( "skipping aggresive-release due to open resources on batcher" );
}
else {
connection.afterStatementExecution();
}
logicalConnection.afterStatementExecution();
}
}
@ -282,33 +260,32 @@ public class ConnectionManager implements Serializable {
* indicates.
*/
public void afterTransaction() {
if ( connection != null ) {
if ( isAfterTransactionRelease() ) {
connection.afterTransaction();
}
else if ( isAggressiveReleaseNoTransactionCheck() && batcher.hasOpenResources() ) {
log.info( "forcing batcher resource cleanup on transaction completion; forgot to close ScrollableResults/Iterator?" );
batcher.closeStatements();
connection.afterTransaction();
if ( logicalConnection != null ) {
if ( isAfterTransactionRelease() || isAggressiveReleaseNoTransactionCheck() ) {
logicalConnection.afterTransaction();
}
else if ( isOnCloseRelease() ) {
// log a message about potential connection leaks
log.debug( "transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!" );
}
}
batcher.unsetTransactionTimeout();
}
private boolean isAfterTransactionRelease() {
return connection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION;
return logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION;
}
private boolean isOnCloseRelease() {
return connection.getConnectionReleaseMode() == ConnectionReleaseMode.ON_CLOSE;
return logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.ON_CLOSE;
}
public boolean isLogicallyConnected() {
return connection != null && connection.isOpen();
return logicalConnection != null && logicalConnection.isOpen();
}
@Override
public void setTransactionTimeout(int seconds) {
logicalConnection.setTransactionTimeout( seconds );
}
/**
@ -318,6 +295,7 @@ public class ConnectionManager implements Serializable {
* @return The connection mantained here at time of close. Null if
* there was no connection cached internally.
*/
@Override
public Connection close() {
return cleanup();
}
@ -329,12 +307,12 @@ public class ConnectionManager implements Serializable {
* @return The connection mantained here at time of disconnect. Null if
* there was no connection cached internally.
*/
@Override
public Connection manualDisconnect() {
if ( ! isLogicallyConnected() ) {
throw new IllegalStateException( "cannot manually disconnect because not logically connected." );
}
batcher.closeStatements();
return connection.manualDisconnect();
return logicalConnection.manualDisconnect();
}
/**
@ -343,6 +321,7 @@ public class ConnectionManager implements Serializable {
* <p/>
* This form is used for ConnectionProvider-supplied connections.
*/
@Override
public void manualReconnect() {
manualReconnect( null );
}
@ -353,11 +332,12 @@ public class ConnectionManager implements Serializable {
* <p/>
* This form is used for user-supplied connections.
*/
@Override
public void manualReconnect(Connection suppliedConnection) {
if ( ! isLogicallyConnected() ) {
throw new IllegalStateException( "cannot manually disconnect because not logically connected." );
}
connection.reconnect( suppliedConnection );
logicalConnection.reconnect( suppliedConnection );
}
/**
@ -371,21 +351,17 @@ public class ConnectionManager implements Serializable {
* @throws HibernateException
*/
private Connection cleanup() throws HibernateException {
if ( connection == null ) {
if ( logicalConnection == null ) {
log.trace( "connection already null in cleanup : no action");
return null;
}
try {
log.trace( "performing cleanup" );
if ( isLogicallyConnected() ) {
batcher.closeStatements();
}
Connection c = connection.close();
Connection c = logicalConnection.close();
return c;
}
finally {
connection = null;
logicalConnection = null;
}
}
@ -394,23 +370,192 @@ public class ConnectionManager implements Serializable {
* to temporarily circumvent aggressive connection releasing until after
* the flush cycle is complete {@link #flushEnding()}
*/
@Override
public void flushBeginning() {
log.trace( "registering flush begin" );
connection.disableReleases();
logicalConnection.disableReleases();
}
/**
* Callback to let us know that a flush is ending. We use this fact to
* stop circumventing aggressive releasing connections.
*/
@Override
public void flushEnding() {
log.trace( "registering flush end" );
connection.enableReleases();
logicalConnection.enableReleases();
afterStatement();
}
/**
* Get a non-batchable prepared statement to use for inserting / deleting / updating,
* using JDBC3 getGeneratedKeys ({@link java.sql.Connection#prepareStatement(String, int)}).
*/
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException, HibernateException {
if ( autoGeneratedKeys == PreparedStatement.RETURN_GENERATED_KEYS ) {
checkAutoGeneratedKeysSupportEnabled();
}
executeBatch();
return proxiedConnection.prepareStatement(
getSQL( sql ),
autoGeneratedKeys
);
}
/**
* Get a non-batchable prepared statement to use for inserting / deleting / updating.
* using JDBC3 getGeneratedKeys ({@link java.sql.Connection#prepareStatement(String, String[])}).
*/
public PreparedStatement prepareStatement(String sql, String[] columnNames)
throws SQLException, HibernateException {
checkAutoGeneratedKeysSupportEnabled();
executeBatch();
return proxiedConnection.prepareStatement( getSQL( sql ), columnNames );
}
private void checkAutoGeneratedKeysSupportEnabled() {
if ( ! factory.getSettings().isGetGeneratedKeysEnabled() ) {
throw new AssertionFailure("getGeneratedKeys() support is not enabled");
}
}
/**
* Get a non-batchable prepared statement to use for selecting. Does not
* result in execution of the current batch.
*/
public PreparedStatement prepareSelectStatement(String sql)
throws SQLException, HibernateException {
return proxiedConnection.prepareStatement( getSQL( sql ) );
}
/**
* Get a non-batchable prepared statement to use for inserting / deleting / updating.
*/
public PreparedStatement prepareStatement(String sql, boolean isCallable)
throws SQLException, HibernateException {
return isCallable ? prepareCallableStatement( sql ) : prepareStatement( sql );
}
/**
* Get a non-batchable callable statement to use for inserting / deleting / updating.
*/
public CallableStatement prepareCallableStatement(String sql) throws SQLException, HibernateException {
executeBatch();
log.trace("preparing callable statement");
return CallableStatement.class.cast(
proxiedConnection.prepareStatement( getSQL( sql ) )
);
}
/**
* Get a batchable prepared statement to use for inserting / deleting / updating
* (might be called many times before a single call to <tt>executeBatch()</tt>).
* After setting parameters, call <tt>addToBatch</tt> - do not execute the
* statement explicitly.
* @see org.hibernate.jdbc.Batcher#addToBatch
*/
public PreparedStatement prepareBatchStatement(String sql, boolean isCallable)
throws SQLException, HibernateException {
String batchUpdateSQL = getSQL( sql );
PreparedStatement batchUpdate = getBatcher().getStatement( batchUpdateSQL );
if ( batchUpdate == null ) {
batchUpdate = prepareStatement( batchUpdateSQL, isCallable ); // calls executeBatch()
getBatcher().setStatement( batchUpdateSQL, batchUpdate );
}
else {
log.debug( "reusing prepared statement" );
factory.getJdbcServices().getSqlStatementLogger().logStatement( batchUpdateSQL );
}
return batchUpdate;
}
private Batcher getBatcher() {
return logicalConnection.getBatcher();
}
private PreparedStatement prepareStatement(String sql)
throws SQLException, HibernateException {
executeBatch();
return proxiedConnection.prepareStatement( getSQL( sql ) );
}
/**
* Get a prepared statement for use in loading / querying. If not explicitly
* released by <tt>closeQueryStatement()</tt>, it will be released when the
* session is closed or disconnected.
*/
public PreparedStatement prepareQueryStatement(
String sql,
boolean isCallable) throws SQLException, HibernateException {
sql = getSQL( sql );
PreparedStatement result = (
isCallable ?
proxiedConnection.prepareCall(sql ) :
proxiedConnection.prepareStatement( sql )
);
setStatementFetchSize( result );
logicalConnection.getResourceRegistry().registerLastQuery( result );
return result;
}
/**
* Cancel the current query statement
*/
public void cancelLastQuery() throws HibernateException {
logicalConnection.getResourceRegistry().cancelLastQuery();
}
public PreparedStatement prepareScrollableQueryStatement(
String sql,
ScrollMode scrollMode,
boolean isCallable) throws SQLException, HibernateException {
if ( ! factory.getSettings().isScrollableResultSetsEnabled() ) {
throw new AssertionFailure("scrollable result sets are not enabled");
}
sql = getSQL( sql );
PreparedStatement result = (
isCallable ?
proxiedConnection.prepareCall(
sql, scrollMode.toResultSetType(), ResultSet.CONCUR_READ_ONLY
) :
proxiedConnection.prepareStatement(
sql, scrollMode.toResultSetType(), ResultSet.CONCUR_READ_ONLY
)
);
setStatementFetchSize( result );
logicalConnection.getResourceRegistry().registerLastQuery( result );
return result;
}
public void abortBatch(SQLException sqle) {
getBatcher().abortBatch( sqle );
}
public void addToBatch(Expectation expectation ) throws SQLException, HibernateException {
getBatcher().addToBatch( expectation );
}
public void executeBatch() throws HibernateException {
getBatcher().executeBatch();
}
private String getSQL(String sql) {
sql = interceptor.onPrepareStatement( sql );
if ( sql==null || sql.length() == 0 ) {
throw new AssertionFailure( "Interceptor.onPrepareStatement() returned null or empty string." );
}
return sql;
}
private void setStatementFetchSize(PreparedStatement statement) throws SQLException {
if ( factory.getSettings().getJdbcFetchSize() !=null ) {
statement.setFetchSize( factory.getSettings().getJdbcFetchSize().intValue() );
}
}
public boolean isReadyForSerialization() {
return connection == null ? true : ! batcher.hasOpenResources() && connection.isReadyForSerialization();
return logicalConnection == null ? true : logicalConnection.isReadyForSerialization();
}
/**
@ -423,9 +568,6 @@ public class ConnectionManager implements Serializable {
if ( !isReadyForSerialization() ) {
throw new IllegalStateException( "Cannot serialize a ConnectionManager while connected" );
}
oos.writeObject( factory );
oos.writeObject( interceptor );
oos.defaultWriteObject();
}
@ -437,34 +579,30 @@ public class ConnectionManager implements Serializable {
* @throws ClassNotFoundException Indicates resource class resolution.
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
factory = (SessionFactoryImplementor) ois.readObject();
interceptor = (Interceptor) ois.readObject();
ois.defaultReadObject();
}
public void serialize(ObjectOutputStream oos) throws IOException {
connection.serialize( oos );
logicalConnection.serialize( oos );
}
public static ConnectionManager deserialize(
public static ConnectionManagerImpl deserialize(
ObjectInputStream ois,
SessionFactoryImplementor factory,
Interceptor interceptor,
ConnectionReleaseMode connectionReleaseMode,
Callback callback) throws IOException {
ConnectionManager connectionManager = new ConnectionManager(
return new ConnectionManagerImpl(
factory,
callback,
connectionReleaseMode,
interceptor
);
connectionManager.connection =
interceptor,
LogicalConnectionImpl.deserialize(
ois,
factory.getJdbcServices( ),
connectionReleaseMode
);
connectionManager.connection.addObserver( callback );
return connectionManager;
factory.getJdbcServices(),
factory.getStatistics() != null ? factory.getStatisticsImplementor() : null,
connectionReleaseMode,
factory.getSettings().getBatcherFactory()
)
);
}
}

View File

@ -22,9 +22,8 @@
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.jdbc;
package org.hibernate.engine.jdbc.internal;
import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
@ -41,12 +40,12 @@ import org.hibernate.Interceptor;
import org.hibernate.SessionException;
import org.hibernate.Transaction;
import org.hibernate.TransactionException;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.jdbc.spi.ConnectionManager;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.transaction.synchronization.CallbackCoordinator;
import org.hibernate.transaction.synchronization.HibernateSynchronizationImpl;
import org.hibernate.util.JTAHelper;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.transaction.TransactionFactory;
/**
* Acts as the mediary between "entity-mode related" sessions in terms of
@ -54,7 +53,7 @@ import org.hibernate.transaction.TransactionFactory;
*
* @author Steve Ebersole
*/
public class JDBCContext implements Serializable, ConnectionManager.Callback {
public class JDBCContextImpl implements ConnectionManagerImpl.Callback, JDBCContext {
// TODO : make this the factory for "entity mode related" sessions;
// also means making this the target of transaction-synch and the
@ -64,36 +63,24 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
// ConnectionManager is a "JDBCContext"? A "SessionContext" should
// live in the impl package...
private static final Logger log = LoggerFactory.getLogger( JDBCContext.class );
public static interface Context extends TransactionFactory.Context {
/**
* We cannot rely upon this method being called! It is only
* called if we are using Hibernate Transaction API.
*/
public void afterTransactionBegin(Transaction tx);
public void beforeTransactionCompletion(Transaction tx);
public void afterTransactionCompletion(boolean success, Transaction tx);
public ConnectionReleaseMode getConnectionReleaseMode();
public boolean isAutoCloseSessionEnabled();
}
private static final Logger log = LoggerFactory.getLogger( JDBCContextImpl.class );
private Context owner;
private ConnectionManager connectionManager;
private ConnectionManagerImpl connectionManager;
private transient boolean isTransactionCallbackRegistered;
private transient Transaction hibernateTransaction;
private CallbackCoordinator jtaSynchronizationCallbackCoordinator;
public JDBCContext(Context owner, Connection connection, Interceptor interceptor) {
public JDBCContextImpl(Context owner, Connection connection, Interceptor interceptor) {
this.owner = owner;
this.connectionManager = new ConnectionManager(
this.connectionManager = new ConnectionManagerImpl(
owner.getFactory(),
this,
this,
owner.getConnectionReleaseMode(),
connection,
interceptor
);
);
final boolean registerSynchronization = owner.isAutoCloseSessionEnabled()
|| owner.isFlushBeforeCompletionEnabled()
@ -107,31 +94,34 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
* Private constructor used exclusively for custom serialization...
*
*/
private JDBCContext() {
private JDBCContextImpl() {
}
@Override
public CallbackCoordinator getJtaSynchronizationCallbackCoordinator() {
return jtaSynchronizationCallbackCoordinator;
}
public CallbackCoordinator getJtaSynchronizationCallbackCoordinator(javax.transaction.Transaction jtaTransaction) {
private CallbackCoordinator getJtaSynchronizationCallbackCoordinator(javax.transaction.Transaction jtaTransaction) {
jtaSynchronizationCallbackCoordinator = new CallbackCoordinator( owner, this, jtaTransaction, hibernateTransaction );
return jtaSynchronizationCallbackCoordinator;
}
@Override
public void cleanUpJtaSynchronizationCallbackCoordinator() {
jtaSynchronizationCallbackCoordinator = null;
}
// ConnectionManager.Callback implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public void physicalConnectionObtained(Connection connection) {
if ( owner.getFactory().getStatistics().isStatisticsEnabled() ) {
owner.getFactory().getStatisticsImplementor().connect();
}
}
@Override
public void physicalConnectionReleased() {
if ( !isTransactionCallbackRegistered ) {
afterTransactionCompletion( false, null );
@ -139,14 +129,17 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
}
}
@Override
public void logicalConnectionClosed() {
// TODO: anything need to be done?
}
@Override
public SessionFactoryImplementor getFactory() {
return owner.getFactory();
}
@Override
public ConnectionManager getConnectionManager() {
return connectionManager;
}
@ -155,6 +148,7 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
return connectionManager.borrowConnection();
}
@Override
public Connection connection() throws HibernateException {
if ( owner.isClosed() ) {
throw new SessionException( "Session is closed" );
@ -163,6 +157,7 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
return connectionManager.getConnection();
}
@Override
public boolean registerCallbackIfNecessary() {
if ( isTransactionCallbackRegistered ) {
return false;
@ -174,6 +169,7 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
}
@Override
public boolean registerSynchronizationIfPossible() {
if ( isTransactionCallbackRegistered ) {
// we already have a callback registered; either a local
@ -234,11 +230,13 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
}
}
@Override
public boolean isTransactionInProgress() {
return owner.getFactory().getSettings().getTransactionFactory()
.isTransactionInProgress( this, owner, hibernateTransaction );
}
@Override
public Transaction getTransaction() throws HibernateException {
if (hibernateTransaction==null) {
hibernateTransaction = owner.getFactory().getSettings()
@ -248,6 +246,7 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
return hibernateTransaction;
}
@Override
public void beforeTransactionCompletion(Transaction tx) {
log.trace( "before transaction completion" );
owner.beforeTransactionCompletion(tx);
@ -257,11 +256,13 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
* We cannot rely upon this method being called! It is only
* called if we are using Hibernate Transaction API.
*/
@Override
public void afterTransactionBegin(Transaction tx) {
log.trace( "after transaction begin" );
owner.afterTransactionBegin(tx);
}
@Override
public void afterTransactionCompletion(boolean success, Transaction tx) {
log.trace( "after transaction completion" );
@ -280,6 +281,7 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
* Called after executing a query outside the scope of
* a Hibernate or JTA transaction
*/
@Override
public void afterNontransactionalQuery(boolean success) {
log.trace( "after autocommit" );
try {
@ -306,6 +308,10 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
// serialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public boolean isReadyForSerialization() {
return connectionManager.isReadyForSerialization();
}
private void writeObject(ObjectOutputStream oos) throws IOException {
// isTransactionCallbackRegistered denotes whether any Hibernate
// Transaction has registered as a callback against this
@ -345,16 +351,16 @@ public class JDBCContext implements Serializable, ConnectionManager.Callback {
* @param ois The stream from which to read the entry.
* @throws IOException
*/
public static JDBCContext deserialize(
public static JDBCContextImpl deserialize(
ObjectInputStream ois,
Context context,
Interceptor interceptor) throws IOException {
JDBCContext jdbcContext = new JDBCContext();
Interceptor interceptor) throws IOException, ClassNotFoundException {
JDBCContextImpl jdbcContext = new JDBCContextImpl();
jdbcContext.owner = context;
jdbcContext.connectionManager = ConnectionManager.deserialize(
jdbcContext.connectionManager = ConnectionManagerImpl.deserialize(
ois,
context.getFactory(),
interceptor,
interceptor,
context.getConnectionReleaseMode(),
jdbcContext
);

View File

@ -23,11 +23,14 @@
*/
package org.hibernate.engine.jdbc.internal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@ -35,9 +38,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.spi.JdbcWrapper;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
import org.hibernate.engine.jdbc.spi.InvalidatableWrapper;
import org.hibernate.jdbc.Batcher;
import org.hibernate.jdbc.BatcherFactory;
/**
* Standard implementation of the {@link org.hibernate.engine.jdbc.spi.JdbcResourceRegistry} contract
@ -50,9 +56,13 @@ public class JdbcResourceRegistryImpl implements JdbcResourceRegistry {
private final HashMap<Statement,Set<ResultSet>> xref = new HashMap<Statement,Set<ResultSet>>();
private final Set<ResultSet> unassociatedResultSets = new HashSet<ResultSet>();
private final SQLExceptionHelper exceptionHelper;
private final Batcher batcher;
public JdbcResourceRegistryImpl(SQLExceptionHelper exceptionHelper) {
private Statement lastQuery;
public JdbcResourceRegistryImpl(SQLExceptionHelper exceptionHelper, BatcherFactory batcherFactory) {
this.exceptionHelper = exceptionHelper;
this.batcher = batcherFactory.createBatcher( exceptionHelper );
}
public void register(Statement statement) {
@ -63,6 +73,38 @@ public class JdbcResourceRegistryImpl implements JdbcResourceRegistry {
xref.put( statement, null );
}
public Batcher getBatcher() {
return batcher;
}
@SuppressWarnings({ "unchecked" })
public void registerLastQuery(Statement statement) {
log.trace( "registering last query statement [{}]", statement );
if ( statement instanceof JdbcWrapper ) {
JdbcWrapper<Statement> wrapper = ( JdbcWrapper<Statement> ) statement;
registerLastQuery( wrapper.getWrappedObject() );
return;
}
lastQuery = statement;
}
public void cancelLastQuery() {
try {
if (lastQuery != null) {
lastQuery.cancel();
}
}
catch (SQLException sqle) {
throw exceptionHelper.convert(
sqle,
"Cannot cancel query"
);
}
finally {
lastQuery = null;
}
}
public void release(Statement statement) {
log.trace( "releasing statement [" + statement + "]" );
Set<ResultSet> resultSets = xref.get( statement );
@ -132,7 +174,7 @@ public class JdbcResourceRegistryImpl implements JdbcResourceRegistry {
}
public boolean hasRegisteredResources() {
return ! ( xref.isEmpty() && unassociatedResultSets.isEmpty() );
return ! xref.isEmpty() || ! unassociatedResultSets.isEmpty();
}
public void releaseResources() {
@ -141,6 +183,7 @@ public class JdbcResourceRegistryImpl implements JdbcResourceRegistry {
}
private void cleanup() {
batcher.closeStatements();
for ( Map.Entry<Statement,Set<ResultSet>> entry : xref.entrySet() ) {
if ( entry.getValue() != null ) {
for ( ResultSet resultSet : entry.getValue() ) {
@ -156,6 +199,59 @@ public class JdbcResourceRegistryImpl implements JdbcResourceRegistry {
close( resultSet );
}
unassociatedResultSets.clear();
// TODO: can ConcurrentModificationException still happen???
// Following is from old AbstractBatcher...
/*
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 );
}
catch ( ConcurrentModificationException e ) {
// this has been shown to happen occasionally in rare cases
// when using a transaction manager + transaction-timeout
// where the timeout calls back through Hibernate's
// registered transaction synchronization on a separate
// "reaping" thread. In cases where that reaping thread
// executes through this block at the same time the main
// application thread does we can get into situations where
// these CMEs occur. And though it is not "allowed" per-se,
// the end result without handling it specifically is infinite
// looping. So here, we simply break the loop
log.info( "encountered CME attempting to release batcher; assuming cause is tx-timeout scenario and ignoring" );
break;
}
catch ( Throwable e ) {
// sybase driver (jConnect) throwing NPE here in certain
// cases, but we'll just handle the general "unexpected" case
log.warn( "Could not close a JDBC result set", e );
}
}
resultSetsToClose.clear();
iter = statementsToClose.iterator();
while ( iter.hasNext() ) {
try {
closeQueryStatement( ( PreparedStatement ) iter.next() );
}
catch ( ConcurrentModificationException e ) {
// see explanation above...
log.info( "encountered CME attempting to release batcher; assuming cause is tx-timeout scenario and ignoring" );
break;
}
catch ( SQLException e ) {
// no big deal
log.warn( "Could not close a JDBC statement", e );
}
}
statementsToClose.clear();
*/
}
public void close() {
@ -191,6 +287,9 @@ public class JdbcResourceRegistryImpl implements JdbcResourceRegistry {
return; // EARLY EXIT!!!
}
statement.close();
if ( lastQuery == statement ) {
lastQuery = null;
}
}
catch( SQLException sqle ) {
log.debug( "Unable to release statement [{}]", sqle.getMessage() );

View File

@ -41,7 +41,10 @@ import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.jdbc.Batcher;
import org.hibernate.jdbc.BatcherFactory;
import org.hibernate.jdbc.BorrowedConnectionProxy;
import org.hibernate.stat.StatisticsImplementor;
/**
* LogicalConnectionImpl implementation
@ -51,50 +54,71 @@ import org.hibernate.jdbc.BorrowedConnectionProxy;
public class LogicalConnectionImpl implements LogicalConnectionImplementor {
private static final Logger log = LoggerFactory.getLogger( LogicalConnectionImpl.class );
private transient Connection physicalConnection;
private transient Connection borrowedConnection;
private Connection physicalConnection;
private Connection borrowedConnection;
private final ConnectionReleaseMode connectionReleaseMode;
private final JdbcServices jdbcServices;
private final JdbcResourceRegistry jdbcResourceRegistry;
private final StatisticsImplementor statisticsImplementor;
private final JdbcResourceRegistryImpl jdbcResourceRegistry;
private final List<ConnectionObserver> observers = new ArrayList<ConnectionObserver>();
private boolean releasesEnabled = true;
private long transactionTimeout = -1;
boolean isTransactionTimeoutSet;
private final boolean isUserSuppliedConnection;
private boolean isClosed;
public LogicalConnectionImpl(
Connection userSuppliedConnection,
ConnectionReleaseMode connectionReleaseMode,
JdbcServices jdbcServices) {
public LogicalConnectionImpl(Connection userSuppliedConnection,
ConnectionReleaseMode connectionReleaseMode,
JdbcServices jdbcServices,
StatisticsImplementor statisticsImplementor,
BatcherFactory batcherFactory
) {
this.jdbcServices = jdbcServices;
this.statisticsImplementor = statisticsImplementor;
this.physicalConnection = userSuppliedConnection;
this.connectionReleaseMode =
determineConnectionReleaseMode(
userSuppliedConnection != null, connectionReleaseMode, jdbcServices
jdbcServices, userSuppliedConnection != null, connectionReleaseMode
);
this.jdbcResourceRegistry =
new JdbcResourceRegistryImpl(
getJdbcServices().getSqlExceptionHelper(),
batcherFactory
);
this.jdbcServices = jdbcServices;
this.jdbcResourceRegistry = new JdbcResourceRegistryImpl( jdbcServices.getSqlExceptionHelper() );
this.isUserSuppliedConnection = ( userSuppliedConnection != null );
this.isClosed = false;
}
public LogicalConnectionImpl(
ConnectionReleaseMode connectionReleaseMode,
JdbcServices jdbcServices,
boolean isUserSuppliedConnection,
boolean isClosed) {
// used for deserialization
private LogicalConnectionImpl(ConnectionReleaseMode connectionReleaseMode,
JdbcServices jdbcServices,
StatisticsImplementor statisticsImplementor,
BatcherFactory batcherFactory,
boolean isUserSuppliedConnection,
boolean isClosed) {
this.connectionReleaseMode = determineConnectionReleaseMode(
isUserSuppliedConnection, connectionReleaseMode, jdbcServices
jdbcServices, isUserSuppliedConnection, connectionReleaseMode
);
this.jdbcServices = jdbcServices;
this.jdbcResourceRegistry = new JdbcResourceRegistryImpl( jdbcServices.getSqlExceptionHelper() );
this.statisticsImplementor = statisticsImplementor;
this.jdbcResourceRegistry =
new JdbcResourceRegistryImpl(
getJdbcServices().getSqlExceptionHelper(),
batcherFactory
);
this.isUserSuppliedConnection = isUserSuppliedConnection;
this.isClosed = isClosed;
}
private static ConnectionReleaseMode determineConnectionReleaseMode(boolean isUserSuppliedConnection,
ConnectionReleaseMode connectionReleaseMode,
JdbcServices jdbcServices) {
private static ConnectionReleaseMode determineConnectionReleaseMode(JdbcServices jdbcServices,
boolean isUserSuppliedConnection,
ConnectionReleaseMode connectionReleaseMode) {
if ( isUserSuppliedConnection ) {
return ConnectionReleaseMode.ON_CLOSE;
}
@ -108,6 +132,40 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
}
}
/**
* Set the transaction timeout to <tt>seconds</tt> later
* than the current system time.
*/
public void setTransactionTimeout(int seconds) {
isTransactionTimeoutSet = true;
transactionTimeout = System.currentTimeMillis() / 1000 + seconds;
}
/**
* Unset the transaction timeout, called after the end of a
* transaction.
*/
private void unsetTransactionTimeout() {
isTransactionTimeoutSet = false;
}
/**
* {@inheritDoc}
*/
public boolean isTransactionTimeoutSet() {
return isTransactionTimeoutSet;
}
/**
* {@inheritDoc}
*/
public long getTransactionTimeout() throws HibernateException {
if ( isTransactionTimeoutSet ) {
throw new HibernateException( "transaction timeout has not been set." );
}
return transactionTimeout;
}
/**
* {@inheritDoc}
*/
@ -115,6 +173,13 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
return jdbcServices;
}
/**
* {@inheritDoc}
*/
public StatisticsImplementor getStatisticsImplementor() {
return statisticsImplementor;
}
/**
* {@inheritDoc}
*/
@ -136,6 +201,15 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
return !isClosed;
}
/**
* {@inheritDoc}
*/
public boolean isLogicallyConnected() {
return isUserSuppliedConnection ?
isPhysicallyConnected() :
isOpen();
}
/**
* {@inheritDoc}
*/
@ -192,8 +266,8 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
return connectionReleaseMode;
}
public boolean isUserSuppliedConnection() {
return isUserSuppliedConnection;
public Batcher getBatcher() {
return jdbcResourceRegistry.getBatcher();
}
public boolean hasBorrowedConnection() {
@ -204,7 +278,7 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
if ( isClosed ) {
throw new HibernateException( "connection has been closed" );
}
if ( isUserSuppliedConnection() ) {
if ( isUserSuppliedConnection ) {
return physicalConnection;
}
else {
@ -237,6 +311,9 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
log.debug( "skipping aggressive release due to registered resources" );
return;
}
else if ( borrowedConnection != null ) {
log.debug( "skipping aggresive-release due to borrowed connection" );
}
releaseConnection();
}
}
@ -250,6 +327,7 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
}
aggressiveRelease();
}
unsetTransactionTimeout();
}
public void disableReleases() {
@ -342,6 +420,7 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
throw new IllegalStateException( "cannot manually disconnect because logical connection is already closed" );
}
Connection c = physicalConnection;
jdbcResourceRegistry.releaseResources();
releaseConnection();
return c;
}
@ -380,7 +459,7 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
}
public boolean isReadyForSerialization() {
return isUserSuppliedConnection() ?
return isUserSuppliedConnection ?
! isPhysicallyConnected() :
! getResourceRegistry().hasRegisteredResources()
;
@ -391,13 +470,17 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
oos.writeBoolean( isClosed );
}
public static LogicalConnectionImpl deserialize(
ObjectInputStream ois,
JdbcServices jdbcServices,
ConnectionReleaseMode connectionReleaseMode ) throws IOException {
public static LogicalConnectionImpl deserialize(ObjectInputStream ois,
JdbcServices jdbcServices,
StatisticsImplementor statisticsImplementor,
ConnectionReleaseMode connectionReleaseMode,
BatcherFactory batcherFactory
) throws IOException {
return new LogicalConnectionImpl(
connectionReleaseMode,
jdbcServices,
statisticsImplementor,
batcherFactory,
ois.readBoolean(),
ois.readBoolean()
);

View File

@ -140,7 +140,7 @@ public abstract class AbstractStatementProxyHandler extends AbstractProxyHandler
final ResultSet wrapper;
if ( "getGeneratedKeys".equals( method.getName() ) ) {
wrapper = ProxyBuilder.buildImplicitResultSet( ( ResultSet ) result, connectionProxyHandler, connectionProxy );
wrapper = ProxyBuilder.buildImplicitResultSet( ( ResultSet ) result, connectionProxyHandler, connectionProxy, ( Statement ) proxy );
}
else {
wrapper = ProxyBuilder.buildResultSet( ( ResultSet ) result, this, ( Statement ) proxy );

View File

@ -0,0 +1,65 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* 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, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY 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
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.internal.proxy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Invocation handler for {@link java.sql.CallableStatement} proxies
*
* @author Gail Badner
*/
public class CallableStatementProxyHandler extends PreparedStatementProxyHandler {
private static final Logger log = LoggerFactory.getLogger( CallableStatementProxyHandler.class );
protected CallableStatementProxyHandler(
String sql,
Statement statement,
ConnectionProxyHandler connectionProxyHandler,
Connection connectionProxy) {
super( sql, statement, connectionProxyHandler, connectionProxy );
}
protected Object continueInvocation(Object proxy, Method method, Object[] args) throws Throwable {
if ( ! "executeQuery".equals( method.getName() ) ) {
return super.continueInvocation( proxy, method, args ); // EARLY RETURN!
}
errorIfInvalid();
return executeQuery();
}
private Object executeQuery() throws SQLException {
return getConnectionProxy().getJdbcServices().getDialect().getResultSet( ( CallableStatement ) this );
}
}

View File

@ -36,10 +36,12 @@ import java.sql.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.TransactionException;
import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.stat.StatisticsImplementor;
/**
* The {@link InvocationHandler} for intercepting messages to {@link java.sql.Connection} proxies.
@ -127,7 +129,7 @@ public class ConnectionProxyHandler extends AbstractProxyHandler implements Invo
try {
Object result = method.invoke( extractPhysicalConnection(), args );
result = wrapIfNecessary( result, proxy, method, args );
result = postProcess( result, proxy, method, args );
return result;
}
@ -143,7 +145,7 @@ public class ConnectionProxyHandler extends AbstractProxyHandler implements Invo
}
}
private Object wrapIfNecessary(Object result, Object proxy, Method method, Object[] args) {
private Object postProcess(Object result, Object proxy, Method method, Object[] args) throws SQLException {
String methodName = method.getName();
Object wrapped = result;
if ( "createStatement".equals( methodName ) ) {
@ -152,7 +154,7 @@ public class ConnectionProxyHandler extends AbstractProxyHandler implements Invo
this,
( Connection ) proxy
);
getResourceRegistry().register( ( Statement ) wrapped );
postProcessStatement( ( Statement ) wrapped );
}
else if ( "prepareStatement".equals( methodName ) ) {
wrapped = ProxyBuilder.buildPreparedStatement(
@ -161,7 +163,7 @@ public class ConnectionProxyHandler extends AbstractProxyHandler implements Invo
this,
( Connection ) proxy
);
getResourceRegistry().register( ( Statement ) wrapped );
postProcessPreparedStatement( ( Statement ) wrapped );
}
else if ( "prepareCall".equals( methodName ) ) {
wrapped = ProxyBuilder.buildCallableStatement(
@ -170,7 +172,7 @@ public class ConnectionProxyHandler extends AbstractProxyHandler implements Invo
this,
( Connection ) proxy
);
getResourceRegistry().register( ( Statement ) wrapped );
postProcessPreparedStatement( ( Statement ) wrapped );
}
else if ( "getMetaData".equals( methodName ) ) {
wrapped = ProxyBuilder.buildDatabaseMetaData( (DatabaseMetaData) result, this, ( Connection ) proxy );
@ -178,6 +180,18 @@ public class ConnectionProxyHandler extends AbstractProxyHandler implements Invo
return wrapped;
}
private void postProcessStatement(Statement statement) throws SQLException {
setTimeout( statement );
getResourceRegistry().register( statement );
}
private void postProcessPreparedStatement(Statement statement) throws SQLException {
if ( getStatisticsImplementorOrNull() != null ) {
getStatisticsImplementorOrNull().prepareStatement();
}
postProcessStatement( statement );
}
private void explicitClose() {
if ( isValid() ) {
invalidateHandle();
@ -210,4 +224,23 @@ public class ConnectionProxyHandler extends AbstractProxyHandler implements Invo
log.info( "*** logical connection closed ***" );
invalidateHandle();
}
/* package-protected */
StatisticsImplementor getStatisticsImplementorOrNull() {
return getLogicalConnection().getStatisticsImplementor();
}
private void setTimeout(Statement result) throws SQLException {
if ( logicalConnection.isTransactionTimeoutSet() ) {
int timeout = (int) ( logicalConnection.getTransactionTimeout() - ( System.currentTimeMillis() / 1000 ) );
if (timeout<=0) {
throw new TransactionException("transaction timeout expired");
}
else {
result.setQueryTimeout(timeout);
}
}
}
}

View File

@ -47,6 +47,13 @@ public class ImplicitResultSetProxyHandler extends AbstractResultSetProxyHandler
this.connectionProxy = connectionProxy;
}
public ImplicitResultSetProxyHandler(ResultSet resultSet, ConnectionProxyHandler connectionProxyHandler, Connection connectionProxy, Statement sourceStatement) {
super( resultSet );
this.connectionProxyHandler = connectionProxyHandler;
this.connectionProxy = connectionProxy;
this.sourceStatement = sourceStatement;
}
@Override
protected JdbcServices getJdbcServices() {
return connectionProxyHandler.getJdbcServices();

View File

@ -31,6 +31,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import org.hibernate.Interceptor;
import org.hibernate.engine.jdbc.spi.JdbcWrapper;
import org.hibernate.engine.jdbc.spi.InvalidatableWrapper;
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
@ -139,7 +140,7 @@ public class ProxyBuilder {
CallableStatement statement,
ConnectionProxyHandler connectionProxyHandler,
Connection connectionProxy) {
PreparedStatementProxyHandler proxyHandler = new PreparedStatementProxyHandler(
CallableStatementProxyHandler proxyHandler = new CallableStatementProxyHandler(
sql,
statement,
connectionProxyHandler,
@ -186,6 +187,19 @@ public class ProxyBuilder {
);
}
public static ResultSet buildImplicitResultSet(
ResultSet resultSet,
ConnectionProxyHandler connectionProxyHandler,
Connection connectionProxy,
Statement sourceStatement) {
ImplicitResultSetProxyHandler proxyHandler = new ImplicitResultSetProxyHandler( resultSet, connectionProxyHandler, connectionProxy, sourceStatement );
return ( ResultSet ) Proxy.newProxyInstance(
JdbcWrapper.class.getClassLoader(),
RESULTSET_PROXY_INTERFACES,
proxyHandler
);
}
// DatabaseMetaData ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,195 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* 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, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY 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
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.spi;
import java.io.Serializable;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.ScrollMode;
import org.hibernate.jdbc.Expectation;
/**
* Encapsulates JDBC Connection management SPI.
* <p/>
* The lifecycle is intended to span a logical series of interactions with the
* database. Internally, this means the the lifecycle of the Session.
*
* @author Gail Badner
*/
public interface ConnectionManager extends Serializable {
/**
* Retrieves the connection currently managed by this ConnectionManager.
* <p/>
* Note, that we may need to obtain a connection to return here if a
* connection has either not yet been obtained (non-UserSuppliedConnectionProvider)
* or has previously been aggressively released (if supported in this environment).
*
* @return The current Connection.
*
* @throws HibernateException Indicates a connection is currently not
* available (we are currently manually disconnected).
*/
Connection getConnection() throws HibernateException;
// TODO: should this be removd from the SPI?
boolean hasBorrowedConnection();
// TODO: should this be removd from the SPI?
void releaseBorrowedConnection();
/**
* Is this ConnectionManager instance "logically" connected. Meaning
* do we either have a cached connection available or do we have the
* ability to obtain a connection on demand.
*
* @return True if logically connected; false otherwise.
*/
boolean isCurrentlyConnected();
/**
* To be called after execution of each JDBC statement. Used to
* conditionally release the JDBC connection aggressively if
* the configured release mode indicates.
*/
void afterStatement();
void setTransactionTimeout(int seconds);
/**
* To be called after Session completion. Used to release the JDBC
* connection.
*
* @return The connection mantained here at time of close. Null if
* there was no connection cached internally.
*/
Connection close();
/**
* Manually disconnect the underlying JDBC Connection. The assumption here
* is that the manager will be reconnected at a later point in time.
*
* @return The connection mantained here at time of disconnect. Null if
* there was no connection cached internally.
*/
Connection manualDisconnect();
/**
* Manually reconnect the underlying JDBC Connection. Should be called at
* some point after manualDisconnect().
* <p/>
* This form is used for ConnectionProvider-supplied connections.
*/
void manualReconnect();
/**
* Manually reconnect the underlying JDBC Connection. Should be called at
* some point after manualDisconnect().
* <p/>
* This form is used for user-supplied connections.
*/
void manualReconnect(Connection suppliedConnection);
/**
* Callback to let us know that a flush is beginning. We use this fact
* to temporarily circumvent aggressive connection releasing until after
* the flush cycle is complete {@link #flushEnding()}
*/
void flushBeginning();
/**
* Callback to let us know that a flush is ending. We use this fact to
* stop circumventing aggressive releasing connections.
*/
void flushEnding();
/**
* Get a non-batchable prepared statement to use for inserting / deleting / updating,
* using JDBC3 getGeneratedKeys ({@link java.sql.Connection#prepareStatement(String, int)}).
*/
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException, HibernateException;
/**
* Get a non-batchable prepared statement to use for inserting / deleting / updating.
* using JDBC3 getGeneratedKeys ({@link java.sql.Connection#prepareStatement(String, String[])}).
*/
public PreparedStatement prepareStatement(String sql, String[] columnNames)
throws SQLException, HibernateException;
/**
* Get a non-batchable prepared statement to use for selecting. Does not
* result in execution of the current batch.
*/
public PreparedStatement prepareSelectStatement(String sql)
throws SQLException, HibernateException;
/**
* Get a non-batchable prepared statement to use for inserting / deleting / updating.
*/
public PreparedStatement prepareStatement(String sql, boolean isCallable)
throws SQLException, HibernateException ;
/**
* Get a non-batchable callable statement to use for inserting / deleting / updating.
*/
public CallableStatement prepareCallableStatement(String sql) throws SQLException, HibernateException;
/**
* Get a batchable prepared statement to use for inserting / deleting / updating
* (might be called many times before a single call to <tt>executeBatch()</tt>).
* After setting parameters, call <tt>addToBatch</tt> - do not execute the
* statement explicitly.
* @see org.hibernate.jdbc.Batcher#addToBatch
*/
public PreparedStatement prepareBatchStatement(String sql, boolean isCallable) throws SQLException, HibernateException;
/**
* Get a prepared statement for use in loading / querying. If not explicitly
* released by <tt>closeQueryStatement()</tt>, it will be released when the
* session is closed or disconnected.
*/
public PreparedStatement prepareQueryStatement(
String sql,
boolean isCallable) throws SQLException, HibernateException;
/**
* Cancel the current query statement
*/
public void cancelLastQuery() throws HibernateException;
public PreparedStatement prepareScrollableQueryStatement(
String sql,
ScrollMode scrollMode,
boolean isCallable) throws SQLException, HibernateException;
public void abortBatch(SQLException sqle);
public void addToBatch(Expectation expectation ) throws SQLException, HibernateException;
public void executeBatch() throws HibernateException;
}

View File

@ -0,0 +1,83 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* 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, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY 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
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.spi;
import java.io.Serializable;
import java.sql.Connection;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.transaction.TransactionFactory;
import org.hibernate.transaction.synchronization.CallbackCoordinator;
/**
* Acts as the SPI for the mediary between "entity-mode related" sessions in terms of
* their interaction with the JDBC data store.
*
* @author Gail Badner
*/
public interface JDBCContext extends Serializable {
// TODO: Document these methods...
CallbackCoordinator getJtaSynchronizationCallbackCoordinator();
void cleanUpJtaSynchronizationCallbackCoordinator();
SessionFactoryImplementor getFactory();
ConnectionManager getConnectionManager();
Connection connection() throws HibernateException;
boolean registerCallbackIfNecessary();
boolean registerSynchronizationIfPossible();
boolean isTransactionInProgress();
Transaction getTransaction() throws HibernateException;
void beforeTransactionCompletion(Transaction tx);
void afterTransactionBegin(Transaction tx);
void afterTransactionCompletion(boolean success, Transaction tx);
void afterNontransactionalQuery(boolean success);
public static interface Context extends TransactionFactory.Context {
/**
* We cannot rely upon this method being called! It is only
* called if we are using Hibernate Transaction API.
*/
public void afterTransactionBegin(Transaction tx);
public void beforeTransactionCompletion(Transaction tx);
public void afterTransactionCompletion(boolean success, Transaction tx);
public ConnectionReleaseMode getConnectionReleaseMode();
public boolean isAutoCloseSessionEnabled();
}
}

View File

@ -39,6 +39,10 @@ public interface JdbcResourceRegistry {
*/
public void register(Statement statement);
public void registerLastQuery(Statement statement);
public void cancelLastQuery();
/**
* Release a previously registered statement.
*

View File

@ -31,7 +31,7 @@ import java.sql.Connection;
*
* @author Steve Ebersole
*/
public interface LogicalConnection extends Serializable {
public interface LogicalConnection {
/**
* Is this logical connection open? Another phraseology sometimes used is: "are we
* logically connected"?

View File

@ -24,6 +24,7 @@
package org.hibernate.engine.jdbc.spi;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.stat.StatisticsImplementor;
/**
* The "internal" contract for LogicalConnection
@ -38,6 +39,27 @@ public interface LogicalConnectionImplementor extends LogicalConnection {
*/
public JdbcServices getJdbcServices();
/**
* Obtains the statistics implementor.
*
* @return the statistics implementor
*/
public StatisticsImplementor getStatisticsImplementor();
/**
* Is the transaction timeout set?
*
* @return true, if the transaction timeout is set; false otherwise
*/
public boolean isTransactionTimeoutSet();
/**
* Gets the transaction timeout.
*
* @return the transaction time out
*/
public long getTransactionTimeout();
/**
* Obtains the JDBC resource registry associated with this logical connection.
*
@ -82,4 +104,6 @@ public interface LogicalConnectionImplementor extends LogicalConnection {
* Re-enable aggressive release processing (after a prior {@link #disableReleases()} call.
*/
public void enableReleases();
}

View File

@ -42,7 +42,6 @@ import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.TypedValue;
import org.hibernate.event.EventSource;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.loader.custom.sql.SQLCustomQuery;
import org.hibernate.type.Type;
import org.hibernate.util.ArrayHelper;
@ -199,7 +198,7 @@ public class NativeSQLQueryPlan implements Serializable {
session );
String sql = queryParameters.getFilteredSQL();
ps = session.getBatcher().prepareStatement( sql );
ps = session.getJDBCContext().getConnectionManager().prepareStatement( sql, false );
try {
int col = 1;
@ -211,7 +210,7 @@ public class NativeSQLQueryPlan implements Serializable {
}
finally {
if ( ps != null ) {
session.getBatcher().closeStatement( ps );
ps.close();
}
}
}

View File

@ -238,7 +238,9 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
// at the very least cleanup the data :)
PreparedStatement ps = null;
try {
ps = session.getBatcher().prepareStatement( "delete from " + persister.getTemporaryIdTableName() );
ps = session.getJDBCContext().getConnectionManager().prepareStatement( "delete from " + persister.getTemporaryIdTableName(),
false
);
ps.executeUpdate();
}
catch( Throwable t ) {
@ -247,7 +249,7 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
finally {
if ( ps != null ) {
try {
session.getBatcher().closeStatement( ps );
ps.close();
}
catch( Throwable ignore ) {
// ignore

View File

@ -33,7 +33,6 @@ import org.hibernate.HibernateException;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.RowSelection;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.hql.ast.HqlSqlWalker;
import org.hibernate.hql.ast.QuerySyntaxException;
import org.hibernate.hql.ast.SqlGenerator;
@ -85,7 +84,7 @@ public class BasicExecutor extends AbstractStatementExecutor {
try {
try {
st = session.getBatcher().prepareStatement( sql );
st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, false );
Iterator parameterSpecifications = this.parameterSpecifications.iterator();
int pos = 1;
while ( parameterSpecifications.hasNext() ) {
@ -102,7 +101,7 @@ public class BasicExecutor extends AbstractStatementExecutor {
}
finally {
if ( st != null ) {
session.getBatcher().closeStatement( st );
st.close();
}
}
}

View File

@ -31,7 +31,6 @@ import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.hql.ast.HqlSqlWalker;
import org.hibernate.hql.ast.tree.DeleteStatement;
import org.hibernate.hql.ast.tree.FromElement;
@ -106,7 +105,7 @@ public class MultiTableDeleteExecutor extends AbstractStatementExecutor {
int resultCount = 0;
try {
try {
ps = session.getBatcher().prepareStatement( idInsertSelect );
ps = session.getJDBCContext().getConnectionManager().prepareStatement( idInsertSelect, false );
Iterator paramSpecifications = getIdSelectParameterSpecifications().iterator();
int pos = 1;
while ( paramSpecifications.hasNext() ) {
@ -117,7 +116,7 @@ public class MultiTableDeleteExecutor extends AbstractStatementExecutor {
}
finally {
if ( ps != null ) {
session.getBatcher().closeStatement( ps );
ps.close();
}
}
}
@ -133,12 +132,12 @@ public class MultiTableDeleteExecutor extends AbstractStatementExecutor {
for ( int i = 0; i < deletes.length; i++ ) {
try {
try {
ps = session.getBatcher().prepareStatement( deletes[i] );
ps = session.getJDBCContext().getConnectionManager().prepareStatement( deletes[i], false );
ps.executeUpdate();
}
finally {
if ( ps != null ) {
session.getBatcher().closeStatement( ps );
ps.close();
}
}
}

View File

@ -33,7 +33,6 @@ import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.hql.ast.HqlSqlWalker;
import org.hibernate.hql.ast.tree.AssignmentSpecification;
import org.hibernate.hql.ast.tree.FromElement;
@ -130,7 +129,7 @@ public class MultiTableUpdateExecutor extends AbstractStatementExecutor {
int resultCount = 0;
try {
try {
ps = session.getBatcher().prepareStatement( idInsertSelect );
ps = session.getJDBCContext().getConnectionManager().prepareStatement( idInsertSelect, false );
// int parameterStart = getWalker().getNumberOfParametersInSetClause();
// List allParams = getIdSelectParameterSpecifications();
// Iterator whereParams = allParams.subList( parameterStart, allParams.size() ).iterator();
@ -143,7 +142,7 @@ public class MultiTableUpdateExecutor extends AbstractStatementExecutor {
}
finally {
if ( ps != null ) {
session.getBatcher().closeStatement( ps );
ps.close();
}
}
}
@ -162,7 +161,7 @@ public class MultiTableUpdateExecutor extends AbstractStatementExecutor {
}
try {
try {
ps = session.getBatcher().prepareStatement( updates[i] );
ps = session.getJDBCContext().getConnectionManager().prepareStatement( updates[i], false );
if ( hqlParameters[i] != null ) {
int position = 1; // jdbc params are 1-based
for ( int x = 0; x < hqlParameters[i].length; x++ ) {
@ -173,7 +172,7 @@ public class MultiTableUpdateExecutor extends AbstractStatementExecutor {
}
finally {
if ( ps != null ) {
session.getBatcher().closeStatement( ps );
ps.close();
}
}
}

View File

@ -32,7 +32,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
/**
* Generates <tt>string</tt> values using the SQL Server NEWID() function.
@ -59,7 +58,7 @@ public class GUIDGenerator implements IdentifierGenerator {
final String sql = session.getFactory().getDialect().getSelectGUIDString();
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement(sql);
try {
ResultSet rs = st.executeQuery();
final String result;
@ -74,7 +73,7 @@ public class GUIDGenerator implements IdentifierGenerator {
return result;
}
finally {
session.getBatcher().closeStatement(st);
st.close();
}
}
catch (SQLException sqle) {

View File

@ -87,7 +87,7 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
}
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
return session.getBatcher().prepareStatement( insertSQL, true );
return session.getJDBCContext().getConnectionManager().prepareStatement( insertSQL, PreparedStatement.RETURN_GENERATED_KEYS );
}
public Serializable executeAndExtract(PreparedStatement insert) throws SQLException {
@ -131,7 +131,7 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
}
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
return session.getBatcher().prepareStatement( insertSQL, false );
return session.getJDBCContext().getConnectionManager().prepareStatement( insertSQL, PreparedStatement.NO_GENERATED_KEYS );
}
public Serializable executeAndExtract(PreparedStatement insert) throws SQLException {

View File

@ -36,7 +36,6 @@ import org.hibernate.MappingException;
import org.hibernate.cfg.ObjectNameNormalizer;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.mapping.Table;
import org.hibernate.type.Type;
import org.hibernate.util.StringHelper;
@ -122,7 +121,7 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
log.debug( "fetching initial value: " + sql );
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
try {
ResultSet rs = st.executeQuery();
try {
@ -140,7 +139,7 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
}
}
finally {
session.getBatcher().closeStatement(st);
st.close();
}
}
catch (SQLException sqle) {

View File

@ -34,7 +34,6 @@ import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.cfg.ObjectNameNormalizer;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.mapping.Table;
@ -107,7 +106,7 @@ public class SequenceGenerator implements PersistentIdentifierGenerator, Configu
protected IntegralDataTypeHolder generateHolder(SessionImplementor session) {
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
try {
ResultSet rs = st.executeQuery();
try {
@ -124,7 +123,7 @@ public class SequenceGenerator implements PersistentIdentifierGenerator, Configu
}
}
finally {
session.getBatcher().closeStatement(st);
st.close();
}
}

View File

@ -96,7 +96,7 @@ public class SequenceIdentityGenerator extends SequenceGenerator
}
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
return session.getBatcher().prepareStatement( insertSQL, keyColumns );
return session.getJDBCContext().getConnectionManager().prepareStatement( insertSQL, keyColumns );
}
protected Serializable executeAndExtract(PreparedStatement insert) throws SQLException {

View File

@ -33,7 +33,6 @@ import org.slf4j.LoggerFactory;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.HibernateException;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.id.IntegralDataTypeHolder;
@ -103,7 +102,7 @@ public class SequenceStructure implements DatabaseStructure {
public IntegralDataTypeHolder getNextValue() {
accessCounter++;
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
try {
ResultSet rs = st.executeQuery();
try {
@ -125,7 +124,7 @@ public class SequenceStructure implements DatabaseStructure {
}
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}

View File

@ -26,7 +26,6 @@ package org.hibernate.id.insert;
import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.pretty.MessageHelper;
import java.io.Serializable;
@ -78,6 +77,6 @@ public abstract class AbstractReturningDelegate implements InsertGeneratedIdenti
protected abstract Serializable executeAndExtract(PreparedStatement insert) throws SQLException;
protected void releaseStatement(PreparedStatement insert, SessionImplementor session) throws SQLException {
session.getBatcher().closeStatement( insert );
insert.close();
}
}

View File

@ -24,7 +24,6 @@
*/
package org.hibernate.id.insert;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.id.PostInsertIdentityPersister;
@ -51,13 +50,13 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
public final Serializable performInsert(String insertSQL, SessionImplementor session, Binder binder) {
try {
// prepare and execute the insert
PreparedStatement insert = session.getBatcher().prepareStatement( insertSQL, false );
PreparedStatement insert = session.getJDBCContext().getConnectionManager().prepareStatement( insertSQL, PreparedStatement.NO_GENERATED_KEYS );
try {
binder.bindValues( insert );
insert.executeUpdate();
}
finally {
session.getBatcher().closeStatement( insert );
insert.close();
}
}
catch ( SQLException sqle ) {
@ -72,7 +71,7 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
try {
//fetch the generated id in a separate query
PreparedStatement idSelect = session.getBatcher().prepareStatement( selectSQL );
PreparedStatement idSelect = session.getJDBCContext().getConnectionManager().prepareStatement( selectSQL, false );
try {
bindParameters( session, idSelect, binder.getEntity() );
ResultSet rs = idSelect.executeQuery();
@ -84,7 +83,7 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
}
}
finally {
session.getBatcher().closeStatement( idSelect );
idSelect.close();
}
}

View File

@ -45,7 +45,6 @@ import org.hibernate.MappingException;
import org.hibernate.ScrollableResults;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.hql.HolderInstantiator;
import org.hibernate.loader.Loader;
import org.hibernate.type.Type;
@ -119,7 +118,8 @@ public abstract class AbstractScrollableResults implements ScrollableResults {
public final void close() throws HibernateException {
try {
// not absolutely necessary, but does help with aggressive release
session.getBatcher().closeQueryStatement( ps, resultSet );
//session.getJDBCContext().getConnectionManager().closeQueryStatement( ps, resultSet );
ps.close();
}
catch (SQLException sqle) {
throw session.getFactory().getSQLExceptionHelper().convert(

View File

@ -35,7 +35,6 @@ import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.engine.HibernateIterator;
import org.hibernate.event.EventSource;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.hql.HolderInstantiator;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
@ -87,7 +86,7 @@ public final class IteratorImpl implements HibernateIterator {
if (ps!=null) {
try {
log.debug("closing iterator");
session.getBatcher().closeQueryStatement(ps, rs);
ps.close();
ps = null;
rs = null;
hasNext = false;

View File

@ -89,6 +89,8 @@ import org.hibernate.engine.Status;
import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.internal.JDBCContextImpl;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.engine.query.FilterQueryPlan;
import org.hibernate.engine.query.HQLQueryPlan;
import org.hibernate.engine.query.NativeSQLQueryPlan;
@ -122,9 +124,6 @@ import org.hibernate.event.ReplicateEvent;
import org.hibernate.event.ReplicateEventListener;
import org.hibernate.event.SaveOrUpdateEvent;
import org.hibernate.event.SaveOrUpdateEventListener;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.jdbc.Batcher;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.jdbc.Work;
import org.hibernate.loader.criteria.CriteriaLoader;
import org.hibernate.loader.custom.CustomLoader;
@ -174,7 +173,7 @@ public final class SessionImpl extends AbstractSessionImpl
private transient ActionQueue actionQueue;
private transient StatefulPersistenceContext persistenceContext;
private transient JDBCContext jdbcContext;
private transient JDBCContextImpl jdbcContext;
private transient EventListeners listeners;
private transient boolean flushBeforeCompletionEnabled;
@ -252,7 +251,7 @@ public final class SessionImpl extends AbstractSessionImpl
this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;
this.autoCloseSessionEnabled = autoCloseSessionEnabled;
this.connectionReleaseMode = connectionReleaseMode;
this.jdbcContext = new JDBCContext( this, connection, interceptor );
this.jdbcContext = new JDBCContextImpl( this, connection, interceptor );
loadQueryInfluencers = new LoadQueryInfluencers( factory );
@ -300,14 +299,6 @@ public final class SessionImpl extends AbstractSessionImpl
actionQueue.clear();
}
public Batcher getBatcher() {
errorIfClosed();
checkTransactionSynchStatus();
// TODO : should remove this exposure
// and have all references to the session's batcher use the ConnectionManager.
return jdbcContext.getConnectionManager().getBatcher();
}
public long getTimestamp() {
checkTransactionSynchStatus();
return timestamp;
@ -1913,7 +1904,7 @@ public final class SessionImpl extends AbstractSessionImpl
public void cancelQuery() throws HibernateException {
errorIfClosed();
getBatcher().cancelLastQuery();
getJDBCContext().getConnectionManager().cancelLastQuery();
}
public Interceptor getInterceptor() {
@ -2140,7 +2131,7 @@ public final class SessionImpl extends AbstractSessionImpl
listeners = factory.getEventListeners();
if ( isRootSession ) {
jdbcContext = JDBCContext.deserialize( ois, this, interceptor );
jdbcContext = JDBCContextImpl.deserialize( ois, this, interceptor );
}
persistenceContext = StatefulPersistenceContext.deserialize( ois, this );
@ -2177,7 +2168,7 @@ public final class SessionImpl extends AbstractSessionImpl
* @throws IOException Indicates a general IO stream exception
*/
private void writeObject(ObjectOutputStream oos) throws IOException {
if ( !jdbcContext.getConnectionManager().isReadyForSerialization() ) {
if ( !jdbcContext.isReadyForSerialization() ) {
throw new IllegalStateException( "Cannot serialize a session while connected" );
}

View File

@ -56,13 +56,13 @@ import org.hibernate.engine.StatefulPersistenceContext;
import org.hibernate.engine.Versioning;
import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.NonFlushedChanges;
import org.hibernate.engine.jdbc.internal.JDBCContextImpl;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.engine.query.HQLQueryPlan;
import org.hibernate.engine.query.NativeSQLQueryPlan;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
import org.hibernate.event.EventListeners;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.jdbc.Batcher;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.loader.criteria.CriteriaLoader;
import org.hibernate.loader.custom.CustomLoader;
import org.hibernate.loader.custom.CustomQuery;
@ -81,12 +81,12 @@ public class StatelessSessionImpl extends AbstractSessionImpl
private static final Logger log = LoggerFactory.getLogger( StatelessSessionImpl.class );
private JDBCContext jdbcContext;
private JDBCContextImpl jdbcContext;
private PersistenceContext temporaryPersistenceContext = new StatefulPersistenceContext( this );
StatelessSessionImpl(Connection connection, SessionFactoryImpl factory) {
super( factory );
this.jdbcContext = new JDBCContext( this, connection, EmptyInterceptor.INSTANCE );
this.jdbcContext = new JDBCContextImpl( this, connection, EmptyInterceptor.INSTANCE );
}
@ -330,7 +330,7 @@ public class StatelessSessionImpl extends AbstractSessionImpl
public void managedFlush() {
errorIfClosed();
getBatcher().executeBatch();
getJDBCContext().getConnectionManager().executeBatch();
}
public boolean shouldAutoClose() {
@ -371,12 +371,6 @@ public class StatelessSessionImpl extends AbstractSessionImpl
return result;
}
public Batcher getBatcher() {
errorIfClosed();
return jdbcContext.getConnectionManager()
.getBatcher();
}
public CacheMode getCacheMode() {
return CacheMode.IGNORE;
}

View File

@ -24,29 +24,14 @@
*/
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 java.util.ConcurrentModificationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.ScrollMode;
import org.hibernate.TransactionException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.jdbc.util.FormatStyle;
import org.hibernate.util.JDBCExceptionReporter;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
/**
* Manages prepared statements and batching.
@ -55,225 +40,84 @@ import org.hibernate.util.JDBCExceptionReporter;
*/
public abstract class AbstractBatcher implements Batcher {
private static int globalOpenPreparedStatementCount;
private static int globalOpenResultSetCount;
private int openPreparedStatementCount;
private int openResultSetCount;
protected static final Logger log = LoggerFactory.getLogger( AbstractBatcher.class );
private final ConnectionManager connectionManager;
private final SessionFactoryImplementor factory;
private final SQLExceptionHelper exceptionHelper;
private final int jdbcBatchSize;
private PreparedStatement batchUpdate;
private String batchUpdateSQL;
private boolean isClosingBatchUpdate = false;
private HashSet statementsToClose = new HashSet();
private HashSet resultSetsToClose = new HashSet();
private PreparedStatement lastQuery;
private boolean releasing = false;
private final Interceptor interceptor;
private long transactionTimeout = -1;
boolean isTransactionTimeoutSet;
public AbstractBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
this.connectionManager = connectionManager;
this.interceptor = interceptor;
this.factory = connectionManager.getFactory();
public AbstractBatcher(SQLExceptionHelper exceptionHelper, int jdbcBatchSize) {
this.exceptionHelper = exceptionHelper;
this.jdbcBatchSize = jdbcBatchSize;
}
public void setTransactionTimeout(int seconds) {
isTransactionTimeoutSet = true;
transactionTimeout = System.currentTimeMillis() / 1000 + seconds;
public final int getJdbcBatchSize() {
return jdbcBatchSize;
}
public void unsetTransactionTimeout() {
isTransactionTimeoutSet = false;
public boolean hasOpenResources() {
try {
return !isClosingBatchUpdate && batchUpdate != null && ! batchUpdate.isClosed();
}
catch (SQLException sqle) {
throw exceptionHelper.convert(
sqle,
"Could check to see if batch statement was closed",
batchUpdateSQL
);
}
}
public PreparedStatement getStatement(String sql) {
return batchUpdate != null && batchUpdateSQL.equals( sql ) ? batchUpdate : null;
}
public void setStatement(String sql, PreparedStatement ps) {
checkNotClosingBatchUpdate();
batchUpdateSQL = sql;
batchUpdate = ps;
}
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,
null,
false
);
}
public PreparedStatement prepareStatement(String sql, String[] columnNames)
throws SQLException, HibernateException {
executeBatch();
logOpenPreparedStatement();
return getPreparedStatement(
connectionManager.getConnection(),
sql,
false,
false,
columnNames,
null,
false
);
}
public PreparedStatement prepareSelectStatement(String sql)
throws SQLException, HibernateException {
logOpenPreparedStatement();
return getPreparedStatement(
connectionManager.getConnection(),
sql,
false,
false,
null,
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,
null,
scrollMode,
true
);
setStatementFetchSize( ps );
statementsToClose.add( ps );
lastQuery = ps;
return ps;
}
public void abortBatch(SQLException sqle) {
closeStatements();
}
/**
* Actually releases the batcher, allowing it to cleanup internally held
* resources.
*/
public void closeStatements() {
try {
if (batchUpdate!=null) closeStatement(batchUpdate);
closeBatchUpdate();
}
catch (SQLException e) {
//noncritical, swallow and let the other propagate!
JDBCExceptionReporter.logExceptions(e);
}
finally {
batchUpdate=null;
batchUpdateSQL=null;
catch ( SQLException sqle ) {
//no big deal
log.warn( "Could not close a JDBC prepared statement", sqle );
}
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 {
boolean psStillThere = statementsToClose.remove( ps );
try {
if ( rs != null ) {
if ( resultSetsToClose.remove( rs ) ) {
logCloseResults();
rs.close();
}
}
}
finally {
if ( psStillThere ) {
closeQueryStatement( ps );
}
}
}
public PreparedStatement prepareBatchStatement(String sql)
throws SQLException, HibernateException {
sql = getSQL( sql );
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 {
checkNotClosingBatchUpdate();
if (batchUpdate!=null) {
try {
try {
doExecuteBatch(batchUpdate);
}
finally {
closeStatement(batchUpdate);
closeBatchUpdate();
}
}
catch (SQLException sqle) {
throw factory.getSQLExceptionHelper().convert(
throw exceptionHelper.convert(
sqle,
"Could not execute JDBC batch update",
batchUpdateSQL
@ -286,321 +130,28 @@ public abstract class AbstractBatcher implements Batcher {
}
}
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 );
}
catch ( ConcurrentModificationException e ) {
// this has been shown to happen occasionally in rare cases
// when using a transaction manager + transaction-timeout
// where the timeout calls back through Hibernate's
// registered transaction synchronization on a separate
// "reaping" thread. In cases where that reaping thread
// executes through this block at the same time the main
// application thread does we can get into situations where
// these CMEs occur. And though it is not "allowed" per-se,
// the end result without handling it specifically is infinite
// looping. So here, we simply break the loop
log.info( "encountered CME attempting to release batcher; assuming cause is tx-timeout scenario and ignoring" );
break;
}
catch ( Throwable e ) {
// sybase driver (jConnect) throwing NPE here in certain
// cases, but we'll just handle the general "unexpected" case
log.warn( "Could not close a JDBC result set", e );
}
}
resultSetsToClose.clear();
iter = statementsToClose.iterator();
while ( iter.hasNext() ) {
try {
closeQueryStatement( ( PreparedStatement ) iter.next() );
}
catch ( ConcurrentModificationException e ) {
// see explanation above...
log.info( "encountered CME attempting to release batcher; assuming cause is tx-timeout scenario and ignoring" );
break;
}
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) {
factory.getSettings().getSqlStatementLogger().logStatement( sql, FormatStyle.BASIC );
}
private PreparedStatement getPreparedStatement(
final Connection conn,
final String sql,
final boolean scrollable,
final ScrollMode scrollMode) throws SQLException {
return getPreparedStatement(
conn,
sql,
scrollable,
false,
null,
scrollMode,
false
);
}
private CallableStatement getCallableStatement(
final Connection conn,
String sql,
boolean scrollable) throws SQLException {
if ( scrollable && !factory.getSettings().isScrollableResultSetsEnabled() ) {
throw new AssertionFailure("scrollable result sets are not enabled");
}
sql = getSQL( sql );
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 String getSQL(String sql) {
sql = interceptor.onPrepareStatement( sql );
if ( sql==null || sql.length() == 0 ) {
throw new AssertionFailure( "Interceptor.onPrepareStatement() returned null or empty string." );
}
return sql;
}
private PreparedStatement getPreparedStatement(
final Connection conn,
String sql,
boolean scrollable,
final boolean useGetGeneratedKeys,
final String[] namedGeneratedKeys,
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");
}
sql = getSQL( sql );
log( sql );
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 = conn.prepareStatement( sql, PreparedStatement.RETURN_GENERATED_KEYS );
}
else if ( namedGeneratedKeys != null ) {
result = conn.prepareStatement( sql, namedGeneratedKeys );
}
else {
if ( callable ) {
result = conn.prepareCall( sql );
}
else {
result = conn.prepareStatement( sql );
}
}
setTimeout( result );
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor().prepareStatement();
}
return result;
}
private void setTimeout(PreparedStatement result) throws SQLException {
if ( isTransactionTimeoutSet ) {
int timeout = (int) ( transactionTimeout - ( System.currentTimeMillis() / 1000 ) );
if (timeout<=0) {
throw new TransactionException("transaction timeout expired");
}
else {
result.setQueryTimeout(timeout);
}
}
}
private void closePreparedStatement(PreparedStatement ps) throws SQLException {
private void closeBatchUpdate() throws SQLException{
checkNotClosingBatchUpdate();
try {
log.trace("closing statement");
ps.close();
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor().closeStatement();
if ( batchUpdate != null ) {
isClosingBatchUpdate = true;
batchUpdate.close();
}
}
finally {
if ( !releasing ) {
// If we are in the process of releasing, no sense
// checking for aggressive-release possibility.
connectionManager.afterStatement();
}
isClosingBatchUpdate = false;
}
}
private void checkNotClosingBatchUpdate() {
if ( isClosingBatchUpdate ) {
throw new IllegalStateException( "Cannot perform operation while closing batch update." );
}
}
private void setStatementFetchSize(PreparedStatement statement) throws SQLException {
Integer statementFetchSize = factory.getSettings().getJdbcFetchSize();
if ( statementFetchSize!=null ) {
statement.setFetchSize( statementFetchSize.intValue() );
}
}
public void cancelLastQuery() throws HibernateException {
try {
if (lastQuery!=null) lastQuery.cancel();
}
catch (SQLException sqle) {
throw factory.getSQLExceptionHelper().convert(
sqle,
"Cannot cancel query"
);
}
}
public boolean hasOpenResources() {
return resultSetsToClose.size() > 0 || statementsToClose.size() > 0;
}
public String openResourceStatsAsString() {
return preparedStatementCountsToString() + resultSetCountsToString();
}
}

View File

@ -45,82 +45,10 @@ import org.hibernate.dialect.Dialect;
* @author Gavin King
*/
public interface Batcher {
/**
* Get a prepared statement for use in loading / querying. If not explicitly
* released by <tt>closeQueryStatement()</tt>, it will be released when the
* session is closed or disconnected.
*/
public PreparedStatement prepareQueryStatement(String sql, boolean scrollable, ScrollMode scrollMode) throws SQLException, HibernateException;
/**
* Close a prepared statement opened with <tt>prepareQueryStatement()</tt>
*/
public void closeQueryStatement(PreparedStatement ps, ResultSet rs) throws SQLException;
/**
* Get a prepared statement for use in loading / querying. If not explicitly
* released by <tt>closeQueryStatement()</tt>, it will be released when the
* session is closed or disconnected.
*/
public CallableStatement prepareCallableQueryStatement(String sql, boolean scrollable, ScrollMode scrollMode) throws SQLException, HibernateException;
/**
* Get a non-batchable prepared statement to use for selecting. Does not
* result in execution of the current batch.
*/
public PreparedStatement prepareSelectStatement(String sql) throws SQLException, HibernateException;
/**
* Get a non-batchable prepared statement to use for inserting / deleting / updating,
* using JDBC3 getGeneratedKeys ({@link Connection#prepareStatement(String, int)}).
* <p/>
* Must be explicitly released by {@link #closeStatement} after use.
*/
public PreparedStatement prepareStatement(String sql, boolean useGetGeneratedKeys) throws SQLException, HibernateException;
/**
* Get a non-batchable prepared statement to use for inserting / deleting / updating.
* using JDBC3 getGeneratedKeys ({@link Connection#prepareStatement(String, String[])}).
* <p/>
* Must be explicitly released by {@link #closeStatement} after use.
*/
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException, HibernateException;
/**
* Get a non-batchable prepared statement to use for inserting / deleting / updating.
* <p/>
* Must be explicitly released by {@link #closeStatement} after use.
*/
public PreparedStatement prepareStatement(String sql) throws SQLException, HibernateException;
/**
* Get a non-batchable callable statement to use for inserting / deleting / updating.
* <p/>
* Must be explicitly released by {@link #closeStatement} after use.
*/
public CallableStatement prepareCallableStatement(String sql) throws SQLException, HibernateException;
/**
* Close a prepared or callable statement opened using <tt>prepareStatement()</tt> or <tt>prepareCallableStatement()</tt>
*/
public void closeStatement(PreparedStatement ps) throws SQLException;
/**
* Get a batchable prepared statement to use for inserting / deleting / updating
* (might be called many times before a single call to <tt>executeBatch()</tt>).
* After setting parameters, call <tt>addToBatch</tt> - do not execute the
* statement explicitly.
* @see Batcher#addToBatch
*/
public PreparedStatement prepareBatchStatement(String sql) throws SQLException, HibernateException;
/**
* Get a batchable callable statement to use for inserting / deleting / updating
* (might be called many times before a single call to <tt>executeBatch()</tt>).
* After setting parameters, call <tt>addToBatch</tt> - do not execute the
* statement explicitly.
* @see Batcher#addToBatch
*/
public CallableStatement prepareBatchCallableStatement(String sql) throws SQLException, HibernateException;
public PreparedStatement getStatement(String sql);
public void setStatement(String sql, PreparedStatement ps);
public boolean hasOpenResources();
/**
* Add an insert / delete / update to the current batch (might be called multiple times
@ -133,19 +61,6 @@ public interface Batcher {
*/
public void executeBatch() throws HibernateException;
/**
* Close any query statements that were left lying around
*/
public void closeStatements();
/**
* Execute the statement and return the result set
*/
public ResultSet getResultSet(PreparedStatement ps) throws SQLException;
/**
* Execute the statement and return the result set from a callable statement
*/
public ResultSet getResultSet(CallableStatement ps, Dialect dialect) throws SQLException;
/**
* Must be called when an exception occurs
* @param sqle the (not null) exception that is the reason for aborting
@ -153,23 +68,9 @@ public interface Batcher {
public void abortBatch(SQLException sqle);
/**
* Cancel the current query statement
* Actually releases the batcher, allowing it to cleanup internally held
* resources.
*/
public void cancelLastQuery() throws HibernateException;
public boolean hasOpenResources();
public String openResourceStatsAsString();
/**
* Set the transaction timeout to <tt>seconds</tt> later
* than the current system time.
*/
public void setTransactionTimeout(int seconds);
/**
* Unset the transaction timeout, called after the end of a
* transaction.
*/
public void unsetTransactionTimeout();
public void closeStatements();
}

View File

@ -25,6 +25,7 @@
package org.hibernate.jdbc;
import org.hibernate.Interceptor;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
/**
@ -32,5 +33,6 @@ import org.hibernate.Interceptor;
* @author Gavin King
*/
public interface BatcherFactory {
public Batcher createBatcher(ConnectionManager connectionManager, Interceptor interceptor);
public void setJdbcBatchSize(int jdbcBatchSize);
public Batcher createBatcher(SQLExceptionHelper exceptionHelper);
}

View File

@ -28,9 +28,7 @@ import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
/**
* An implementation of the <tt>Batcher</tt> interface that
@ -39,12 +37,13 @@ import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
*/
public class BatchingBatcher extends AbstractBatcher {
private int batchSize;
private Expectation[] expectations;
public BatchingBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
super( connectionManager, interceptor );
expectations = new Expectation[ getFactory().getSettings().getJdbcBatchSize() ];
private int currentSize;
public BatchingBatcher(SQLExceptionHelper exceptionHelper, int jdbcBatchSize) {
super( exceptionHelper, jdbcBatchSize );
expectations = new Expectation[ jdbcBatchSize ];
currentSize = 0;
}
public void addToBatch(Expectation expectation) throws SQLException, HibernateException {
@ -53,19 +52,19 @@ public class BatchingBatcher extends AbstractBatcher {
}
PreparedStatement batchUpdate = getStatement();
batchUpdate.addBatch();
expectations[ batchSize++ ] = expectation;
if ( batchSize == getFactory().getSettings().getJdbcBatchSize() ) {
expectations[ currentSize++ ] = expectation;
if ( currentSize == getJdbcBatchSize() ) {
doExecuteBatch( batchUpdate );
}
}
protected void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException {
if ( batchSize == 0 ) {
if ( currentSize == 0 ) {
log.debug( "no batched statements to execute" );
}
else {
if ( log.isDebugEnabled() ) {
log.debug( "Executing batch size: " + batchSize );
log.debug( "Executing batch size: " + currentSize );
}
try {
@ -76,16 +75,15 @@ public class BatchingBatcher extends AbstractBatcher {
throw re;
}
finally {
batchSize = 0;
currentSize = 0;
}
}
}
private void checkRowCounts(int[] rowCounts, PreparedStatement ps) throws SQLException, HibernateException {
int numberOfRowCounts = rowCounts.length;
if ( numberOfRowCounts != batchSize ) {
if ( numberOfRowCounts != currentSize ) {
log.warn( "JDBC driver did not return the expected number of row counts" );
}
for ( int i = 0; i < numberOfRowCounts; i++ ) {

View File

@ -24,7 +24,7 @@
*/
package org.hibernate.jdbc;
import org.hibernate.Interceptor;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
/**
@ -35,8 +35,14 @@ import org.hibernate.Interceptor;
*/
public class BatchingBatcherFactory implements BatcherFactory {
public Batcher createBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
return new BatchingBatcher( connectionManager, interceptor );
private int jdbcBatchSize;
public void setJdbcBatchSize(int jdbcBatchSize) {
this.jdbcBatchSize = jdbcBatchSize;
}
public Batcher createBatcher(SQLExceptionHelper exceptionHelper) {
return new BatchingBatcher( exceptionHelper, jdbcBatchSize );
}
}

View File

@ -28,9 +28,7 @@ import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
/**
* An implementation of the <tt>Batcher</tt> interface that does no batching
@ -39,8 +37,8 @@ import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
*/
public class NonBatchingBatcher extends AbstractBatcher {
public NonBatchingBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
super( connectionManager, interceptor );
public NonBatchingBatcher(SQLExceptionHelper exceptionHelper) {
super( exceptionHelper, 1 );
}
public void addToBatch(Expectation expectation) throws SQLException, HibernateException {

View File

@ -24,7 +24,8 @@
*/
package org.hibernate.jdbc;
import org.hibernate.Interceptor;
import org.hibernate.AssertionFailure;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
/**
@ -35,8 +36,14 @@ import org.hibernate.Interceptor;
*/
public class NonBatchingBatcherFactory implements BatcherFactory {
public Batcher createBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
return new NonBatchingBatcher( connectionManager, interceptor );
public void setJdbcBatchSize(int jdbcBatchSize) {
if ( jdbcBatchSize > 1 ) {
throw new AssertionFailure( "jdbcBatchSize must be 1 for " + getClass().getName() );
}
}
public Batcher createBatcher(SQLExceptionHelper exceptionHelper) {
return new NonBatchingBatcher( exceptionHelper );
}
}

View File

@ -67,7 +67,6 @@ import org.hibernate.engine.jdbc.ColumnNameCache;
import org.hibernate.event.EventSource;
import org.hibernate.event.PostLoadEvent;
import org.hibernate.event.PreLoadEvent;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.hql.HolderInstantiator;
import org.hibernate.impl.FetchingScrollableResultsImpl;
import org.hibernate.impl.ScrollableResultsImpl;
@ -891,7 +890,7 @@ public abstract class Loader {
}
finally {
session.getBatcher().closeQueryStatement( st, rs );
st.close();
}
initializeEntitiesAndCollections( hydratedObjects, rs, session, queryParameters.isReadOnly( session ) );
@ -1749,16 +1748,12 @@ public abstract class Loader {
sql = preprocessSQL( sql, queryParameters, dialect );
PreparedStatement st = null;
if (callable) {
st = session.getBatcher()
.prepareCallableQueryStatement( sql, scroll || useScrollableResultSetToSkip, scrollMode );
}
else {
st = session.getBatcher()
.prepareQueryStatement( sql, scroll || useScrollableResultSetToSkip, scrollMode );
}
st = (
scroll || useScrollableResultSetToSkip ?
session.getJDBCContext().getConnectionManager().prepareScrollableQueryStatement( sql, scrollMode, callable ) :
session.getJDBCContext().getConnectionManager().prepareQueryStatement( sql, callable )
);
try {
@ -1809,11 +1804,11 @@ public abstract class Loader {
log.trace( "Bound [" + col + "] parameters total" );
}
catch ( SQLException sqle ) {
session.getBatcher().closeQueryStatement( st, null );
st.close();
throw sqle;
}
catch ( HibernateException he ) {
session.getBatcher().closeQueryStatement( st, null );
st.close();
throw he;
}
@ -2004,12 +1999,7 @@ public abstract class Loader {
ResultSet rs = null;
try {
Dialect dialect = getFactory().getDialect();
if (callable) {
rs = session.getBatcher().getResultSet( (CallableStatement) st, dialect );
}
else {
rs = session.getBatcher().getResultSet( st );
}
rs = st.executeQuery();
rs = wrapResultSetIfEnabled( rs , session );
if ( !dialect.supportsLimitOffset() || !useLimit( selection, dialect ) ) {
@ -2022,7 +2012,7 @@ public abstract class Loader {
return rs;
}
catch ( SQLException sqle ) {
session.getBatcher().closeQueryStatement( st, rs );
st.close();
throw sqle;
}
}

View File

@ -55,7 +55,6 @@ import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.exception.SQLExceptionConverter;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.jdbc.Expectation;
@ -1084,20 +1083,10 @@ public abstract class AbstractCollectionPersister
boolean useBatch = expectation.canBeBatched();
String sql = getSQLDeleteString();
if ( useBatch ) {
if ( callable ) {
st = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
st = session.getBatcher().prepareBatchStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareBatchStatement( sql, callable );
}
else {
if ( callable ) {
st = session.getBatcher().prepareCallableStatement( sql );
}
else {
st = session.getBatcher().prepareStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
}
@ -1106,7 +1095,7 @@ public abstract class AbstractCollectionPersister
writeKey( st, id, offset, session );
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
session.getJDBCContext().getConnectionManager().addToBatch( expectation );
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@ -1114,13 +1103,13 @@ public abstract class AbstractCollectionPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
session.getJDBCContext().getConnectionManager().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( st );
st.close();
}
}
@ -1172,20 +1161,10 @@ public abstract class AbstractCollectionPersister
String sql = getSQLInsertRowString();
if ( useBatch ) {
if ( callable ) {
st = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
st = session.getBatcher().prepareBatchStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareBatchStatement( sql, callable );
}
else {
if ( callable ) {
st = session.getBatcher().prepareCallableStatement( sql );
}
else {
st = session.getBatcher().prepareStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
}
@ -1203,7 +1182,7 @@ public abstract class AbstractCollectionPersister
loc = writeElement(st, collection.getElement(entry), loc, session );
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
session.getJDBCContext().getConnectionManager().addToBatch( expectation );
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@ -1214,13 +1193,13 @@ public abstract class AbstractCollectionPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
session.getJDBCContext().getConnectionManager().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( st );
st.close();
}
}
@ -1282,20 +1261,10 @@ public abstract class AbstractCollectionPersister
String sql = getSQLDeleteRowString();
if ( useBatch ) {
if ( callable ) {
st = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
st = session.getBatcher().prepareBatchStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareBatchStatement( sql, callable );
}
else {
if ( callable ) {
st = session.getBatcher().prepareCallableStatement( sql );
}
else {
st = session.getBatcher().prepareStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
}
try {
@ -1317,7 +1286,7 @@ public abstract class AbstractCollectionPersister
}
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
session.getJDBCContext().getConnectionManager().addToBatch( expectation );
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@ -1326,13 +1295,13 @@ public abstract class AbstractCollectionPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
session.getJDBCContext().getConnectionManager().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( st );
st.close();
}
}
@ -1392,21 +1361,11 @@ public abstract class AbstractCollectionPersister
if ( useBatch ) {
if ( st == null ) {
if ( callable ) {
st = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
st = session.getBatcher().prepareBatchStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareBatchStatement( sql, callable );
}
}
else {
if ( callable ) {
st = session.getBatcher().prepareCallableStatement( sql );
}
else {
st = session.getBatcher().prepareStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
}
try {
@ -1422,7 +1381,7 @@ public abstract class AbstractCollectionPersister
writeElement(st, collection.getElement(entry), offset, session );
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
session.getJDBCContext().getConnectionManager().addToBatch( expectation );
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@ -1432,13 +1391,13 @@ public abstract class AbstractCollectionPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
session.getJDBCContext().getConnectionManager().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( st );
st.close();
}
}
}
@ -1744,7 +1703,7 @@ public abstract class AbstractCollectionPersister
public int getSize(Serializable key, SessionImplementor session) {
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement(sqlSelectSizeString);
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement(sqlSelectSizeString);
try {
getKeyType().nullSafeSet(st, key, 1, session);
ResultSet rs = st.executeQuery();
@ -1756,7 +1715,7 @@ public abstract class AbstractCollectionPersister
}
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}
catch (SQLException sqle) {
@ -1779,7 +1738,7 @@ public abstract class AbstractCollectionPersister
private boolean exists(Serializable key, Object indexOrElement, Type indexOrElementType, String sql, SessionImplementor session) {
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement(sql);
try {
getKeyType().nullSafeSet(st, key, 1, session);
indexOrElementType.nullSafeSet( st, indexOrElement, keyColumnNames.length + 1, session );
@ -1795,7 +1754,7 @@ public abstract class AbstractCollectionPersister
return false;
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}
catch (SQLException sqle) {
@ -1810,7 +1769,7 @@ public abstract class AbstractCollectionPersister
public Object getElementByIndex(Serializable key, Object index, SessionImplementor session, Object owner) {
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement(sqlSelectRowByIndexString);
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement(sqlSelectRowByIndexString);
try {
getKeyType().nullSafeSet(st, key, 1, session);
getIndexType().nullSafeSet( st, incrementIndexByBase(index), keyColumnNames.length + 1, session );
@ -1828,7 +1787,7 @@ public abstract class AbstractCollectionPersister
}
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}
catch (SQLException sqle) {

View File

@ -39,7 +39,6 @@ import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations;
import org.hibernate.loader.collection.BatchingCollectionInitializer;
@ -212,21 +211,11 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
if ( useBatch ) {
if ( st == null ) {
if ( callable ) {
st = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
st = session.getBatcher().prepareBatchStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareBatchStatement( sql, callable );
}
}
else {
if ( callable ) {
st = session.getBatcher().prepareCallableStatement( sql );
}
else {
st = session.getBatcher().prepareStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
}
try {
@ -246,7 +235,7 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
}
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
session.getJDBCContext().getConnectionManager().addToBatch( expectation );
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@ -254,13 +243,13 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
session.getJDBCContext().getConnectionManager().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( st );
st.close();
}
}
count++;

View File

@ -39,7 +39,6 @@ import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations;
import org.hibernate.loader.collection.BatchingCollectionInitializer;
@ -203,18 +202,21 @@ public class OneToManyPersister extends AbstractCollectionPersister {
expectation = Expectations.appropriateExpectation( getDeleteCheckStyle() );
useBatch = expectation.canBeBatched();
st = useBatch
? session.getBatcher().prepareBatchCallableStatement( sql )
: session.getBatcher().prepareCallableStatement( sql );
? session.getJDBCContext().getConnectionManager().prepareBatchStatement( sql, true )
: session.getJDBCContext().getConnectionManager().prepareStatement( sql, true );
offset += expectation.prepare( st );
}
else {
st = session.getBatcher().prepareBatchStatement( getSQLDeleteRowString() );
st = session.getJDBCContext().getConnectionManager().prepareBatchStatement(
getSQLDeleteRowString(),
false
);
}
}
int loc = writeKey( st, id, offset, session );
writeElementToWhere( st, collection.getSnapshotElement(entry, i), loc, session );
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
session.getJDBCContext().getConnectionManager().addToBatch( expectation );
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@ -226,13 +228,13 @@ public class OneToManyPersister extends AbstractCollectionPersister {
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
session.getJDBCContext().getConnectionManager().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( st );
st.close();
}
}
}
@ -253,21 +255,11 @@ public class OneToManyPersister extends AbstractCollectionPersister {
if ( collection.needsUpdating( entry, i, elementType ) ) {
if ( useBatch ) {
if ( st == null ) {
if ( callable ) {
st = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
st = session.getBatcher().prepareBatchStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareBatchStatement( sql, callable );
}
}
else {
if ( callable ) {
st = session.getBatcher().prepareCallableStatement( sql );
}
else {
st = session.getBatcher().prepareStatement( sql );
}
st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
}
offset += expectation.prepare( st );
@ -280,7 +272,7 @@ public class OneToManyPersister extends AbstractCollectionPersister {
writeElementToWhere( st, collection.getElement( entry ), loc, session );
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
session.getJDBCContext().getConnectionManager().addToBatch( expectation );
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@ -292,13 +284,13 @@ public class OneToManyPersister extends AbstractCollectionPersister {
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
session.getJDBCContext().getConnectionManager().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( st );
st.close();
}
}
}

View File

@ -67,7 +67,6 @@ import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.ValueInclusion;
import org.hibernate.engine.Versioning;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.PostInsertIdentityPersister;
@ -843,7 +842,7 @@ public abstract class AbstractEntityPersister
// null sql means that the only lazy properties
// are shared PK one-to-one associations which are
// handled differently in the Type#nullSafeGet code...
ps = session.getBatcher().prepareSelectStatement(lazySelect);
ps = session.getJDBCContext().getConnectionManager().prepareSelectStatement(lazySelect);
getIdentifierType().nullSafeSet( ps, id, 1, session );
rs = ps.executeQuery();
rs.next();
@ -864,7 +863,7 @@ public abstract class AbstractEntityPersister
}
finally {
if ( ps != null ) {
session.getBatcher().closeStatement( ps );
ps.close();
}
}
@ -1090,7 +1089,7 @@ public abstract class AbstractEntityPersister
}
try {
PreparedStatement ps = session.getBatcher().prepareSelectStatement( getSQLSnapshotSelectString() );
PreparedStatement ps = session.getJDBCContext().getConnectionManager().prepareSelectStatement( getSQLSnapshotSelectString() );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
//if ( isVersioned() ) getVersionType().nullSafeSet( ps, version, getIdentifierColumnSpan()+1, session );
@ -1117,7 +1116,7 @@ public abstract class AbstractEntityPersister
}
}
finally {
session.getBatcher().closeStatement( ps );
ps.close();
}
}
catch ( SQLException sqle ) {
@ -1301,7 +1300,7 @@ public abstract class AbstractEntityPersister
PreparedStatement st = null;
try {
try {
st = session.getBatcher().prepareStatement( versionIncrementString );
st = session.getJDBCContext().getConnectionManager().prepareStatement( versionIncrementString, false );
getVersionType().nullSafeSet( st, nextVersion, 1, session );
getIdentifierType().nullSafeSet( st, id, 2, session );
getVersionType().nullSafeSet( st, currentVersion, 2 + getIdentifierColumnSpan(), session );
@ -1311,7 +1310,7 @@ public abstract class AbstractEntityPersister
}
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}
catch ( SQLException sqle ) {
@ -1349,7 +1348,7 @@ public abstract class AbstractEntityPersister
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( getVersionSelectString() );
PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( getVersionSelectString() );
try {
getIdentifierType().nullSafeSet( st, id, 1, session );
@ -1368,7 +1367,7 @@ public abstract class AbstractEntityPersister
}
}
finally {
session.getBatcher().closeStatement( st );
st.close();
}
}
@ -2208,7 +2207,7 @@ public abstract class AbstractEntityPersister
final String sql = rootPersister.getSequentialSelect( getEntityName() );
if ( sql != null ) {
//TODO: I am not so sure about the exception handling in this bit!
sequentialSelect = session.getBatcher().prepareSelectStatement( sql );
sequentialSelect = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
rootPersister.getIdentifierType().nullSafeSet( sequentialSelect, id, 1, session );
sequentialResultSet = sequentialSelect.executeQuery();
if ( !sequentialResultSet.next() ) {
@ -2275,7 +2274,7 @@ public abstract class AbstractEntityPersister
}
finally {
if ( sequentialSelect != null ) {
session.getBatcher().closeStatement( sequentialSelect );
sequentialSelect.close();
}
}
}
@ -2382,20 +2381,10 @@ public abstract class AbstractEntityPersister
// Render the SQL query
final PreparedStatement insert;
if ( useBatch ) {
if ( callable ) {
insert = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
insert = session.getBatcher().prepareBatchStatement( sql );
}
insert = session.getJDBCContext().getConnectionManager().prepareBatchStatement( sql, callable );
}
else {
if ( callable ) {
insert = session.getBatcher().prepareCallableStatement( sql );
}
else {
insert = session.getBatcher().prepareStatement( sql );
}
insert = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
}
try {
@ -2409,7 +2398,7 @@ public abstract class AbstractEntityPersister
if ( useBatch ) {
// TODO : shouldnt inserts be Expectations.NONE?
session.getBatcher().addToBatch( expectation );
session.getJDBCContext().getConnectionManager().addToBatch( expectation );
}
else {
expectation.verifyOutcome( insert.executeUpdate(), insert, -1 );
@ -2418,13 +2407,13 @@ public abstract class AbstractEntityPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
session.getJDBCContext().getConnectionManager().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( insert );
insert.close();
}
}
}
@ -2511,20 +2500,10 @@ public abstract class AbstractEntityPersister
int index = 1; // starting index
final PreparedStatement update;
if ( useBatch ) {
if ( callable ) {
update = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
update = session.getBatcher().prepareBatchStatement( sql );
}
update = session.getJDBCContext().getConnectionManager().prepareBatchStatement( sql, callable );
}
else {
if ( callable ) {
update = session.getBatcher().prepareCallableStatement( sql );
}
else {
update = session.getBatcher().prepareStatement( sql );
}
update = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
}
try {
@ -2564,7 +2543,7 @@ public abstract class AbstractEntityPersister
}
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
session.getJDBCContext().getConnectionManager().addToBatch( expectation );
return true;
}
else {
@ -2574,13 +2553,13 @@ public abstract class AbstractEntityPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
session.getJDBCContext().getConnectionManager().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( update );
update.close();
}
}
@ -2635,20 +2614,10 @@ public abstract class AbstractEntityPersister
PreparedStatement delete;
int index = 1;
if ( useBatch ) {
if ( callable ) {
delete = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
delete = session.getBatcher().prepareBatchStatement( sql );
}
delete = session.getJDBCContext().getConnectionManager().prepareBatchStatement( sql, callable );
}
else {
if ( callable ) {
delete = session.getBatcher().prepareCallableStatement( sql );
}
else {
delete = session.getBatcher().prepareStatement( sql );
}
delete = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
}
try {
@ -2680,7 +2649,7 @@ public abstract class AbstractEntityPersister
}
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
session.getJDBCContext().getConnectionManager().addToBatch( expectation );
}
else {
check( delete.executeUpdate(), id, j, expectation, delete );
@ -2689,13 +2658,13 @@ public abstract class AbstractEntityPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
session.getJDBCContext().getConnectionManager().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( delete );
delete.close();
}
}
@ -3965,10 +3934,10 @@ public abstract class AbstractEntityPersister
String selectionSQL,
ValueInclusion[] includeds) {
session.getBatcher().executeBatch(); //force immediate execution of the insert
session.getJDBCContext().getConnectionManager().executeBatch(); //force immediate execution of the insert
try {
PreparedStatement ps = session.getBatcher().prepareSelectStatement( selectionSQL );
PreparedStatement ps = session.getJDBCContext().getConnectionManager().prepareSelectStatement( selectionSQL );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
ResultSet rs = ps.executeQuery();
@ -3994,7 +3963,7 @@ public abstract class AbstractEntityPersister
}
}
finally {
session.getBatcher().closeStatement( ps );
ps.close();
}
}
catch( SQLException sqle ) {
@ -4064,7 +4033,7 @@ public abstract class AbstractEntityPersister
Object[] snapshot = new Object[ naturalIdPropertyCount ];
try {
PreparedStatement ps = session.getBatcher().prepareSelectStatement( sql );
PreparedStatement ps = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
ResultSet rs = ps.executeQuery();
@ -4089,7 +4058,7 @@ public abstract class AbstractEntityPersister
}
}
finally {
session.getBatcher().closeStatement( ps );
ps.close();
}
}
catch ( SQLException sqle ) {

View File

@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.TransactionException;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.util.JTAHelper;
/**

View File

@ -30,8 +30,8 @@ import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.TransactionException;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.util.JTAHelper;
import org.hibernate.jdbc.JDBCContext;
import javax.transaction.SystemException;

View File

@ -33,7 +33,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.TransactionException;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.util.JTAHelper;
/**
@ -53,7 +53,7 @@ public final class CacheSynchronization implements Synchronization {
public CacheSynchronization(
TransactionFactory.Context ctx,
JDBCContext jdbcContext,
JDBCContext jdbcContext,
Transaction transaction,
org.hibernate.Transaction tx) {
this.ctx = ctx;

View File

@ -33,8 +33,8 @@ import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.TransactionException;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.engine.transaction.SynchronizationRegistry;
import org.hibernate.jdbc.JDBCContext;
/**
* {@link Transaction} implementation based on transaction management through a JDBC {@link java.sql.Connection}.
@ -100,7 +100,6 @@ public class JDBCTransaction implements Transaction {
if ( timeout>0 ) {
jdbcContext.getConnectionManager()
.getBatcher()
.setTransactionTimeout(timeout);
}

View File

@ -29,7 +29,7 @@ import java.util.Properties;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.engine.jdbc.spi.JDBCContext;
/**
* Factory for {@link JDBCTransaction} instances.

View File

@ -36,7 +36,7 @@ import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.TransactionException;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.util.JTAHelper;
/**

View File

@ -38,8 +38,8 @@ import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.TransactionException;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.internal.util.jndi.JndiHelper;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.cfg.Environment;
import org.hibernate.util.JTAHelper;

View File

@ -30,7 +30,7 @@ import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.engine.jdbc.spi.JDBCContext;
/**
* Contract for generating Hibernate {@link Transaction} instances.

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.transaction.synchronization;
import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
@ -31,9 +30,8 @@ import javax.transaction.Transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.TransactionException;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.transaction.TransactionFactory;
import org.hibernate.util.JTAHelper;
@ -158,7 +156,8 @@ public class CallbackCoordinator {
private static final BeforeCompletionManagedFlushChecker STANDARD_MANAGED_FLUSH_CHECKER = new BeforeCompletionManagedFlushChecker() {
public boolean shouldDoManagedFlush(TransactionFactory.Context ctx, Transaction jtaTransaction)
throws SystemException {
return !ctx.isFlushModeNever() &&
return !ctx.isClosed() &&
!ctx.isFlushModeNever() &&
ctx.isFlushBeforeCompletionEnabled() &&
!JTAHelper.isRollback( jtaTransaction.getStatus() );
//actually, this last test is probably unnecessary, since

View File

@ -32,7 +32,6 @@ import java.util.Date;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.dialect.Dialect;
import org.hibernate.exception.JDBCExceptionHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -90,8 +89,8 @@ public class DbTimestampType extends TimestampType {
private Timestamp usePreparedStatement(String timestampSelectString, SessionImplementor session) {
PreparedStatement ps = null;
try {
ps = session.getBatcher().prepareStatement( timestampSelectString );
ResultSet rs = session.getBatcher().getResultSet( ps );
ps = session.getJDBCContext().getConnectionManager().prepareStatement( timestampSelectString, false );
ResultSet rs = ps.executeQuery();
rs.next();
Timestamp ts = rs.getTimestamp( 1 );
if ( log.isTraceEnabled() ) {
@ -113,7 +112,7 @@ public class DbTimestampType extends TimestampType {
finally {
if ( ps != null ) {
try {
session.getBatcher().closeStatement( ps );
ps.close();
}
catch( SQLException sqle ) {
log.warn( "unable to clean up prepared statement", sqle );
@ -125,7 +124,7 @@ public class DbTimestampType extends TimestampType {
private Timestamp useCallableStatement(String callString, SessionImplementor session) {
CallableStatement cs = null;
try {
cs = session.getBatcher().prepareCallableStatement( callString );
cs = session.getJDBCContext().getConnectionManager().prepareCallableStatement( callString );
cs.registerOutParameter( 1, java.sql.Types.TIMESTAMP );
cs.execute();
Timestamp ts = cs.getTimestamp( 1 );
@ -148,7 +147,7 @@ public class DbTimestampType extends TimestampType {
finally {
if ( cs != null ) {
try {
session.getBatcher().closeStatement( cs );
cs.close();
}
catch( SQLException sqle ) {
log.warn( "unable to clean up callable statement", sqle );

View File

@ -8,15 +8,14 @@ import java.sql.PreparedStatement;
import junit.framework.Test;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.Session;
import org.hibernate.Interceptor;
import org.hibernate.HibernateException;
import org.hibernate.jdbc.BatchingBatcher;
import org.hibernate.jdbc.ConnectionManager;
import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.BatcherFactory;
import org.hibernate.jdbc.Batcher;
@ -61,7 +60,7 @@ public class InsertOrderingTest extends FunctionalTestCase {
s.getTransaction().commit();
s.close();
assertEquals( 6, StatsBatcher.batchSizes.size() ); // 2 batches of each insert statement
assertEquals( 3, StatsBatcher.batchSizes.size() );
s = openSession();
s.beginTransaction();
@ -82,8 +81,8 @@ public class InsertOrderingTest extends FunctionalTestCase {
private static List batchSizes = new ArrayList();
private static int currentBatch = -1;
public StatsBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
super( connectionManager, interceptor );
public StatsBatcher(SQLExceptionHelper exceptionHelper, int jdbcBatchSize) {
super( exceptionHelper, jdbcBatchSize );
}
static void reset() {
@ -92,16 +91,15 @@ public class InsertOrderingTest extends FunctionalTestCase {
batchSQL = null;
}
public PreparedStatement prepareBatchStatement(String sql) throws SQLException {
PreparedStatement rtn = super.prepareBatchStatement( sql );
if ( batchSQL == null || !batchSQL.equals( sql ) ) {
public void setStatement(String sql, PreparedStatement ps) {
if ( batchSQL == null || ! batchSQL.equals( sql ) ) {
currentBatch++;
batchSQL = sql;
batchSizes.add( currentBatch, new Counter() );
System.out.println( "--------------------------------------------------------" );
System.out.println( "Preparing statement [" + sql + "]" );
}
return rtn;
super.setStatement( sql, ps );
}
public void addToBatch(Expectation expectation) throws SQLException, HibernateException {
@ -114,14 +112,18 @@ public class InsertOrderingTest extends FunctionalTestCase {
protected void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException {
System.out.println( "executing batch [" + batchSQL + "]" );
System.out.println( "--------------------------------------------------------" );
batchSQL = null;
super.doExecuteBatch( ps );
}
}
public static class StatsBatcherFactory implements BatcherFactory {
public Batcher createBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
return new StatsBatcher( connectionManager, interceptor );
private int jdbcBatchSize;
public void setJdbcBatchSize(int jdbcBatchSize) {
this.jdbcBatchSize = jdbcBatchSize;
}
public Batcher createBatcher(SQLExceptionHelper exceptionHelper) {
return new StatsBatcher( exceptionHelper, jdbcBatchSize );
}
}
}

View File

@ -35,7 +35,7 @@ import org.hibernate.ConnectionReleaseMode;
import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
import org.hibernate.stat.ConcurrentStatisticsImpl;
import org.hibernate.jdbc.NonBatchingBatcherFactory;
import org.hibernate.test.common.BasicTestingJdbcServiceImpl;
import org.hibernate.testing.junit.UnitTestCase;
@ -131,7 +131,13 @@ public class AggressiveReleaseTest extends UnitTestCase {
}
public void testBasicRelease() {
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services );
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
null,
ConnectionReleaseMode.AFTER_STATEMENT,
services,
null,
new NonBatchingBatcherFactory()
);
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
ConnectionCounter observer = new ConnectionCounter();
logicalConnection.addObserver( observer );
@ -160,7 +166,13 @@ public class AggressiveReleaseTest extends UnitTestCase {
}
public void testReleaseCircumventedByHeldResources() {
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services );
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
null,
ConnectionReleaseMode.AFTER_STATEMENT,
services,
null,
new NonBatchingBatcherFactory()
);
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
ConnectionCounter observer = new ConnectionCounter();
logicalConnection.addObserver( observer );
@ -182,6 +194,7 @@ public class AggressiveReleaseTest extends UnitTestCase {
ps = proxiedConnection.prepareStatement( "select * from SANDBOX_JDBC_TST" );
ps.executeQuery();
assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
assertEquals( 2, observer.obtainCount );
assertEquals( 1, observer.releaseCount );
@ -213,7 +226,13 @@ public class AggressiveReleaseTest extends UnitTestCase {
}
public void testReleaseCircumventedManually() {
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services );
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
null,
ConnectionReleaseMode.AFTER_STATEMENT,
services,
null,
new NonBatchingBatcherFactory()
);
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
ConnectionCounter observer = new ConnectionCounter();
logicalConnection.addObserver( observer );

View File

@ -34,6 +34,7 @@ import org.hibernate.ConnectionReleaseMode;
import org.hibernate.JDBCException;
import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
import org.hibernate.jdbc.NonBatchingBatcherFactory;
import org.hibernate.test.common.BasicTestingJdbcServiceImpl;
import org.hibernate.testing.junit.UnitTestCase;
@ -58,7 +59,13 @@ public class BasicConnectionProxyTest extends UnitTestCase {
}
public void testDatabaseMetaDataHandling() throws Throwable {
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_TRANSACTION, services );
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
null,
ConnectionReleaseMode.AFTER_TRANSACTION,
services,
null,
new NonBatchingBatcherFactory()
);
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
try {
DatabaseMetaData metaData = proxiedConnection.getMetaData();
@ -81,7 +88,13 @@ public class BasicConnectionProxyTest extends UnitTestCase {
}
public void testExceptionHandling() {
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_TRANSACTION, services );
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
null,
ConnectionReleaseMode.AFTER_TRANSACTION,
services,
null,
new NonBatchingBatcherFactory()
);
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
try {
proxiedConnection.prepareStatement( "select count(*) from NON_EXISTENT" ).executeQuery();
@ -98,7 +111,13 @@ public class BasicConnectionProxyTest extends UnitTestCase {
}
public void testBasicJdbcUsage() throws JDBCException {
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_TRANSACTION, services );
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
null,
ConnectionReleaseMode.AFTER_TRANSACTION,
services,
null,
new NonBatchingBatcherFactory()
);
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
try {

View File

@ -26,6 +26,7 @@ import java.util.List;
import junit.framework.Test;
import junit.framework.Assert;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.cfg.Configuration;
@ -37,7 +38,6 @@ import org.hibernate.EmptyInterceptor;
import org.hibernate.jdbc.BatcherFactory;
import org.hibernate.jdbc.NonBatchingBatcher;
import org.hibernate.jdbc.Batcher;
import org.hibernate.jdbc.ConnectionManager;
import org.hibernate.stat.CollectionStatistics;
import org.hibernate.loader.collection.BatchingCollectionInitializer;
import org.hibernate.persister.collection.AbstractCollectionPersister;
@ -68,16 +68,20 @@ public class BatchedManyToManyTest extends FunctionalTestCase {
}
public static class TestingBatcherFactory implements BatcherFactory {
public Batcher createBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
return new TestingBatcher( connectionManager, interceptor );
private int jdbcBatchSize;
public void setJdbcBatchSize(int jdbcBatchSize) {
this.jdbcBatchSize = jdbcBatchSize;
}
public Batcher createBatcher(SQLExceptionHelper exceptionHelper) {
return new TestingBatcher( exceptionHelper, jdbcBatchSize );
}
}
public static class TestingBatcher extends NonBatchingBatcher {
public TestingBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
super( connectionManager, interceptor );
public TestingBatcher(SQLExceptionHelper exceptionHelper, int jdbcBatchSize) {
super( exceptionHelper );
}
}
public void testProperLoaderSetup() {

View File

@ -8,6 +8,7 @@ log4j.rootLogger=info, stdout
log4j.logger.org.hibernate.test=info
log4j.logger.org.hibernate.tool.hbm2ddl=debug
log4j.logger.org.hibernate.engine.jdbc=trace
log4j.logger.org.hibernate.hql.ast.QueryTranslatorImpl=trace
log4j.logger.org.hibernate.hql.ast.HqlSqlWalker=trace
log4j.logger.org.hibernate.hql.ast.SqlGenerator=trace

View File

@ -26,7 +26,7 @@ import javax.transaction.Transaction;
import org.hibernate.HibernateException;
import org.hibernate.TransactionException;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.transaction.CMTTransaction;
import org.hibernate.transaction.TransactionFactory;
import org.hibernate.util.JTAHelper;

View File

@ -23,7 +23,7 @@ package org.hibernate.ejb.transaction;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.transaction.CMTTransactionFactory;
/**

View File

@ -46,11 +46,10 @@ import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.NonFlushedChanges;
import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
import org.hibernate.event.EventListeners;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.jdbc.Batcher;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.loader.custom.CustomQuery;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.Type;
@ -105,10 +104,6 @@ public abstract class AbstractDelegateSessionImplementor implements SessionImple
return delegate.getFactory();
}
public Batcher getBatcher() {
return delegate.getBatcher();
}
public List list(String query, QueryParameters queryParameters) throws HibernateException {
return delegate.list(query, queryParameters);
}