HHH-9747 - Import initial reworking of transaction handling (based on JdbcSession work)

This commit is contained in:
Andrea Boriero 2015-04-20 20:35:22 +01:00 committed by Steve Ebersole
parent 82b312dd21
commit b476094d43
192 changed files with 5726 additions and 5468 deletions

View File

@ -149,4 +149,8 @@ public class EmptyInterceptor implements Interceptor, Serializable {
public void onCollectionUpdate(Object collection, Serializable key) throws CallbackException {
}
@Override
public String inspect(String sql) {
return this.onPrepareStatement( sql );
}
}

View File

@ -26,6 +26,7 @@ package org.hibernate;
import java.io.Serializable;
import java.util.Iterator;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.type.Type;
/**
@ -52,7 +53,7 @@ import org.hibernate.type.Type;
*
* @author Gavin King
*/
public interface Interceptor {
public interface Interceptor extends StatementInspector {
/**
* Called just before an object is initialized. The interceptor may change the <tt>state</tt>, which will
* be propagated to the persistent object. Note that when this method is called, <tt>entity</tt> will be

View File

@ -25,7 +25,9 @@ package org.hibernate;
import javax.transaction.Synchronization;
import org.hibernate.engine.transaction.spi.IsolationDelegate;
import org.hibernate.engine.transaction.spi.LocalStatus;
import org.hibernate.resource.transaction.spi.TransactionStatus;
/**
* Defines the contract for abstracting applications from the configured underlying means of transaction management.
@ -44,12 +46,6 @@ import org.hibernate.engine.transaction.spi.LocalStatus;
* @author Steve Ebersole
*/
public interface Transaction {
/**
* Is this transaction the initiator of any underlying transaction?
*
* @return {@code true} if this transaction initiated the underlying transaction; {@code false} otherwise.
*/
public boolean isInitiator();
/**
* Begin this transaction. No-op if the transaction has already been begun. Note that this is not necessarily
@ -93,58 +89,7 @@ public interface Transaction {
*
* @return The current local status.
*/
public LocalStatus getLocalStatus();
/**
* Is this transaction still active?
* <p/>
* Answers on a best effort basis. For example, in the case of JDBC based transactions we cannot know that a
* transaction is active when it is initiated directly through the JDBC {@link java.sql.Connection}, only when
* it is initiated from here.
*
* @return {@code true} if the transaction is still active; {@code false} otherwise.
*
* @throws HibernateException Indicates a problem checking the transaction status.
*/
public boolean isActive();
/**
* Is Hibernate participating in the underlying transaction?
* <p/>
* Generally speaking this will be the same as {@link #isActive()}.
*
* @return {@code true} if Hibernate is known to be participating in the underlying transaction; {@code false}
* otherwise.
*/
public boolean isParticipating();
/**
* Was this transaction committed?
* <p/>
* Answers on a best effort basis. For example, in the case of JDBC based transactions we cannot know that a
* transaction was committed when the commit was performed directly through the JDBC {@link java.sql.Connection},
* only when the commit was done from this.
*
* @return {@code true} if the transaction is rolled back; {@code false} otherwise.
*
* @throws HibernateException Indicates a problem checking the transaction status.
*/
@SuppressWarnings( {"UnusedDeclaration"})
public boolean wasCommitted();
/**
* Was this transaction rolled back or set to rollback only?
* <p/>
* Answers on a best effort basis. For example, in the case of JDBC based transactions we cannot know that a
* transaction was rolled back when rollback was performed directly through the JDBC {@link java.sql.Connection},
* only when it was rolled back from here.
*
* @return {@literal true} if the transaction is rolled back; {@literal false} otherwise.
*
* @throws HibernateException Indicates a problem checking the transaction status.
*/
@SuppressWarnings( {"UnusedDeclaration"})
public boolean wasRolledBack();
public TransactionStatus getStatus();
/**
* Register a user synchronization callback for this transaction.
@ -168,4 +113,10 @@ public interface Transaction {
* @return The timeout, in seconds.
*/
public int getTimeout();
/**
* Make a best effort to mark the underlying transaction for rollback only.
*/
public void markRollbackOnly();
}

View File

@ -60,12 +60,12 @@ import org.hibernate.engine.config.internal.ConfigurationServiceImpl;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.transaction.spi.TransactionFactory;
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.loader.BatchFetchStyle;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.resource.transaction.TransactionCoordinatorBuilder;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.tuple.entity.EntityTuplizerFactory;
@ -113,6 +113,7 @@ import static org.hibernate.cfg.AvailableSettings.USE_SQL_COMMENTS;
import static org.hibernate.cfg.AvailableSettings.USE_STRUCTURED_CACHE;
import static org.hibernate.cfg.AvailableSettings.WRAP_RESULT_SETS;
import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN;
import static org.hibernate.cfg.AvailableSettings.PREFER_USER_TRANSACTION;
/**
* @author Gail Badner
@ -532,6 +533,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
private boolean wrapResultSetsEnabled;
private Map<String, SQLFunction> sqlFunctions;
private boolean preferUserTransaction;
public SessionFactoryOptionsStateStandardImpl(StandardServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
@ -683,13 +685,16 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
final String releaseModeName = ConfigurationHelper.getString( RELEASE_CONNECTIONS, configurationSettings, "auto" );
if ( "auto".equals( releaseModeName ) ) {
this.connectionReleaseMode = serviceRegistry.getService( TransactionFactory.class ).getDefaultReleaseMode();
this.connectionReleaseMode = serviceRegistry.getService( TransactionCoordinatorBuilder.class )
.getDefaultConnectionReleaseMode();
}
else {
connectionReleaseMode = ConnectionReleaseMode.parse( releaseModeName );
}
this.commentsEnabled = ConfigurationHelper.getBoolean( USE_SQL_COMMENTS, configurationSettings );
this.preferUserTransaction = ConfigurationHelper.getBoolean( PREFER_USER_TRANSACTION, configurationSettings, false );
}
@Override
@ -947,6 +952,10 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return sqlFunctions == null ? Collections.<String, SQLFunction>emptyMap() : sqlFunctions;
}
@Override
public boolean isPreferUserTransaction() {
return this.preferUserTransaction;
}
}
@Override

View File

@ -74,9 +74,6 @@ import org.hibernate.dialect.SybaseASE15Dialect;
import org.hibernate.dialect.SybaseAnywhereDialect;
import org.hibernate.dialect.TeradataDialect;
import org.hibernate.dialect.TimesTenDialect;
import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory;
import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
import org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory;
import org.hibernate.engine.transaction.jta.platform.internal.BitronixJtaPlatform;
import org.hibernate.engine.transaction.jta.platform.internal.BorlandEnterpriseServerJtaPlatform;
import org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform;
@ -92,7 +89,6 @@ import org.hibernate.engine.transaction.jta.platform.internal.WebSphereExtendedJ
import org.hibernate.engine.transaction.jta.platform.internal.WebSphereJtaPlatform;
import org.hibernate.engine.transaction.jta.platform.internal.WeblogicJtaPlatform;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.engine.transaction.spi.TransactionFactory;
import org.hibernate.event.internal.EntityCopyAllowedLoggedObserver;
import org.hibernate.event.internal.EntityCopyAllowedObserver;
import org.hibernate.event.internal.EntityCopyNotAllowedObserver;
@ -165,7 +161,7 @@ public class StrategySelectorBuilder {
// build the baseline...
addDialects( strategySelector );
addJtaPlatforms( strategySelector );
addTransactionFactories( strategySelector );
// addTransactionFactories( strategySelector );
addMultiTableBulkIdStrategies( strategySelector );
addEntityCopyObserverStrategies( strategySelector );
@ -355,16 +351,16 @@ public class StrategySelectorBuilder {
}
}
private void addTransactionFactories(StrategySelectorImpl strategySelector) {
strategySelector.registerStrategyImplementor( TransactionFactory.class, JdbcTransactionFactory.SHORT_NAME, JdbcTransactionFactory.class );
strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.JDBCTransactionFactory", JdbcTransactionFactory.class );
strategySelector.registerStrategyImplementor( TransactionFactory.class, JtaTransactionFactory.SHORT_NAME, JtaTransactionFactory.class );
strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.JTATransactionFactory", JtaTransactionFactory.class );
strategySelector.registerStrategyImplementor( TransactionFactory.class, CMTTransactionFactory.SHORT_NAME, CMTTransactionFactory.class );
strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.CMTTransactionFactory", CMTTransactionFactory.class );
}
// private void addTransactionFactories(StrategySelectorImpl strategySelector) {
// strategySelector.registerStrategyImplementor( TransactionFactory.class, JdbcTransactionFactory.SHORT_NAME, JdbcTransactionFactory.class );
// strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.JDBCTransactionFactory", JdbcTransactionFactory.class );
//
// strategySelector.registerStrategyImplementor( TransactionFactory.class, JtaTransactionFactory.SHORT_NAME, JtaTransactionFactory.class );
// strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.JTATransactionFactory", JtaTransactionFactory.class );
//
// strategySelector.registerStrategyImplementor( TransactionFactory.class, CMTTransactionFactory.SHORT_NAME, CMTTransactionFactory.class );
// strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.CMTTransactionFactory", CMTTransactionFactory.class );
// }
private void addMultiTableBulkIdStrategies(StrategySelectorImpl strategySelector) {
strategySelector.registerStrategyImplementor(

View File

@ -183,4 +183,6 @@ public interface SessionFactoryOptions {
public Map<String, SQLFunction> getCustomSqlFunctionMap();
void setCheckNullability(boolean enabled);
public boolean isPreferUserTransaction();
}

View File

@ -282,10 +282,10 @@ public interface AvailableSettings {
String CURRENT_SESSION_CONTEXT_CLASS = "hibernate.current_session_context_class";
/**
* Names the implementation of {@link org.hibernate.engine.transaction.spi.TransactionFactory} to use for
* creating {@link org.hibernate.Transaction} instances
* Names the implementation of {@link org.hibernate.resource.transaction.TransactionCoordinatorBuilder} to use for
* creating {@link org.hibernate.resource.transaction.TransactionCoordinator} instances
*/
String TRANSACTION_STRATEGY = "hibernate.transaction.factory_class";
String TRANSACTION_COORDINATOR_STRATEGY = "hibernate.transaction.coordinator_class";
/**
* Names the {@link org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform} implementation to use for integrating
@ -807,4 +807,13 @@ public interface AvailableSettings {
* annotations (combined with {@code orm.xml} mappings).
*/
String ARTIFACT_PROCESSING_ORDER = "hibernate.mapping.precedence";
/**
* Used to specify if using {@link javax.transaction.UserTransaction} class to use for JTA transaction management.
*
* Default is <code>false</code>
*
* @since 5.0
*/
String PREFER_USER_TRANSACTION = "hibernate.jta.prefer_user_transaction";
}

View File

@ -329,4 +329,8 @@ public final class Settings {
// ugh, used by org.hibernate.cfg.beanvalidation.TypeSafeActivator as part of the BV integrator
sessionFactoryOptions.setCheckNullability( enabled );
}
public boolean isPreferUserTransaction() {
return sessionFactoryOptions.isPreferUserTransaction();
}
}

View File

@ -242,10 +242,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
}
if ( isTempSession ) {
isJTA = session.getTransactionCoordinator()
.getTransactionContext().getTransactionEnvironment()
.getTransactionFactory()
.compatibleWithJtaSynchronization();
isJTA = session.getTransactionCoordinator().getTransactionCoordinatorBuilder().isJta();
if ( !isJTA ) {
// Explicitly handle the transactions only if we're not in

View File

@ -43,9 +43,9 @@ import org.hibernate.context.spi.AbstractCurrentSessionContext;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.transaction.spi.TransactionContext;
import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.resource.transaction.spi.TransactionStatus;
import org.jboss.logging.Logger;
@ -81,7 +81,6 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
Session.class,
SessionImplementor.class,
EventSource.class,
TransactionContext.class,
LobCreationContext.class
};
@ -220,7 +219,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
if ( orphan != null ) {
LOG.alreadySessionBound();
try {
if ( orphan.getTransaction() != null && orphan.getTransaction().isActive() ) {
if ( orphan.getTransaction() != null && orphan.getTransaction().getStatus() == TransactionStatus.ACTIVE ) {
try {
orphan.getTransaction().rollback();
}
@ -333,7 +332,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
// but we capture that there simply to doAfterTransactionCompletion the unbind...
LOG.tracef( "Allowing invocation [%s] to proceed to real (closed) session", methodName );
}
else if ( !realSession.getTransaction().isActive() ) {
else if ( realSession.getTransaction().getStatus() != TransactionStatus.ACTIVE ) {
// limit the methods available if no transaction is active
if ( "beginTransaction".equals( methodName )
|| "getTransaction".equals( methodName )

View File

@ -73,7 +73,7 @@ public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingS
final SessionFactoryImplementor factory = session.getFactory();
try {
try {
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
@ -85,7 +85,7 @@ public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingS
);
}
final ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
final ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
@ -96,11 +96,12 @@ public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingS
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}

View File

@ -92,7 +92,7 @@ public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
final SessionFactoryImplementor factory = session.getFactory();
try {
try {
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
@ -104,7 +104,7 @@ public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
lockable.getVersionType().nullSafeSet( st, version, offset, session );
}
final int affected = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
final int affected = session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
// todo: should this instead check for exactly one row modified?
if ( affected < 0 ) {
if (factory.getStatistics().isStatisticsEnabled()) {
@ -115,7 +115,8 @@ public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}

View File

@ -72,7 +72,7 @@ public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLocking
final SessionFactoryImplementor factory = session.getFactory();
try {
try {
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
@ -84,7 +84,7 @@ public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLocking
);
}
final ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
final ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
@ -95,11 +95,12 @@ public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLocking
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException e ) {

View File

@ -91,7 +91,7 @@ public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
final SessionFactoryImplementor factory = session.getFactory();
try {
try {
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
@ -103,7 +103,7 @@ public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
lockable.getVersionType().nullSafeSet( st, version, offset, session );
}
final int affected = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
final int affected = session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
// todo: should this instead check for exactly one row modified?
if ( affected < 0 ) {
if (factory.getStatistics().isStatisticsEnabled()) {
@ -114,7 +114,8 @@ public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException e ) {

View File

@ -71,7 +71,7 @@ public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
final String sql = determineSql( timeout );
final SessionFactoryImplementor factory = session.getFactory();
try {
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
@ -83,7 +83,7 @@ public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
);
}
final ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
final ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( !rs.next() ) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
@ -94,11 +94,12 @@ public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}

View File

@ -94,7 +94,7 @@ public class UpdateLockingStrategy implements LockingStrategy {
// todo : should we additionally check the current isolation mode explicitly?
final SessionFactoryImplementor factory = session.getFactory();
try {
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
@ -106,7 +106,7 @@ public class UpdateLockingStrategy implements LockingStrategy {
lockable.getVersionType().nullSafeSet( st, version, offset, session );
}
final int affected = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
final int affected = session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
if ( affected < 0 ) {
if (factory.getStatistics().isStatisticsEnabled()) {
factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
@ -116,7 +116,8 @@ public class UpdateLockingStrategy implements LockingStrategy {
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}

View File

@ -28,6 +28,8 @@ import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import org.jboss.logging.Logger;
import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.batch.spi.BatchKey;
import org.hibernate.engine.jdbc.batch.spi.BatchObserver;
@ -35,11 +37,8 @@ import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.transaction.spi.TransactionContext;
import org.hibernate.internal.CoreMessageLogger;
import org.jboss.logging.Logger;
/**
* Convenience base class for implementers of the Batch interface.
*
@ -55,7 +54,6 @@ public abstract class AbstractBatchImpl implements Batch {
private final BatchKey key;
private final JdbcCoordinator jdbcCoordinator;
private final TransactionContext transactionContext;
private final SqlStatementLogger sqlStatementLogger;
private final SqlExceptionHelper sqlExceptionHelper;
@ -72,24 +70,27 @@ public abstract class AbstractBatchImpl implements Batch {
this.key = key;
this.jdbcCoordinator = jdbcCoordinator;
this.transactionContext = jdbcCoordinator.getTransactionCoordinator().getTransactionContext();
final JdbcServices jdbcServices = transactionContext.getTransactionEnvironment().getJdbcServices();
final JdbcServices jdbcServices = jdbcCoordinator.getJdbcSessionOwner()
.getJdbcSessionContext()
.getServiceRegistry()
.getService( JdbcServices.class );
this.sqlStatementLogger = jdbcServices.getSqlStatementLogger();
this.sqlExceptionHelper = jdbcServices.getSqlExceptionHelper();
}
protected JdbcCoordinator getJdbcCoordinator(){
return this.jdbcCoordinator;
}
/**
* Perform batch execution.
* Perform batch execution..
* <p/>
* This is called from the explicit {@link #execute() execution}, but may also be called from elsewhere
* depending on the exact implementation.
*/
protected abstract void doExecuteBatch();
public TransactionContext transactionContext() {
return transactionContext;
}
/**
* Convenience access to the SQLException helper.
*
@ -170,7 +171,8 @@ public abstract class AbstractBatchImpl implements Batch {
protected void releaseStatements() {
for ( PreparedStatement statement : getStatements().values() ) {
clearBatch( statement );
jdbcCoordinator.release( statement );
jdbcCoordinator.getResourceRegistry().release( statement );
jdbcCoordinator.afterStatementExecution();
}
getStatements().clear();
}

View File

@ -123,11 +123,11 @@ public class BatchingBatch extends AbstractBatchImpl {
final PreparedStatement statement = entry.getValue();
final int[] rowCounts;
try {
transactionContext().startBatchExecution();
getJdbcCoordinator().getJdbcSessionOwner().getJdbcSessionContext().getObserver().jdbcExecuteBatchStart();
rowCounts = statement.executeBatch();
}
finally {
transactionContext().endBatchExecution();
getJdbcCoordinator().getJdbcSessionOwner().getJdbcSessionContext().getObserver().jdbcExecuteBatchEnd();
}
checkRowCounts( rowCounts, statement );
}

View File

@ -61,7 +61,8 @@ public class NonBatchingBatch extends AbstractBatchImpl {
final PreparedStatement statement = entry.getValue();
final int rowCount = jdbcCoordinator.getResultSetReturn().executeUpdate( statement );
getKey().getExpectation().verifyOutcome( rowCount, statement, 0 );
jdbcCoordinator.release( statement );
jdbcCoordinator.getResourceRegistry().release( statement );
jdbcCoordinator.afterStatementExecution();
}
catch ( SQLException e ) {
abortBatch();

View File

@ -36,29 +36,32 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jboss.logging.Logger;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.TransactionException;
import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
import org.hibernate.engine.jdbc.batch.spi.BatchKey;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.InvalidatableWrapper;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.JdbcWrapper;
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.engine.jdbc.spi.ResultSetReturn;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.StatementPreparer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl;
import org.hibernate.engine.transaction.spi.TransactionContext;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.jdbc.WorkExecutor;
import org.hibernate.jdbc.WorkExecutorVisitable;
import org.jboss.logging.Logger;
import org.hibernate.resource.jdbc.ResourceRegistry;
import org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl;
import org.hibernate.resource.jdbc.internal.LogicalConnectionProvidedImpl;
import org.hibernate.resource.jdbc.spi.JdbcSessionOwner;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.resource.transaction.backend.store.spi.DataStoreTransaction;
/**
* Standard Hibernate implementation of {@link JdbcCoordinator}
@ -75,8 +78,11 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
JdbcCoordinatorImpl.class.getName()
);
private transient TransactionCoordinator transactionCoordinator;
private final transient LogicalConnectionImpl logicalConnection;
private boolean closed;
private transient LogicalConnectionImplementor logicalConnection;
private transient JdbcSessionOwner owner;
private final ConnectionReleaseMode connectionReleaseMode;
private transient Batch currentBatch;
@ -92,9 +98,11 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
private final HashMap<Statement,Set<ResultSet>> xref = new HashMap<Statement,Set<ResultSet>>();
private final Set<ResultSet> unassociatedResultSets = new HashSet<ResultSet>();
private final transient SqlExceptionHelper exceptionHelper;
private transient SqlExceptionHelper exceptionHelper;
private Statement lastQuery;
private final boolean isUserSuppliedConnection;
/**
* If true, manually (and temporarily) circumvent aggressive release processing.
@ -105,43 +113,47 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
* Constructs a JdbcCoordinatorImpl
*
* @param userSuppliedConnection The user supplied connection (may be null)
* @param transactionCoordinator The transaction coordinator
*/
public JdbcCoordinatorImpl(
Connection userSuppliedConnection,
TransactionCoordinator transactionCoordinator) {
this.transactionCoordinator = transactionCoordinator;
this.logicalConnection = new LogicalConnectionImpl(
userSuppliedConnection,
transactionCoordinator.getTransactionContext().getConnectionReleaseMode(),
transactionCoordinator.getTransactionContext().getTransactionEnvironment().getJdbcServices(),
transactionCoordinator.getTransactionContext().getJdbcConnectionAccess()
JdbcSessionOwner owner) {
if ( userSuppliedConnection != null ) {
this.logicalConnection = new LogicalConnectionProvidedImpl( userSuppliedConnection );
this.isUserSuppliedConnection = true;
}
else {
this.logicalConnection = new LogicalConnectionManagedImpl(
owner.getJdbcConnectionAccess(),
owner.getJdbcSessionContext()
);
this.isUserSuppliedConnection = false;
}
this.connectionReleaseMode = determineConnectionReleaseMode(
owner.getJdbcConnectionAccess(),
isUserSuppliedConnection,
owner.getJdbcSessionContext()
.getConnectionReleaseMode()
);
this.exceptionHelper = logicalConnection.getJdbcServices().getSqlExceptionHelper();
this.owner = owner;
this.exceptionHelper = owner.getJdbcSessionContext()
.getServiceRegistry()
.getService( JdbcServices.class )
.getSqlExceptionHelper();
}
/**
* Constructs a JdbcCoordinatorImpl
*
* @param logicalConnection The logical JDBC connection
* @param transactionCoordinator The transaction coordinator
*/
public JdbcCoordinatorImpl(
LogicalConnectionImpl logicalConnection,
TransactionCoordinator transactionCoordinator) {
this.transactionCoordinator = transactionCoordinator;
private JdbcCoordinatorImpl(
LogicalConnectionImplementor logicalConnection,
boolean isUserSuppliedConnection,
ConnectionReleaseMode connectionReleaseMode,
JdbcSessionOwner owner) {
this.logicalConnection = logicalConnection;
this.exceptionHelper = logicalConnection.getJdbcServices().getSqlExceptionHelper();
}
private JdbcCoordinatorImpl(LogicalConnectionImpl logicalConnection) {
this.logicalConnection = logicalConnection;
this.exceptionHelper = logicalConnection.getJdbcServices().getSqlExceptionHelper();
}
@Override
public TransactionCoordinator getTransactionCoordinator() {
return transactionCoordinator;
this.isUserSuppliedConnection = isUserSuppliedConnection;
this.connectionReleaseMode = connectionReleaseMode;
this.owner = owner;
this.exceptionHelper = owner.getJdbcSessionContext()
.getServiceRegistry()
.getService( JdbcServices.class )
.getSqlExceptionHelper();
}
@Override
@ -149,12 +161,8 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
return logicalConnection;
}
protected TransactionEnvironment transactionEnvironment() {
return getTransactionCoordinator().getTransactionContext().getTransactionEnvironment();
}
protected SessionFactoryImplementor sessionFactory() {
return transactionEnvironment().getSessionFactory();
return this.owner.getJdbcSessionContext().getSessionFactory();
}
protected BatchBuilder batchBuilder() {
@ -170,7 +178,6 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
return exceptionHelper;
}
private int flushDepth;
@Override
@ -202,6 +209,7 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
currentBatch.release();
}
cleanup();
closed = true;
return logicalConnection.close();
}
@ -261,6 +269,11 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
transactionTimeOutInstant = System.currentTimeMillis() + ( seconds * 1000 );
}
@Override
public void flushBeforeTransactionCompletion() {
getJdbcSessionOwner().flushBeforeTransactionCompletion();
}
@Override
public int determineRemainingTransactionTimeOutPeriod() {
if ( transactionTimeOutInstant < 0 ) {
@ -275,8 +288,8 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
@Override
public void afterStatementExecution() {
LOG.tracev( "Starting after statement execution processing [{0}]", connectionReleaseMode() );
if ( connectionReleaseMode() == ConnectionReleaseMode.AFTER_STATEMENT ) {
LOG.tracev( "Starting after statement execution processing [{0}]", getConnectionReleaseMode() );
if ( getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_STATEMENT ) {
if ( ! releasesEnabled ) {
LOG.debug( "Skipping aggressive release due to manual disabling" );
return;
@ -285,30 +298,56 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
LOG.debug( "Skipping aggressive release due to registered resources" );
return;
}
getLogicalConnection().releaseConnection();
getLogicalConnection().afterStatement();
}
}
@Override
public void afterTransaction() {
transactionTimeOutInstant = -1;
if ( connectionReleaseMode() == ConnectionReleaseMode.AFTER_STATEMENT ||
connectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION ) {
if ( hasRegisteredResources() ) {
LOG.forcingContainerResourceCleanup();
releaseResources();
}
getLogicalConnection().aggressiveRelease();
if ( getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_STATEMENT ||
getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION ) {
this.logicalConnection.afterTransaction();
}
}
private ConnectionReleaseMode connectionReleaseMode() {
return getLogicalConnection().getConnectionReleaseMode();
private void releaseResources() {
getResourceRegistry().releaseResources();
}
private boolean hasRegisteredResources() {
return getResourceRegistry().hasRegisteredResources();
}
@Override
public ResourceRegistry getResourceRegistry(){
return this.logicalConnection.getResourceRegistry();
}
@Override
public ConnectionReleaseMode getConnectionReleaseMode() {
return this.connectionReleaseMode;
}
private ConnectionReleaseMode determineConnectionReleaseMode(
JdbcConnectionAccess jdbcConnectionAccess,
boolean isUserSuppliedConnection,
ConnectionReleaseMode connectionReleaseMode) {
if ( isUserSuppliedConnection ) {
return ConnectionReleaseMode.ON_CLOSE;
}
else if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT &&
! jdbcConnectionAccess.supportsAggressiveRelease() ) {
LOG.debug( "Connection provider reports to not support aggressive release; overriding" );
return ConnectionReleaseMode.AFTER_TRANSACTION;
}
else {
return connectionReleaseMode;
}
}
@Override
public <T> T coordinateWork(WorkExecutorVisitable<T> work) {
final Connection connection = getLogicalConnection().getConnection();
final Connection connection = getLogicalConnection().getPhysicalConnection();
try {
final T result = work.accept( new WorkExecutor<T>(), connection );
afterStatementExecution();
@ -321,65 +360,11 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
@Override
public boolean isReadyForSerialization() {
return getLogicalConnection().isUserSuppliedConnection()
return this.isUserSuppliedConnection
? ! getLogicalConnection().isPhysicallyConnected()
: ! hasRegisteredResources();
}
/**
* JDK serialization hook
*
* @param oos The stream into which to write our state
*
* @throws IOException Trouble accessing the stream
*/
public void serialize(ObjectOutputStream oos) throws IOException {
if ( ! isReadyForSerialization() ) {
throw new HibernateException( "Cannot serialize Session while connected" );
}
logicalConnection.serialize( oos );
}
/**
* JDK deserialization hook
*
* @param ois The stream into which to write our state
* @param transactionContext The transaction context which owns the JdbcCoordinatorImpl to be deserialized.
*
* @return The deserialized JdbcCoordinatorImpl
*
* @throws IOException Trouble accessing the stream
* @throws ClassNotFoundException Trouble reading the stream
*/
public static JdbcCoordinatorImpl deserialize(
ObjectInputStream ois,
TransactionContext transactionContext) throws IOException, ClassNotFoundException {
return new JdbcCoordinatorImpl( LogicalConnectionImpl.deserialize( ois, transactionContext ) );
}
/**
* Callback after deserialization from Session is done
*
* @param transactionCoordinator The transaction coordinator
*/
public void afterDeserialize(TransactionCoordinatorImpl transactionCoordinator) {
this.transactionCoordinator = transactionCoordinator;
}
@Override
public void register(Statement statement) {
LOG.tracev( "Registering statement [{0}]", statement );
// Benchmarking has shown this to be a big hotspot. Originally, most usages would call both
// #containsKey and #put. Instead, we optimize for the most common path (no previous Statement was
// registered) by calling #put only once, but still handling the unlikely conflict and resulting exception.
final Set<ResultSet> previousValue = xref.put( statement, EMPTY_RESULTSET );
if ( previousValue != null ) {
// Put the previous value back to undo the put
xref.put( statement, previousValue );
throw new HibernateException( "statement already registered with JDBCContainer" );
}
}
@Override
@SuppressWarnings({ "unchecked" })
public void registerLastQuery(Statement statement) {
@ -407,92 +392,6 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
}
}
@Override
public void release(Statement statement) {
LOG.tracev( "Releasing statement [{0}]", statement );
final Set<ResultSet> resultSets = xref.get( statement );
if ( resultSets != null ) {
for ( ResultSet resultSet : resultSets ) {
close( resultSet );
}
resultSets.clear();
}
xref.remove( statement );
close( statement );
afterStatementExecution();
}
@Override
public void register(ResultSet resultSet, Statement statement) {
if ( statement == null ) {
try {
statement = resultSet.getStatement();
}
catch ( SQLException e ) {
throw exceptionHelper.convert( e, "unable to access statement from resultset" );
}
}
if ( statement != null ) {
LOG.tracev( "Registering result set [{0}]", resultSet );
Set<ResultSet> resultSets = xref.get( statement );
if ( resultSets == null ) {
LOG.unregisteredStatement();
}
if ( resultSets == null || resultSets == EMPTY_RESULTSET ) {
resultSets = new HashSet<ResultSet>();
xref.put( statement, resultSets );
}
resultSets.add( resultSet );
}
else {
unassociatedResultSets.add( resultSet );
}
}
@Override
public void release(ResultSet resultSet, Statement statement) {
LOG.tracev( "Releasing result set [{0}]", resultSet );
if ( statement == null ) {
try {
statement = resultSet.getStatement();
}
catch ( SQLException e ) {
throw exceptionHelper.convert( e, "unable to access statement from resultset" );
}
}
if ( statement != null ) {
final Set<ResultSet> resultSets = xref.get( statement );
if ( resultSets == null ) {
LOG.unregisteredStatement();
}
else {
resultSets.remove( resultSet );
if ( resultSets.isEmpty() ) {
xref.remove( statement );
}
}
}
else {
final boolean removed = unassociatedResultSets.remove( resultSet );
if ( !removed ) {
LOG.unregisteredResultSetWithoutStatement();
}
}
close( resultSet );
}
@Override
public boolean hasRegisteredResources() {
return ! xref.isEmpty() || ! unassociatedResultSets.isEmpty();
}
@Override
public void releaseResources() {
LOG.tracev( "Releasing JDBC container resources [{0}]", this );
cleanup();
}
@Override
public void enableReleases() {
releasesEnabled = true;
@ -590,4 +489,81 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
LOG.debugf( "Unable to release JDBC result set [%s]", e.getMessage() );
}
}
@Override
public boolean isActive() {
return !closed;
}
@Override
public void afterTransactionBegin() {
owner.afterTransactionBegin();
}
@Override
public void beforeTransactionCompletion() {
owner.beforeTransactionCompletion();
}
@Override
public void afterTransactionCompletion(boolean successful) {
afterTransaction();
owner.afterTransactionCompletion( successful );
}
@Override
public JdbcSessionOwner getJdbcSessionOwner() {
return this.owner;
}
@Override
public DataStoreTransaction getResourceLocalTransaction() {
return logicalConnection.getPhysicalJdbcTransaction();
}
/**
* JDK serialization hook
*
* @param oos The stream into which to write our state
*
* @throws IOException Trouble accessing the stream
*/
public void serialize(ObjectOutputStream oos) throws IOException {
if ( ! isReadyForSerialization() ) {
throw new HibernateException( "Cannot serialize Session while connected" );
}
oos.writeBoolean( isUserSuppliedConnection );
oos.writeObject( connectionReleaseMode );
logicalConnection.serialize( oos );
}
/**
* JDK deserialization hook
*
* @param ois The stream into which to write our state
* @param JdbcSessionOwner The Jdbc Session owner which owns the JdbcCoordinatorImpl to be deserialized.
*
* @return The deserialized JdbcCoordinatorImpl
*
* @throws IOException Trouble accessing the stream
* @throws ClassNotFoundException Trouble reading the stream
*/
public static JdbcCoordinatorImpl deserialize(
ObjectInputStream ois,
JdbcSessionOwner owner) throws IOException, ClassNotFoundException {
final boolean isUserSuppliedConnection = ois.readBoolean();
final ConnectionReleaseMode connectionReleaseMode = (ConnectionReleaseMode) ois.readObject();
LogicalConnectionImplementor logicalConnection;
if ( isUserSuppliedConnection ) {
logicalConnection = LogicalConnectionProvidedImpl.deserialize( ois );
}
else {
logicalConnection = LogicalConnectionManagedImpl.deserialize(
ois,
owner.getJdbcConnectionAccess(),
owner.getJdbcSessionContext()
);
}
return new JdbcCoordinatorImpl( logicalConnection, isUserSuppliedConnection, connectionReleaseMode, owner );
}
}

View File

@ -1,393 +0,0 @@
/*
* 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;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.engine.jdbc.spi.NonDurableConnectionObserver;
import org.hibernate.engine.transaction.spi.TransactionContext;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.jboss.logging.Logger;
/**
* Standard Hibernate {@link org.hibernate.engine.jdbc.spi.LogicalConnection} implementation
* <p/>
* IMPL NOTE : Custom serialization handling!
*
* @author Steve Ebersole
* @author Brett Meyer
*/
public class LogicalConnectionImpl implements LogicalConnectionImplementor {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
LogicalConnectionImpl.class.getName()
);
private transient Connection physicalConnection;
private final transient ConnectionReleaseMode connectionReleaseMode;
private final transient JdbcServices jdbcServices;
private final transient JdbcConnectionAccess jdbcConnectionAccess;
private final transient List<ConnectionObserver> observers;
private final boolean isUserSuppliedConnection;
private boolean isClosed;
/**
* Constructs a LogicalConnectionImpl
*
* @param userSuppliedConnection The user-supplied connection
* @param connectionReleaseMode The connection release mode to use
* @param jdbcServices JdbcServices
* @param jdbcConnectionAccess JDBC Connection access
*/
public LogicalConnectionImpl(
Connection userSuppliedConnection,
ConnectionReleaseMode connectionReleaseMode,
JdbcServices jdbcServices,
JdbcConnectionAccess jdbcConnectionAccess) {
this(
connectionReleaseMode,
jdbcServices,
jdbcConnectionAccess,
(userSuppliedConnection != null),
false,
new ArrayList<ConnectionObserver>()
);
this.physicalConnection = userSuppliedConnection;
}
/**
* Constructs a LogicalConnectionImpl. This for used from deserialization
*/
private LogicalConnectionImpl(
ConnectionReleaseMode connectionReleaseMode,
JdbcServices jdbcServices,
JdbcConnectionAccess jdbcConnectionAccess,
boolean isUserSuppliedConnection,
boolean isClosed,
List<ConnectionObserver> observers) {
this.connectionReleaseMode = determineConnectionReleaseMode(
jdbcConnectionAccess, isUserSuppliedConnection, connectionReleaseMode
);
this.jdbcServices = jdbcServices;
this.jdbcConnectionAccess = jdbcConnectionAccess;
this.observers = observers;
this.isUserSuppliedConnection = isUserSuppliedConnection;
this.isClosed = isClosed;
}
private static ConnectionReleaseMode determineConnectionReleaseMode(
JdbcConnectionAccess jdbcConnectionAccess,
boolean isUserSuppliedConnection,
ConnectionReleaseMode connectionReleaseMode) {
if ( isUserSuppliedConnection ) {
return ConnectionReleaseMode.ON_CLOSE;
}
else if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT &&
! jdbcConnectionAccess.supportsAggressiveRelease() ) {
LOG.debug( "Connection provider reports to not support aggressive release; overriding" );
return ConnectionReleaseMode.AFTER_TRANSACTION;
}
else {
return connectionReleaseMode;
}
}
@Override
public JdbcServices getJdbcServices() {
return jdbcServices;
}
@Override
public void addObserver(ConnectionObserver observer) {
observers.add( observer );
}
@Override
public void removeObserver(ConnectionObserver connectionObserver) {
observers.remove( connectionObserver );
}
@Override
public boolean isOpen() {
return !isClosed;
}
@Override
public boolean isPhysicallyConnected() {
return physicalConnection != null;
}
@Override
public Connection getConnection() throws HibernateException {
if ( isClosed ) {
throw new HibernateException( "Logical connection is closed" );
}
if ( physicalConnection == null ) {
if ( isUserSuppliedConnection ) {
// should never happen
throw new HibernateException( "User-supplied connection was null" );
}
obtainConnection();
}
return physicalConnection;
}
@Override
public Connection close() {
LOG.trace( "Closing logical connection" );
final Connection c = isUserSuppliedConnection ? physicalConnection : null;
try {
if ( !isUserSuppliedConnection && physicalConnection != null ) {
releaseConnection();
}
return c;
}
finally {
// no matter what
physicalConnection = null;
isClosed = true;
LOG.trace( "Logical connection closed" );
for ( ConnectionObserver observer : observers ) {
observer.logicalConnectionClosed();
}
observers.clear();
}
}
@Override
public ConnectionReleaseMode getConnectionReleaseMode() {
return connectionReleaseMode;
}
/**
* Force aggressive release of the underlying connection.
*/
@Override
public void aggressiveRelease() {
if ( isUserSuppliedConnection ) {
LOG.debug( "Cannot aggressively release user-supplied connection; skipping" );
}
else {
LOG.debug( "Aggressively releasing JDBC connection" );
if ( physicalConnection != null ) {
releaseConnection();
}
}
}
/**
* Physically opens a JDBC Connection.
*
* @throws org.hibernate.JDBCException Indicates problem opening a connection
*/
private void obtainConnection() throws JDBCException {
LOG.debug( "Obtaining JDBC connection" );
try {
physicalConnection = jdbcConnectionAccess.obtainConnection();
for ( ConnectionObserver observer : observers ) {
observer.physicalConnectionObtained( physicalConnection );
}
LOG.debug( "Obtained JDBC connection" );
}
catch ( SQLException sqle) {
throw getJdbcServices().getSqlExceptionHelper().convert( sqle, "Could not open connection" );
}
}
/**
* Physically closes the JDBC Connection.
*
* @throws JDBCException Indicates problem closing a connection
*/
@Override
public void releaseConnection() throws JDBCException {
LOG.debug( "Releasing JDBC connection" );
if ( physicalConnection == null ) {
return;
}
try {
if ( !physicalConnection.isClosed() ) {
getJdbcServices().getSqlExceptionHelper().logAndClearWarnings( physicalConnection );
}
if ( !isUserSuppliedConnection ) {
jdbcConnectionAccess.releaseConnection( physicalConnection );
}
}
catch (SQLException e) {
throw getJdbcServices().getSqlExceptionHelper().convert( e, "Could not close connection" );
}
finally {
physicalConnection = null;
}
LOG.debug( "Released JDBC connection" );
for ( ConnectionObserver observer : observers ) {
observer.physicalConnectionReleased();
}
releaseNonDurableObservers();
}
private void releaseNonDurableObservers() {
final Iterator observers = this.observers.iterator();
while ( observers.hasNext() ) {
if ( NonDurableConnectionObserver.class.isInstance( observers.next() ) ) {
observers.remove();
}
}
}
@Override
public Connection manualDisconnect() {
if ( isClosed ) {
throw new IllegalStateException( "cannot manually disconnect because logical connection is already closed" );
}
final Connection c = physicalConnection;
releaseConnection();
return c;
}
@Override
public void manualReconnect(Connection suppliedConnection) {
if ( isClosed ) {
throw new IllegalStateException( "cannot manually reconnect because logical connection is already closed" );
}
if ( !isUserSuppliedConnection ) {
throw new IllegalStateException( "cannot manually reconnect unless Connection was originally supplied" );
}
else {
if ( suppliedConnection == null ) {
throw new IllegalArgumentException( "cannot reconnect a null user-supplied connection" );
}
else if ( suppliedConnection == physicalConnection ) {
LOG.debug( "reconnecting the same connection that is already connected; should this connection have been disconnected?" );
}
else if ( physicalConnection != null ) {
throw new IllegalArgumentException(
"cannot reconnect to a new user-supplied connection because currently connected; must disconnect before reconnecting."
);
}
physicalConnection = suppliedConnection;
LOG.debug( "Reconnected JDBC connection" );
}
}
@Override
public boolean isAutoCommit() {
if ( !isOpen() || ! isPhysicallyConnected() ) {
return true;
}
try {
return getConnection().getAutoCommit();
}
catch (SQLException e) {
throw jdbcServices.getSqlExceptionHelper().convert( e, "could not inspect JDBC autocommit mode" );
}
}
@Override
public boolean isUserSuppliedConnection() {
return isUserSuppliedConnection;
}
@Override
public void notifyObserversStatementPrepared() {
for ( ConnectionObserver observer : observers ) {
observer.statementPrepared();
}
}
/**
* Serialization hook
*
* @param oos The stream to write out state to
*
* @throws IOException Problem accessing stream
*/
public void serialize(ObjectOutputStream oos) throws IOException {
oos.writeBoolean( isUserSuppliedConnection );
oos.writeBoolean( isClosed );
final List<ConnectionObserver> durableConnectionObservers = new ArrayList<ConnectionObserver>();
for ( ConnectionObserver observer : observers ) {
if ( ! NonDurableConnectionObserver.class.isInstance( observer ) ) {
durableConnectionObservers.add( observer );
}
}
oos.writeInt( durableConnectionObservers.size() );
for ( ConnectionObserver observer : durableConnectionObservers ) {
oos.writeObject( observer );
}
}
/**
* Deserialization hook
*
* @param ois The stream to read our state from
* @param transactionContext The transactionContext which owns this logical connection
*
* @return The deserialized LogicalConnectionImpl
*
* @throws IOException Trouble accessing the stream
* @throws ClassNotFoundException Trouble reading the stream
*/
public static LogicalConnectionImpl deserialize(
ObjectInputStream ois,
TransactionContext transactionContext) throws IOException, ClassNotFoundException {
final boolean isUserSuppliedConnection = ois.readBoolean();
final boolean isClosed = ois.readBoolean();
final int observerCount = ois.readInt();
final List<ConnectionObserver> observers = CollectionHelper.arrayList( observerCount );
for ( int i = 0; i < observerCount; i++ ) {
observers.add( (ConnectionObserver) ois.readObject() );
}
return new LogicalConnectionImpl(
transactionContext.getConnectionReleaseMode(),
transactionContext.getTransactionEnvironment().getJdbcServices(),
transactionContext.getJdbcConnectionAccess(),
isUserSuppliedConnection,
isClosed,
observers
);
}
}

View File

@ -55,11 +55,13 @@ public class ResultSetReturnImpl implements ResultSetReturn {
public ResultSetReturnImpl(JdbcCoordinator jdbcCoordinator) {
this.jdbcCoordinator = jdbcCoordinator;
final JdbcServices jdbcServices = jdbcCoordinator.getTransactionCoordinator().getTransactionContext()
.getTransactionEnvironment()
.getJdbcServices();
final JdbcServices jdbcServices = jdbcCoordinator.getJdbcSessionOwner()
.getJdbcSessionContext()
.getServiceRegistry()
.getService( JdbcServices.class );
this.dialect = jdbcServices.getDialect();
this.sqlStatementLogger = jdbcServices.getSqlStatementLogger();
this.sqlExceptionHelper = jdbcServices.getSqlExceptionHelper();
}
@ -78,11 +80,11 @@ public class ResultSetReturnImpl implements ResultSetReturn {
try {
final ResultSet rs;
try {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().startStatementExecution();
jdbcExecuteStatementStart();
rs = statement.executeQuery();
}
finally {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().endStatementExecution();
jdbcExecuteStatementEnd();
}
postExtract( rs, statement );
return rs;
@ -92,6 +94,14 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
}
private void jdbcExecuteStatementEnd() {
jdbcCoordinator.getJdbcSessionOwner().getJdbcSessionContext().getObserver().jdbcExecuteStatementEnd();
}
private void jdbcExecuteStatementStart() {
jdbcCoordinator.getJdbcSessionOwner().getJdbcSessionContext().getObserver().jdbcExecuteStatementStart();
}
private boolean isTypeOf(final Statement statement, final Class<? extends Statement> type) {
if (isJdbc4) {
try {
@ -117,11 +127,11 @@ public class ResultSetReturnImpl implements ResultSetReturn {
try {
final ResultSet rs;
try {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().startStatementExecution();
jdbcExecuteStatementStart();
rs = dialect.getResultSet( callableStatement );
}
finally {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().endStatementExecution();
jdbcExecuteStatementEnd();
}
postExtract( rs, callableStatement );
return rs;
@ -137,11 +147,11 @@ public class ResultSetReturnImpl implements ResultSetReturn {
try {
final ResultSet rs;
try {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().startStatementExecution();
jdbcExecuteStatementStart();
rs = statement.executeQuery( sql );
}
finally {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().endStatementExecution();
jdbcExecuteStatementEnd();
}
postExtract( rs, statement );
return rs;
@ -157,7 +167,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
try {
final ResultSet rs;
try {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().startStatementExecution();
jdbcExecuteStatementStart();
if ( !statement.execute() ) {
while ( !statement.getMoreResults() && statement.getUpdateCount() != -1 ) {
// do nothing until we hit the resultset
@ -166,7 +176,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
rs = statement.getResultSet();
}
finally {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().endStatementExecution();
jdbcExecuteStatementEnd();
}
postExtract( rs, statement );
return rs;
@ -182,7 +192,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
try {
final ResultSet rs;
try {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().startStatementExecution();
jdbcExecuteStatementStart();
if ( !statement.execute( sql ) ) {
while ( !statement.getMoreResults() && statement.getUpdateCount() != -1 ) {
// do nothing until we hit the resultset
@ -191,7 +201,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
rs = statement.getResultSet();
}
finally {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().endStatementExecution();
jdbcExecuteStatementEnd();
}
postExtract( rs, statement );
return rs;
@ -204,14 +214,14 @@ public class ResultSetReturnImpl implements ResultSetReturn {
@Override
public int executeUpdate(PreparedStatement statement) {
try {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().startStatementExecution();
jdbcExecuteStatementStart();
return statement.executeUpdate();
}
catch (SQLException e) {
throw sqlExceptionHelper.convert( e, "could not execute statement" );
}
finally {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().endStatementExecution();
jdbcExecuteStatementEnd();
}
}
@ -219,20 +229,20 @@ public class ResultSetReturnImpl implements ResultSetReturn {
public int executeUpdate(Statement statement, String sql) {
sqlStatementLogger.logStatement( sql );
try {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().startStatementExecution();
jdbcExecuteStatementStart();
return statement.executeUpdate( sql );
}
catch (SQLException e) {
throw sqlExceptionHelper.convert( e, "could not execute statement" );
}
finally {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().endStatementExecution();
jdbcExecuteStatementEnd();
}
}
private void postExtract(ResultSet rs, Statement st) {
if ( rs != null ) {
jdbcCoordinator.register( rs, st );
jdbcCoordinator.getResourceRegistry().register( rs, st );
}
}

View File

@ -32,9 +32,10 @@ import java.sql.Statement;
import org.hibernate.AssertionFailure;
import org.hibernate.ScrollMode;
import org.hibernate.cfg.Settings;
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.StatementPreparer;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
/**
* Standard implementation of StatementPreparer
@ -60,7 +61,7 @@ class StatementPreparerImpl implements StatementPreparer {
}
protected final Connection connection() {
return logicalConnection().getConnection();
return logicalConnection().getPhysicalConnection();
}
protected final LogicalConnectionImplementor logicalConnection() {
@ -68,16 +69,14 @@ class StatementPreparerImpl implements StatementPreparer {
}
protected final SqlExceptionHelper sqlExceptionHelper() {
return jdbcCoordinator.getTransactionCoordinator().getTransactionContext().getTransactionEnvironment()
.getJdbcServices()
.getSqlExceptionHelper();
return getJdbcService().getSqlExceptionHelper();
}
@Override
public Statement createStatement() {
try {
final Statement statement = connection().createStatement();
jdbcCoordinator.register( statement );
jdbcCoordinator.getResourceRegistry().register( statement, true );
return statement;
}
catch ( SQLException e ) {
@ -173,21 +172,23 @@ class StatementPreparerImpl implements StatementPreparer {
protected final String sql;
protected StatementPreparationTemplate(String sql) {
this.sql = jdbcCoordinator.getTransactionCoordinator().getTransactionContext().onPrepareStatement( sql );
this.sql = jdbcCoordinator.getJdbcSessionOwner().getJdbcSessionContext().getStatementInspector().inspect(
sql
);
}
public PreparedStatement prepareStatement() {
try {
jdbcCoordinator.getLogicalConnection().getJdbcServices().getSqlStatementLogger().logStatement( sql );
getJdbcService().getSqlStatementLogger().logStatement( sql );
final PreparedStatement preparedStatement;
try {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().startPrepareStatement();
jdbcCoordinator.getJdbcSessionOwner().getJdbcSessionContext().getObserver().jdbcPrepareStatementStart();
preparedStatement = doPrepare();
setStatementTimeout( preparedStatement );
}
finally {
jdbcCoordinator.getTransactionCoordinator().getTransactionContext().endPrepareStatement();
jdbcCoordinator.getJdbcSessionOwner().getJdbcSessionContext().getObserver().jdbcPrepareStatementEnd();
}
postProcess( preparedStatement );
return preparedStatement;
@ -200,8 +201,8 @@ class StatementPreparerImpl implements StatementPreparer {
protected abstract PreparedStatement doPrepare() throws SQLException;
public void postProcess(PreparedStatement preparedStatement) throws SQLException {
jdbcCoordinator.register( preparedStatement );
logicalConnection().notifyObserversStatementPrepared();
jdbcCoordinator.getResourceRegistry().register( preparedStatement, true );
// logicalConnection().notifyObserversStatementPrepared();
}
private void setStatementTimeout(PreparedStatement preparedStatement) throws SQLException {
@ -212,6 +213,14 @@ class StatementPreparerImpl implements StatementPreparer {
}
}
private JdbcServices getJdbcService() {
return jdbcCoordinator
.getJdbcSessionOwner()
.getJdbcSessionContext()
.getServiceRegistry()
.getService( JdbcServices.class );
}
private abstract class QueryStatementPreparationTemplate extends StatementPreparationTemplate {
protected QueryStatementPreparationTemplate(String sql) {
super( sql );

View File

@ -25,13 +25,17 @@ package org.hibernate.engine.jdbc.spi;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.batch.spi.BatchKey;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.jdbc.WorkExecutorVisitable;
import org.hibernate.resource.jdbc.ResourceRegistry;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.resource.transaction.TransactionCoordinator;
import org.hibernate.resource.transaction.backend.store.spi.DataStoreTransactionAccess;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorOwner;
/**
* Coordinates JDBC-related activities.
@ -39,13 +43,13 @@ import org.hibernate.jdbc.WorkExecutorVisitable;
* @author Steve Ebersole
* @author Brett Meyer
*/
public interface JdbcCoordinator extends Serializable {
/**
* Retrieve the transaction coordinator associated with this JDBC coordinator.
*
* @return The transaction coordinator
*/
public TransactionCoordinator getTransactionCoordinator();
public interface JdbcCoordinator extends Serializable, TransactionCoordinatorOwner, DataStoreTransactionAccess {
// /**
// * Retrieve the transaction coordinator associated with this JDBC coordinator.
// *
// * @return The transaction coordinator
// */
// public TransactionCoordinator getTransactionCoordinator();
/**
* Retrieves the logical connection associated with this JDBC coordinator.
@ -105,7 +109,7 @@ public interface JdbcCoordinator extends Serializable {
*
* @return The {@link Connection} associated with the managed {@link #getLogicalConnection() logical connection}
*
* @see LogicalConnection#close
* @see org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor#close
*/
public Connection close();
@ -138,13 +142,6 @@ public interface JdbcCoordinator extends Serializable {
*/
public void cancelLastQuery();
/**
* Set the effective transaction timeout period for the current transaction, in seconds.
*
* @param seconds The number of seconds before a time out should occur.
*/
public void setTransactionTimeOut(int seconds);
/**
* Calculate the amount of time, in seconds, still remaining before transaction timeout occurs.
*
@ -155,52 +152,6 @@ public interface JdbcCoordinator extends Serializable {
*/
public int determineRemainingTransactionTimeOutPeriod();
/**
* Register a JDBC statement.
*
* @param statement The statement to register.
*/
public void register(Statement statement);
/**
* Release a previously registered statement.
*
* @param statement The statement to release.
*/
public void release(Statement statement);
/**
* Register a JDBC result set.
* <p/>
* Implementation note: Second parameter has been introduced to prevent
* multiple registrations of the same statement in case {@link ResultSet#getStatement()}
* does not return original {@link Statement} object.
*
* @param resultSet The result set to register.
* @param statement Statement from which {@link ResultSet} has been generated.
*/
public void register(ResultSet resultSet, Statement statement);
/**
* Release a previously registered result set.
*
* @param resultSet The result set to release.
* @param statement Statement from which {@link ResultSet} has been generated.
*/
public void release(ResultSet resultSet, Statement statement);
/**
* Does this registry currently have any registered resources?
*
* @return True if the registry does have registered resources; false otherwise.
*/
public boolean hasRegisteredResources();
/**
* Release all registered resources.
*/
public void releaseResources();
/**
* Enable connection releases
*/
@ -224,4 +175,13 @@ public interface JdbcCoordinator extends Serializable {
* @return {@code true} indicates the coordinator can be serialized.
*/
public boolean isReadyForSerialization();
/**
* The release mode under which this logical connection is operating.
*
* @return the release mode.
*/
public ConnectionReleaseMode getConnectionReleaseMode();
public ResourceRegistry getResourceRegistry();
}

View File

@ -1,71 +0,0 @@
/*
* 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;
/**
* LogicalConnection contract
*
* @author Steve Ebersole
*/
public interface LogicalConnection extends Serializable {
/**
* Is this logical connection open? Another phraseology sometimes used is: "are we
* logically connected"?
*
* @return True if logically connected; false otherwise.
*/
public boolean isOpen();
/**
* Is this logical connection instance "physically" connected. Meaning
* do we currently internally have a cached connection.
*
* @return True if physically connected; false otherwise.
*/
public boolean isPhysicallyConnected();
/**
* Retrieves the connection currently "logically" managed by this LogicalConnectionImpl.
* <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.
*
* @return The current Connection.
*/
public Connection getConnection();
/**
* Release the underlying connection and clean up any other resources associated
* with this logical connection.
* <p/>
* This leaves the logical connection in a "no longer usable" state.
*
* @return The application-supplied connection, or {@code null} if Hibernate was managing connection.
*/
public Connection close();
}

View File

@ -202,17 +202,18 @@ public class NativeSQLQueryPlan implements Serializable {
queryParameters.processFilters( this.customQuery.getSQL(), session );
final String sql = queryParameters.getFilteredSQL();
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
ps = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
try {
int col = 1;
col += bindPositionalParameters( ps, queryParameters, col, session );
col += bindNamedParameters( ps, queryParameters.getNamedParameters(), col, session );
result = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
result = session.getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
}
finally {
if ( ps != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}

View File

@ -481,7 +481,7 @@ public class ActionQueue {
}
list.clear();
session.getTransactionCoordinator().getJdbcCoordinator().executeBatch();
session.getJdbcCoordinator().executeBatch();
}
/**

View File

@ -56,13 +56,14 @@ import org.hibernate.UnknownProfileException;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.jdbc.Work;
import org.hibernate.loader.custom.CustomQuery;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.resource.transaction.TransactionCoordinator;
import org.hibernate.stat.SessionStatistics;
import org.hibernate.type.Type;
@ -359,11 +360,26 @@ public class SessionDelegatorBaseImpl implements SessionImplementor, Session {
return sessionImplementor.getTransactionCoordinator();
}
@Override
public JdbcCoordinator getJdbcCoordinator() {
return sessionImplementor.getJdbcCoordinator();
}
@Override
public boolean isClosed() {
return sessionImplementor.isClosed();
}
@Override
public boolean shouldAutoClose() {
return sessionImplementor.shouldAutoClose();
}
@Override
public boolean isAutoCloseSessionEnabled() {
return sessionImplementor.isAutoCloseSessionEnabled();
}
@Override
public LoadQueryInfluencers getLoadQueryInfluencers() {
return sessionImplementor.getLoadQueryInfluencers();

View File

@ -38,14 +38,16 @@ import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Transaction;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.loader.custom.CustomQuery;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.resource.transaction.TransactionCoordinator;
import org.hibernate.type.Type;
/**
@ -384,6 +386,8 @@ public interface SessionImplementor extends Serializable, LobCreationContext {
*/
public TransactionCoordinator getTransactionCoordinator();
public JdbcCoordinator getJdbcCoordinator();
/**
* Determine whether the session is closed. Provided separately from
* {@link #isOpen()} as this method does not attempt any JTA synchronization
@ -394,6 +398,10 @@ public interface SessionImplementor extends Serializable, LobCreationContext {
*/
public boolean isClosed();
public boolean shouldAutoClose();
public boolean isAutoCloseSessionEnabled();
/**
* Get the load query influencers associated with this session.
*

View File

@ -1,398 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.transaction.internal;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.ResourceClosedException;
import org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.engine.transaction.spi.JoinStatus;
import org.hibernate.engine.transaction.spi.SynchronizationRegistry;
import org.hibernate.engine.transaction.spi.TransactionContext;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.engine.transaction.spi.TransactionFactory;
import org.hibernate.engine.transaction.spi.TransactionImplementor;
import org.hibernate.engine.transaction.spi.TransactionObserver;
import org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization;
import org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorNonTrackingImpl;
import org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorTrackingImpl;
import org.hibernate.engine.transaction.synchronization.spi.SynchronizationCallbackCoordinator;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.CollectionHelper;
/**
* Standard implementation of the Hibernate {@link TransactionCoordinator}
* <p/>
* IMPL NOTE : Custom serialization handling!
*
* @author Steve Ebersole
*/
public final class TransactionCoordinatorImpl implements TransactionCoordinator {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( TransactionCoordinatorImpl.class );
private final transient TransactionContext transactionContext;
private final transient JdbcCoordinatorImpl jdbcCoordinator;
private final transient TransactionFactory transactionFactory;
private final transient TransactionEnvironment transactionEnvironment;
private final transient List<TransactionObserver> observers;
private final transient SynchronizationRegistryImpl synchronizationRegistry;
private transient TransactionImplementor currentHibernateTransaction;
private transient SynchronizationCallbackCoordinator callbackCoordinator;
private transient boolean open = true;
private transient boolean synchronizationRegistered;
private transient boolean ownershipTaken;
private transient boolean isDebugging = LOG.isDebugEnabled();
private transient boolean isTracing = LOG.isTraceEnabled();
public TransactionCoordinatorImpl(
Connection userSuppliedConnection,
TransactionContext transactionContext) {
this.transactionContext = transactionContext;
this.jdbcCoordinator = new JdbcCoordinatorImpl( userSuppliedConnection, this );
this.transactionEnvironment = transactionContext.getTransactionEnvironment();
this.transactionFactory = this.transactionEnvironment.getTransactionFactory();
this.observers = new ArrayList<TransactionObserver>();
this.synchronizationRegistry = new SynchronizationRegistryImpl();
reset();
final boolean registerSynchronization = transactionContext.isAutoCloseSessionEnabled()
|| transactionContext.isFlushBeforeCompletionEnabled()
|| transactionContext.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION;
if ( registerSynchronization ) {
pulse();
}
}
public TransactionCoordinatorImpl(
TransactionContext transactionContext,
JdbcCoordinatorImpl jdbcCoordinator,
List<TransactionObserver> observers) {
this.transactionContext = transactionContext;
this.jdbcCoordinator = jdbcCoordinator;
this.transactionEnvironment = transactionContext.getTransactionEnvironment();
this.transactionFactory = this.transactionEnvironment.getTransactionFactory();
this.observers = observers;
this.synchronizationRegistry = new SynchronizationRegistryImpl();
reset();
}
/**
* Reset the internal state.
*/
public void reset() {
synchronizationRegistered = false;
ownershipTaken = false;
if ( currentHibernateTransaction != null ) {
currentHibernateTransaction.invalidate();
}
currentHibernateTransaction = transactionFactory().createTransaction( this );
if ( transactionContext.shouldAutoJoinTransaction() ) {
currentHibernateTransaction.markForJoin();
currentHibernateTransaction.join();
}
// IMPL NOTE : reset clears synchronizations (following jta spec), but not observers!
synchronizationRegistry.clearSynchronizations();
}
public void afterTransaction(TransactionImplementor hibernateTransaction, int status) {
if (isTracing) {
LOG.trace( "after transaction completion" );
}
final boolean success = JtaStatusHelper.isCommitted( status );
if ( sessionFactory().getStatistics().isStatisticsEnabled() ) {
transactionEnvironment.getStatisticsImplementor().endTransaction( success );
}
getJdbcCoordinator().afterTransaction();
getTransactionContext().afterTransactionCompletion( hibernateTransaction, success );
sendAfterTransactionCompletionNotifications( hibernateTransaction, status );
reset();
}
private SessionFactoryImplementor sessionFactory() {
return transactionEnvironment.getSessionFactory();
}
public boolean isSynchronizationRegistered() {
return synchronizationRegistered;
}
@Override
@SuppressWarnings({"unchecked"})
public boolean isTransactionInProgress() {
return open && getTransaction().isActive() && getTransaction().getJoinStatus() == JoinStatus.JOINED;
}
@Override
public TransactionContext getTransactionContext() {
return transactionContext;
}
@Override
public JdbcCoordinator getJdbcCoordinator() {
return jdbcCoordinator;
}
private TransactionFactory transactionFactory() {
return transactionFactory;
}
private TransactionEnvironment getTransactionEnvironment() {
return transactionEnvironment;
}
@Override
public TransactionImplementor getTransaction() {
if ( !open ) {
throw new ResourceClosedException( "This TransactionCoordinator has been closed" );
}
pulse();
return currentHibernateTransaction;
}
public void afterNonTransactionalQuery(boolean success) {
// check to see if the connection is in auto-commit mode (no connection means aggressive connection
// release outside a JTA transaction context, so MUST be autocommit mode)
boolean isAutocommit = getJdbcCoordinator().getLogicalConnection().isAutoCommit();
getJdbcCoordinator().afterTransaction();
if ( isAutocommit ) {
for ( TransactionObserver observer : observers ) {
observer.afterCompletion( success, this.getTransaction() );
}
}
}
@Override
public void resetJoinStatus() {
getTransaction().resetJoinStatus();
}
@SuppressWarnings({"unchecked"})
private void attemptToRegisterJtaSync() {
if ( synchronizationRegistered ) {
return;
}
final JtaPlatform jtaPlatform = getTransactionEnvironment().getJtaPlatform();
if ( jtaPlatform == null ) {
// if no jta platform was registered we wont be able to register a jta synchronization
return;
}
// Has the local transaction (Hibernate facade) taken on the responsibility of driving the transaction inflow?
if ( currentHibernateTransaction.isInitiator() ) {
return;
}
final JoinStatus joinStatus = currentHibernateTransaction.getJoinStatus();
if ( joinStatus != JoinStatus.JOINED ) {
// the transaction is not (yet) joined, see if we should join...
if ( !transactionContext.shouldAutoJoinTransaction() ) {
// we are supposed to not auto join transactions; if the transaction is not marked for join
// we cannot go any further in attempting to join (register sync).
if ( joinStatus != JoinStatus.MARKED_FOR_JOINED ) {
if (isDebugging) {
LOG.debug( "Skipping JTA sync registration due to auto join checking" );
}
return;
}
}
}
// IMPL NOTE : At this point the local callback is the "maybe" one. The only time that needs to change is if
// we are able to successfully register the transaction synchronization in which case the local callback would become
// non driving. To that end, the following checks are simply opt outs where we are unable to register the
// synchronization
// Can we resister a synchronization
if ( !jtaPlatform.canRegisterSynchronization() ) {
if (isTracing) {
LOG.trace( "registered JTA platform says we cannot currently register synchronization; skipping" );
}
return;
}
// Should we resister a synchronization
if ( !transactionFactory().isJoinableJtaTransaction( this, currentHibernateTransaction ) ) {
if (isTracing) {
LOG.trace( "TransactionFactory reported no JTA transaction to join; skipping Synchronization registration" );
}
return;
}
jtaPlatform.registerSynchronization( new RegisteredSynchronization( getSynchronizationCallbackCoordinator() ) );
getSynchronizationCallbackCoordinator().synchronizationRegistered();
synchronizationRegistered = true;
if (isDebugging) {
LOG.debug( "successfully registered Synchronization" );
}
}
@Override
public SynchronizationCallbackCoordinator getSynchronizationCallbackCoordinator() {
if ( callbackCoordinator == null ) {
callbackCoordinator = transactionEnvironment.getSessionFactory().getSettings().isJtaTrackByThread()
? new SynchronizationCallbackCoordinatorTrackingImpl( this )
: new SynchronizationCallbackCoordinatorNonTrackingImpl( this );
}
return callbackCoordinator;
}
public void pulse() {
if ( transactionFactory().compatibleWithJtaSynchronization() ) {
// the configured transaction strategy says it supports callbacks via JTA synchronization, so attempt to
// register JTA synchronization if possible
attemptToRegisterJtaSync();
}
}
public Connection close() {
open = false;
reset();
observers.clear();
return jdbcCoordinator.close();
}
public SynchronizationRegistry getSynchronizationRegistry() {
return synchronizationRegistry;
}
public void addObserver(TransactionObserver observer) {
observers.add( observer );
}
@Override
public void removeObserver(TransactionObserver observer) {
observers.remove( observer );
}
@Override
@SuppressWarnings({"unchecked"})
public boolean isTransactionJoinable() {
return transactionFactory().isJoinableJtaTransaction( this, currentHibernateTransaction );
}
@Override
@SuppressWarnings({"unchecked"})
public boolean isTransactionJoined() {
return currentHibernateTransaction != null && currentHibernateTransaction.getJoinStatus() == JoinStatus.JOINED;
}
public void setRollbackOnly() {
getTransaction().markRollbackOnly();
}
@Override
public boolean takeOwnership() {
if ( ownershipTaken ) {
return false;
}
else {
ownershipTaken = true;
return true;
}
}
@Override
public void sendAfterTransactionBeginNotifications(TransactionImplementor hibernateTransaction) {
for ( TransactionObserver observer : observers ) {
observer.afterBegin( currentHibernateTransaction );
}
}
@Override
public void sendBeforeTransactionCompletionNotifications(TransactionImplementor hibernateTransaction) {
synchronizationRegistry.notifySynchronizationsBeforeTransactionCompletion();
for ( TransactionObserver observer : observers ) {
observer.beforeCompletion( hibernateTransaction );
}
}
@Override
public void sendAfterTransactionCompletionNotifications(TransactionImplementor hibernateTransaction, int status) {
final boolean successful = JtaStatusHelper.isCommitted( status );
for ( TransactionObserver observer : new ArrayList<TransactionObserver>( observers ) ) {
observer.afterCompletion( successful, hibernateTransaction );
}
synchronizationRegistry.notifySynchronizationsAfterTransactionCompletion( status );
}
@Override
public boolean isActive() {
return !sessionFactory().isClosed();
}
// serialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public void serialize(ObjectOutputStream oos) throws IOException {
jdbcCoordinator.serialize( oos );
oos.writeInt( observers.size() );
for ( TransactionObserver observer : observers ) {
oos.writeObject( observer );
}
}
public static TransactionCoordinatorImpl deserialize(
ObjectInputStream ois,
TransactionContext transactionContext) throws ClassNotFoundException, IOException {
final JdbcCoordinatorImpl jdbcCoordinator = JdbcCoordinatorImpl.deserialize( ois, transactionContext );
final int observerCount = ois.readInt();
final List<TransactionObserver> observers = CollectionHelper.arrayList( observerCount );
for ( int i = 0; i < observerCount; i++ ) {
observers.add( (TransactionObserver) ois.readObject() );
}
final TransactionCoordinatorImpl transactionCoordinator = new TransactionCoordinatorImpl(
transactionContext,
jdbcCoordinator,
observers
);
jdbcCoordinator.afterDeserialize( transactionCoordinator );
return transactionCoordinator;
}
}

View File

@ -0,0 +1,144 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) {DATE}, 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.transaction.internal;
import javax.transaction.Synchronization;
import org.jboss.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.TransactionException;
import org.hibernate.internal.CoreLogging;
import org.hibernate.resource.transaction.TransactionCoordinator;
import org.hibernate.resource.transaction.spi.TransactionStatus;
import static org.hibernate.resource.transaction.TransactionCoordinator.LocalInflow;
/**
* @author Andrea Boriero
*/
public class TransactionImpl implements Transaction {
private static final Logger LOG = CoreLogging.logger( TransactionImpl.class );
private final TransactionCoordinator transactionCoordinator;
private final LocalInflow transactionDriverControl;
private boolean valid = true;
public TransactionImpl(TransactionCoordinator transactionCoordinator) {
this.transactionCoordinator = transactionCoordinator;
this.transactionDriverControl = transactionCoordinator.getTransactionDriverControl();
}
@Override
public void begin() {
TransactionStatus status = transactionDriverControl.getStatus();
if ( !valid ) {
throw new TransactionException( "Transaction instance is no longer valid" );
}
if ( status == TransactionStatus.ACTIVE ) {
// throw new TransactionException( "nested transactions not supported" );
return;
}
LOG.debug( "begin" );
this.transactionDriverControl.begin();
}
@Override
public void commit() {
TransactionStatus status = transactionDriverControl.getStatus();
if ( status != TransactionStatus.ACTIVE ) {
throw new TransactionException( "Transaction not successfully started" );
}
LOG.debug( "committing" );
try {
this.transactionDriverControl.commit();
}
catch (Exception e) {
throw new TransactionException( "commit failed", e );
}
finally {
invalidate();
}
}
@Override
public void rollback() {
TransactionStatus status = transactionDriverControl.getStatus();
if ( status != TransactionStatus.ACTIVE && status != TransactionStatus.FAILED_COMMIT ) {
throw new TransactionException( "Transaction not successfully started" );
}
LOG.debug( "rolling back" );
if ( status != TransactionStatus.FAILED_COMMIT || allowFailedCommitToPhysicallyRollback() ) {
try {
this.transactionDriverControl.rollback();
}
catch (Exception e) {
throw new TransactionException( "rollback failed", e );
}
finally {
invalidate();
}
}
}
@Override
public TransactionStatus getStatus() {
return transactionDriverControl.getStatus();
}
@Override
public void registerSynchronization(Synchronization synchronization) throws HibernateException {
this.transactionCoordinator.getLocalSynchronizations().registerSynchronization( synchronization );
}
@Override
public void setTimeout(int seconds) {
this.transactionCoordinator.setTimeOut( seconds );
}
@Override
public int getTimeout() {
return this.transactionCoordinator.getTimeOut();
}
@Override
public void markRollbackOnly() {
transactionDriverControl.markRollbackOnly();
}
public void invalidate() {
valid = false;
}
protected boolean allowFailedCommitToPhysicallyRollback() {
return false;
}
}

View File

@ -1,208 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2007-2011, 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.transaction.internal.jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.spi.AbstractTransactionImpl;
import org.hibernate.engine.transaction.spi.IsolationDelegate;
import org.hibernate.engine.transaction.spi.JoinStatus;
import org.hibernate.engine.transaction.spi.LocalStatus;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.internal.CoreMessageLogger;
import org.jboss.logging.Logger;
/**
* {@link org.hibernate.Transaction} implementation based on transaction management through a JDBC {@link java.sql.Connection}.
* <p/>
* This the default transaction strategy.
*
* @author Anton van Straaten
* @author Gavin King
* @author Steve Ebersole
*/
public class JdbcTransaction extends AbstractTransactionImpl {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, JdbcTransaction.class.getName() );
private Connection managedConnection;
private boolean wasInitiallyAutoCommit;
private boolean isDriver;
protected JdbcTransaction(TransactionCoordinator transactionCoordinator) {
super( transactionCoordinator );
}
@Override
protected void doBegin() {
try {
if ( managedConnection != null ) {
throw new TransactionException( "Already have an associated managed connection" );
}
managedConnection = transactionCoordinator().getJdbcCoordinator().getLogicalConnection().getConnection();
wasInitiallyAutoCommit = managedConnection.getAutoCommit();
LOG.debugv( "initial autocommit status: {0}", wasInitiallyAutoCommit );
if ( wasInitiallyAutoCommit ) {
LOG.debug( "disabling autocommit" );
managedConnection.setAutoCommit( false );
}
}
catch( SQLException e ) {
throw new TransactionException( "JDBC begin transaction failed: ", e );
}
isDriver = transactionCoordinator().takeOwnership();
}
@Override
protected void afterTransactionBegin() {
if ( getTimeout() > 0 ) {
transactionCoordinator().getJdbcCoordinator().setTransactionTimeOut( getTimeout() );
}
transactionCoordinator().sendAfterTransactionBeginNotifications( this );
if ( isDriver ) {
transactionCoordinator().getTransactionContext().afterTransactionBegin( this );
}
}
@Override
protected void beforeTransactionCommit() {
transactionCoordinator().sendBeforeTransactionCompletionNotifications( this );
// basically, if we are the driver of the transaction perform a managed flush prior to
// physically committing the transaction
if ( isDriver && !transactionCoordinator().getTransactionContext().isFlushModeNever() ) {
// if an exception occurs during flush, user must call rollback()
transactionCoordinator().getTransactionContext().managedFlush();
}
if ( isDriver ) {
transactionCoordinator().getTransactionContext().beforeTransactionCompletion( this );
}
}
@Override
protected void doCommit() throws TransactionException {
try {
managedConnection.commit();
LOG.debug( "committed JDBC Connection" );
}
catch( SQLException e ) {
throw new TransactionException( "unable to commit against JDBC connection", e );
}
finally {
releaseManagedConnection();
}
}
private void releaseManagedConnection() {
try {
if ( wasInitiallyAutoCommit ) {
LOG.debug( "re-enabling autocommit" );
managedConnection.setAutoCommit( true );
}
managedConnection = null;
}
catch ( Exception e ) {
LOG.debug( "Could not toggle autocommit", e );
}
}
@Override
protected void afterTransactionCompletion(int status) {
transactionCoordinator().afterTransaction( this, status );
}
@Override
protected void afterAfterCompletion() {
if ( isDriver
&& transactionCoordinator().getTransactionContext().shouldAutoClose()
&& !transactionCoordinator().getTransactionContext().isClosed() ) {
try {
transactionCoordinator().getTransactionContext().managedClose();
}
catch (HibernateException e) {
LOG.unableToCloseSessionButSwallowingError( e );
}
}
}
@Override
protected void beforeTransactionRollBack() {
// nothing to do here
}
@Override
protected void doRollback() throws TransactionException {
try {
managedConnection.rollback();
LOG.debug( "rolled JDBC Connection" );
}
catch( SQLException e ) {
throw new TransactionException( "unable to rollback against JDBC connection", e );
}
finally {
releaseManagedConnection();
}
}
@Override
public boolean isInitiator() {
return isActive();
}
@Override
public IsolationDelegate createIsolationDelegate() {
return new JdbcIsolationDelegate( transactionCoordinator() );
}
@Override
public JoinStatus getJoinStatus() {
return isActive() ? JoinStatus.JOINED : JoinStatus.NOT_JOINED;
}
@Override
public void markRollbackOnly() {
// nothing to do here
}
@Override
public void join() {
// nothing to do
}
@Override
public void resetJoinStatus() {
// nothing to do
}
@Override
public boolean isActive() throws HibernateException {
return getLocalStatus() == LocalStatus.ACTIVE;
}
}

View File

@ -1,63 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2007-2011, 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.transaction.internal.jdbc;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.engine.transaction.spi.TransactionFactory;
/**
* Factory for {@link org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction} instances.
*
* @author Anton van Straaten
* @author Steve Ebersole
*/
public final class JdbcTransactionFactory implements TransactionFactory<JdbcTransaction> {
public static final String SHORT_NAME = "jdbc";
@Override
public JdbcTransaction createTransaction(TransactionCoordinator transactionCoordinator) {
return new JdbcTransaction( transactionCoordinator );
}
@Override
public boolean canBeDriver() {
return true;
}
@Override
public ConnectionReleaseMode getDefaultReleaseMode() {
return ConnectionReleaseMode.ON_CLOSE;
}
@Override
public boolean compatibleWithJtaSynchronization() {
return false;
}
@Override
public boolean isJoinableJtaTransaction(TransactionCoordinator transactionCoordinator, JdbcTransaction transaction) {
return false;
}
}

View File

@ -1,173 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2007-2011, 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.transaction.internal.jta;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.spi.AbstractTransactionImpl;
import org.hibernate.engine.transaction.spi.IsolationDelegate;
import org.hibernate.engine.transaction.spi.JoinStatus;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
/**
* Implements a transaction strategy for Container Managed Transaction (CMT) scenarios. All work is done in
* the context of the container managed transaction.
* <p/>
* The term 'CMT' is potentially misleading; the pertinent point simply being that the transactions are being
* managed by something other than the Hibernate transaction mechanism.
* <p/>
* Additionally, this strategy does *not* attempt to access or use the {@link javax.transaction.UserTransaction} since
* in the actual case CMT access to the {@link javax.transaction.UserTransaction} is explicitly disallowed. Instead
* we use the JTA {@link javax.transaction.Transaction} object obtained from the {@link TransactionManager}
*
* @author Gavin King
* @author Steve Ebersole
*/
public class CMTTransaction extends AbstractTransactionImpl {
private JoinStatus joinStatus = JoinStatus.NOT_JOINED;
protected CMTTransaction(TransactionCoordinator transactionCoordinator) {
super( transactionCoordinator );
}
protected TransactionManager transactionManager() {
return jtaPlatform().retrieveTransactionManager();
}
private TransactionManager getTransactionManager() {
return transactionManager();
}
@Override
protected void doBegin() {
transactionCoordinator().pulse();
}
@Override
protected void afterTransactionBegin() {
if ( ! transactionCoordinator().isSynchronizationRegistered() ) {
throw new TransactionException("Could not register synchronization for container transaction");
}
transactionCoordinator().sendAfterTransactionBeginNotifications( this );
transactionCoordinator().getTransactionContext().afterTransactionBegin( this );
}
@Override
protected void beforeTransactionCommit() {
boolean flush = ! transactionCoordinator().getTransactionContext().isFlushModeNever() &&
! transactionCoordinator().getTransactionContext().isFlushBeforeCompletionEnabled();
if ( flush ) {
// if an exception occurs during flush, user must call rollback()
transactionCoordinator().getTransactionContext().managedFlush();
}
}
@Override
protected void doCommit() {
// nothing to do
}
@Override
protected void beforeTransactionRollBack() {
// nothing to do
}
@Override
protected void doRollback() {
markRollbackOnly();
}
@Override
protected void afterTransactionCompletion(int status) {
// nothing to do
}
@Override
protected void afterAfterCompletion() {
// nothing to do
}
@Override
public boolean isActive() throws TransactionException {
return JtaStatusHelper.isActive( getTransactionManager() );
}
@Override
public IsolationDelegate createIsolationDelegate() {
return new JtaIsolationDelegate( transactionCoordinator() );
}
@Override
public boolean isInitiator() {
return false; // cannot be
}
@Override
public void markRollbackOnly() {
try {
getTransactionManager().setRollbackOnly();
}
catch ( SystemException se ) {
throw new TransactionException("Could not set transaction to rollback only", se);
}
}
@Override
public void markForJoin() {
joinStatus = JoinStatus.MARKED_FOR_JOINED;
}
@Override
public void join() {
if ( joinStatus != JoinStatus.MARKED_FOR_JOINED ) {
return;
}
if ( JtaStatusHelper.isActive( transactionManager() ) ) {
// register synchronization if needed
transactionCoordinator().pulse();
joinStatus = JoinStatus.JOINED;
}
else {
joinStatus = JoinStatus.NOT_JOINED;
}
}
@Override
public void resetJoinStatus() {
joinStatus = JoinStatus.NOT_JOINED;
}
boolean isJoinable() {
return ( joinStatus == JoinStatus.JOINED || joinStatus == JoinStatus.MARKED_FOR_JOINED ) &&
JtaStatusHelper.isActive( transactionManager() );
}
@Override
public JoinStatus getJoinStatus() {
return joinStatus;
}
}

View File

@ -1,77 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2007-2011, 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.transaction.internal.jta;
import javax.transaction.SystemException;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.engine.transaction.spi.TransactionFactory;
/**
* Factory for Container Managed Transaction (CMT) based transaction facades.
*
* @author Steve Ebersole
* @author Gavin King
*/
public class CMTTransactionFactory implements TransactionFactory<CMTTransaction> {
public static final String SHORT_NAME = "cmt";
@Override
public CMTTransaction createTransaction(TransactionCoordinator transactionCoordinator) {
return new CMTTransaction( transactionCoordinator );
}
@Override
public boolean canBeDriver() {
return false;
}
@Override
public ConnectionReleaseMode getDefaultReleaseMode() {
return ConnectionReleaseMode.AFTER_STATEMENT;
}
@Override
public boolean compatibleWithJtaSynchronization() {
return true;
}
@Override
public boolean isJoinableJtaTransaction(TransactionCoordinator transactionCoordinator, CMTTransaction transaction) {
try {
final int status = transactionCoordinator
.getTransactionContext()
.getTransactionEnvironment()
.getJtaPlatform()
.getCurrentStatus();
return JtaStatusHelper.isActive( status );
}
catch( SystemException se ) {
throw new TransactionException( "Unable to check transaction status", se );
}
}
}

View File

@ -1,285 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2007-2011, 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.transaction.internal.jta;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import org.hibernate.HibernateException;
import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.spi.AbstractTransactionImpl;
import org.hibernate.engine.transaction.spi.IsolationDelegate;
import org.hibernate.engine.transaction.spi.JoinStatus;
import org.hibernate.engine.transaction.spi.LocalStatus;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
/**
* Implements a transaction strategy based on transaction management through a JTA {@link UserTransaction}.
*
* @author Gavin King
* @author Steve Ebersole
* @author Les Hazlewood
*/
public class JtaTransaction extends AbstractTransactionImpl {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( JtaTransaction.class );
private UserTransaction userTransaction;
private boolean isInitiator;
private boolean isDriver;
protected JtaTransaction(TransactionCoordinator transactionCoordinator) {
super( transactionCoordinator );
}
@SuppressWarnings( {"UnusedDeclaration"})
public UserTransaction getUserTransaction() {
return userTransaction;
}
@Override
protected void doBegin() {
LOG.debug( "begin" );
userTransaction = locateUserTransaction();
try {
if ( userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION ) {
userTransaction.begin();
isInitiator = true;
LOG.debug( "Began a new JTA transaction" );
}
}
catch ( Exception e ) {
throw new TransactionException( "JTA transaction begin failed", e );
}
}
private UserTransaction locateUserTransaction() {
final UserTransaction userTransaction = jtaPlatform().retrieveUserTransaction();
if ( userTransaction == null ) {
throw new TransactionException( "Unable to locate JTA UserTransaction" );
}
return userTransaction;
}
@Override
protected void afterTransactionBegin() {
transactionCoordinator().pulse();
if ( !transactionCoordinator().isSynchronizationRegistered() ) {
isDriver = transactionCoordinator().takeOwnership();
}
applyTimeout();
transactionCoordinator().sendAfterTransactionBeginNotifications( this );
transactionCoordinator().getTransactionContext().afterTransactionBegin( this );
}
private void applyTimeout() {
if ( getTimeout() > 0 ) {
if ( userTransaction != null ) {
try {
userTransaction.setTransactionTimeout( getTimeout() );
}
catch ( SystemException e ) {
throw new TransactionException( "Unable to apply requested transaction timeout", e );
}
}
else {
LOG.debug( "Unable to apply requested transaction timeout; no UserTransaction. Will try later" );
}
}
}
@Override
protected void beforeTransactionCommit() {
transactionCoordinator().sendBeforeTransactionCompletionNotifications( this );
final boolean flush = ! transactionCoordinator().getTransactionContext().isFlushModeNever() &&
( isDriver || ! transactionCoordinator().getTransactionContext().isFlushBeforeCompletionEnabled() );
if ( flush ) {
// if an exception occurs during flush, user must call rollback()
transactionCoordinator().getTransactionContext().managedFlush();
}
if ( isDriver && isInitiator ) {
transactionCoordinator().getTransactionContext().beforeTransactionCompletion( this );
}
closeIfRequired();
}
private void closeIfRequired() throws HibernateException {
final boolean close = isDriver &&
transactionCoordinator().getTransactionContext().shouldAutoClose() &&
! transactionCoordinator().getTransactionContext().isClosed();
if ( close ) {
transactionCoordinator().getTransactionContext().managedClose();
}
}
@Override
protected void doCommit() {
try {
if ( isInitiator ) {
userTransaction.commit();
LOG.debug( "Committed JTA UserTransaction" );
}
}
catch ( Exception e ) {
throw new TransactionException( "JTA commit failed: ", e );
}
}
@Override
protected void afterTransactionCompletion(int status) {
// nothing to do
}
@Override
protected void afterAfterCompletion() {
// this method is a noop if there is a Synchronization!
try {
if ( isDriver ) {
if ( !isInitiator ) {
LOG.setManagerLookupClass();
}
try {
transactionCoordinator().afterTransaction( this, userTransaction.getStatus() );
}
catch (SystemException e) {
throw new TransactionException( "Unable to determine UserTransaction status", e );
}
}
}
finally {
isInitiator = false;
}
}
@Override
protected void beforeTransactionRollBack() {
// nothing to do
}
@Override
protected void doRollback() {
try {
if ( isInitiator ) {
// failed commits automatically rollback the transaction per JTA spec
if ( getLocalStatus() != LocalStatus.FAILED_COMMIT ) {
userTransaction.rollback();
LOG.debug( "Rolled back JTA UserTransaction" );
}
}
else {
markRollbackOnly();
}
}
catch ( Exception e ) {
throw new TransactionException( "JTA rollback failed", e );
}
}
@Override
public void markRollbackOnly() {
LOG.trace( "Marking transaction for rollback only" );
try {
if ( userTransaction == null ) {
userTransaction = locateUserTransaction();
}
userTransaction.setRollbackOnly();
LOG.debug( "set JTA UserTransaction to rollback only" );
}
catch (SystemException e) {
LOG.debug( "Unable to mark transaction for rollback only", e );
}
}
@Override
public IsolationDelegate createIsolationDelegate() {
return new JtaIsolationDelegate( transactionCoordinator() );
}
@Override
public boolean isInitiator() {
return isInitiator;
}
@Override
public boolean isActive() throws HibernateException {
if ( getLocalStatus() != LocalStatus.ACTIVE ) {
return false;
}
final int status;
try {
status = userTransaction.getStatus();
}
catch ( SystemException se ) {
throw new TransactionException( "Could not determine transaction status: ", se );
}
return JtaStatusHelper.isActive( status );
}
@Override
public void setTimeout(int seconds) {
super.setTimeout( seconds );
applyTimeout();
}
@Override
public void join() {
}
@Override
public void resetJoinStatus() {
}
@Override
public JoinStatus getJoinStatus() {
// if we already have the UserTransaction cached locally, use it to avoid JNDI look ups
if ( this.userTransaction != null ) {
return JtaStatusHelper.isActive( this.userTransaction ) ? JoinStatus.JOINED : JoinStatus.NOT_JOINED;
}
// Otherwise, try to use the TransactionManager since it is generally cached
TransactionManager transactionManager = jtaPlatform().retrieveTransactionManager();
if ( transactionManager != null ) {
return JtaStatusHelper.isActive( transactionManager ) ? JoinStatus.JOINED : JoinStatus.NOT_JOINED;
}
// Finally, look up the UserTransaction
UserTransaction userTransaction = jtaPlatform().retrieveUserTransaction();
return userTransaction != null && JtaStatusHelper.isActive( userTransaction )
? JoinStatus.JOINED
: JoinStatus.NOT_JOINED;
}
}

View File

@ -1,104 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2007-2011, 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.transaction.internal.jta;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.engine.transaction.spi.TransactionFactory;
/**
* Factory for {@link JtaTransaction} instances.
*
* @author Gavin King
* @author Steve Ebersole
* @author Les Hazlewood
*/
public class JtaTransactionFactory implements TransactionFactory<JtaTransaction> {
public static final String SHORT_NAME = "jta";
@Override
public JtaTransaction createTransaction(TransactionCoordinator transactionCoordinator) {
return new JtaTransaction( transactionCoordinator );
}
@Override
public boolean canBeDriver() {
return true;
}
@Override
public ConnectionReleaseMode getDefaultReleaseMode() {
return ConnectionReleaseMode.AFTER_STATEMENT;
}
@Override
public boolean compatibleWithJtaSynchronization() {
return true;
}
@Override
public boolean isJoinableJtaTransaction(TransactionCoordinator transactionCoordinator, JtaTransaction transaction) {
try {
// Essentially:
// 1) If we have a local (Hibernate) transaction in progress
// and it already has the UserTransaction cached, use that
// UserTransaction to determine the status.
// 2) If a transaction manager has been located, use
// that transaction manager to determine the status.
// 3) Finally, as the last resort, try to lookup the
// UserTransaction via JNDI and use that to determine the
// status.
if ( transaction != null ) {
UserTransaction ut = transaction.getUserTransaction();
if ( ut != null ) {
return JtaStatusHelper.isActive( ut );
}
}
final JtaPlatform jtaPlatform = transactionCoordinator
.getTransactionContext()
.getTransactionEnvironment()
.getJtaPlatform();
if ( jtaPlatform == null ) {
throw new TransactionException( "Unable to check transaction status" );
}
if ( jtaPlatform.retrieveTransactionManager() != null ) {
return JtaStatusHelper.isActive( jtaPlatform.retrieveTransactionManager().getStatus() );
}
else {
final UserTransaction ut = jtaPlatform.retrieveUserTransaction();
return ut != null && JtaStatusHelper.isActive( ut );
}
}
catch ( SystemException se ) {
throw new TransactionException( "Unable to check transaction status", se );
}
}
}

View File

@ -1,251 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.transaction.spi;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import org.hibernate.HibernateException;
import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.internal.CoreLogging;
import org.jboss.logging.Logger;
/**
* Abstract support for creating {@link TransactionImplementor transaction} implementations
*
* @author Steve Ebersole
*/
public abstract class AbstractTransactionImpl implements TransactionImplementor {
private static final Logger LOG = CoreLogging.logger( AbstractTransactionImpl.class );
private final TransactionCoordinator transactionCoordinator;
private boolean valid = true;
private LocalStatus localStatus = LocalStatus.NOT_ACTIVE;
private int timeout = -1;
protected AbstractTransactionImpl(TransactionCoordinator transactionCoordinator) {
this.transactionCoordinator = transactionCoordinator;
}
@Override
public void invalidate() {
valid = false;
}
/**
* Perform the actual steps of beginning a transaction according to the strategy.
*
* @throws org.hibernate.TransactionException Indicates a problem beginning the transaction
*/
protected abstract void doBegin();
/**
* Perform the actual steps of committing a transaction according to the strategy.
*
* @throws org.hibernate.TransactionException Indicates a problem committing the transaction
*/
protected abstract void doCommit();
/**
* Perform the actual steps of rolling back a transaction according to the strategy.
*
* @throws org.hibernate.TransactionException Indicates a problem rolling back the transaction
*/
protected abstract void doRollback();
protected abstract void afterTransactionBegin();
protected abstract void beforeTransactionCommit();
protected abstract void beforeTransactionRollBack();
protected abstract void afterTransactionCompletion(int status);
protected abstract void afterAfterCompletion();
/**
* Provide subclasses with access to the transaction coordinator.
*
* @return This transaction's context.
*/
protected TransactionCoordinator transactionCoordinator() {
return transactionCoordinator;
}
/**
* Provide subclasses with convenient access to the configured {@link JtaPlatform}
*
* @return The {@link org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform}
*/
protected JtaPlatform jtaPlatform() {
return transactionCoordinator().getTransactionContext().getTransactionEnvironment().getJtaPlatform();
}
@Override
public void registerSynchronization(Synchronization synchronization) {
transactionCoordinator().getSynchronizationRegistry().registerSynchronization( synchronization );
}
@Override
public LocalStatus getLocalStatus() {
return localStatus;
}
@Override
public boolean isActive() {
return localStatus == LocalStatus.ACTIVE && doExtendedActiveCheck();
}
@Override
public boolean isParticipating() {
return getJoinStatus() == JoinStatus.JOINED && isActive();
}
@Override
public boolean wasCommitted() {
return localStatus == LocalStatus.COMMITTED;
}
@Override
public boolean wasRolledBack() throws HibernateException {
return localStatus == LocalStatus.ROLLED_BACK;
}
/**
* Active has been checked against local state. Perform any needed checks against resource transactions.
*
* @return {@code true} if the extended active check checks out as well; false otherwise.
*/
protected boolean doExtendedActiveCheck() {
return true;
}
@Override
public void begin() throws HibernateException {
if ( !valid ) {
throw new TransactionException( "Transaction instance is no longer valid" );
}
if ( localStatus == LocalStatus.ACTIVE ) {
throw new TransactionException( "nested transactions not supported" );
}
if ( localStatus != LocalStatus.NOT_ACTIVE ) {
throw new TransactionException( "reuse of Transaction instances not supported" );
}
LOG.debug( "begin" );
doBegin();
localStatus = LocalStatus.ACTIVE;
afterTransactionBegin();
}
@Override
public void commit() throws HibernateException {
if ( localStatus != LocalStatus.ACTIVE ) {
throw new TransactionException( "Transaction not successfully started" );
}
LOG.debug( "committing" );
beforeTransactionCommit();
try {
doCommit();
localStatus = LocalStatus.COMMITTED;
afterTransactionCompletion( Status.STATUS_COMMITTED );
}
catch (Exception e) {
localStatus = LocalStatus.FAILED_COMMIT;
afterTransactionCompletion( Status.STATUS_UNKNOWN );
throw new TransactionException( "commit failed", e );
}
finally {
invalidate();
afterAfterCompletion();
}
}
protected boolean allowFailedCommitToPhysicallyRollback() {
return false;
}
@Override
public void rollback() throws HibernateException {
if ( localStatus != LocalStatus.ACTIVE && localStatus != LocalStatus.FAILED_COMMIT ) {
throw new TransactionException( "Transaction not successfully started" );
}
LOG.debug( "rolling back" );
beforeTransactionRollBack();
if ( localStatus != LocalStatus.FAILED_COMMIT || allowFailedCommitToPhysicallyRollback() ) {
try {
doRollback();
localStatus = LocalStatus.ROLLED_BACK;
afterTransactionCompletion( Status.STATUS_ROLLEDBACK );
}
catch (Exception e) {
afterTransactionCompletion( Status.STATUS_UNKNOWN );
throw new TransactionException( "rollback failed", e );
}
finally {
invalidate();
afterAfterCompletion();
}
}
}
@Override
public void setTimeout(int seconds) {
timeout = seconds;
}
@Override
public int getTimeout() {
return timeout;
}
@Override
public void markForJoin() {
// generally speaking this is no-op
}
@Override
public void join() {
// generally speaking this is no-op
}
@Override
public void resetJoinStatus() {
// generally speaking this is no-op
}
}

View File

@ -1,130 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.transaction.spi;
import java.io.Serializable;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
/**
* Access to services needed in the context of processing transaction requests.
* <p/>
* The context is roughly speaking equivalent to the Hibernate session, as opposed to the {@link TransactionEnvironment}
* which is roughly equivalent to the Hibernate session factory
*
* @author Steve Ebersole
*/
public interface TransactionContext extends Serializable {
/**
* Obtain the {@link TransactionEnvironment} associated with this context.
*
* @return The transaction environment.
*/
public TransactionEnvironment getTransactionEnvironment();
/**
* Get the mode for releasing JDBC connection in effect for ths context.
*
* @return The connection release mode.
*/
public ConnectionReleaseMode getConnectionReleaseMode();
/**
* Should transactions be auto joined? Generally this is only a concern for CMT transactions. The default
* should be to auto join. JPA defines an explicit operation for joining a CMT transaction.
*
* @return Should we automatically join transactions
*/
public boolean shouldAutoJoinTransaction();
/**
* Should session automatically be closed after transaction completion in this context?
*
* @return {@literal true}/{@literal false} appropriately.
*/
public boolean isAutoCloseSessionEnabled();
/**
* Is this context already closed?
*
* @return {@literal true}/{@literal false} appropriately.
*/
public boolean isClosed();
/**
* Should flushes only happen manually for this context?
*
* @return {@literal true}/{@literal false} appropriately.
*/
public boolean isFlushModeNever();
/**
* Should before transaction completion processing perform a flush when initiated from JTA synchronization for this
* context?
*
* @return {@literal true}/{@literal false} appropriately.
*/
public boolean isFlushBeforeCompletionEnabled();
/**
* Perform a managed flush.
*/
public void managedFlush();
/**
* Should JTA synchronization processing perform a automatic close (call to {@link #managedClose} for this
* context?
*
* @return {@literal true}/{@literal false} appropriately.
*/
public boolean shouldAutoClose();
/**
* Perform a managed close.
*/
public void managedClose();
public void afterTransactionBegin(TransactionImplementor hibernateTransaction);
public void beforeTransactionCompletion(TransactionImplementor hibernateTransaction);
public void afterTransactionCompletion(TransactionImplementor hibernateTransaction, boolean successful);
public String onPrepareStatement(String sql);
public JdbcConnectionAccess getJdbcConnectionAccess();
public void startPrepareStatement();
public void endPrepareStatement();
public void startStatementExecution();
public void endStatementExecution();
public void startBatchExecution();
public void endBatchExecution();
}

View File

@ -1,146 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.transaction.spi;
import java.io.Serializable;
import java.sql.Connection;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.transaction.synchronization.spi.SynchronizationCallbackCoordinator;
/**
* Acts as the coordinator between the Hibernate engine and physical transactions.
*
* @author Steve Ebersole
*/
public interface TransactionCoordinator extends Serializable {
/**
* Retrieves the context in which this coordinator operates.
*
* @return The context of the coordinator
*/
public TransactionContext getTransactionContext();
/**
* Retrieves the JDBC coordinator currently operating within this transaction coordinator.
*
* @return The JDBC coordinator.
*/
public JdbcCoordinator getJdbcCoordinator();
/**
* Get the Hibernate transaction facade object currently associated with this coordinator.
*
* @return The current Hibernate transaction.
*/
public TransactionImplementor getTransaction();
/**
* Obtain the {@link javax.transaction.Synchronization} registry associated with this coordinator.
*
* @return The registry
*/
public SynchronizationRegistry getSynchronizationRegistry();
/**
* Adds an observer to the coordinator.
* <p/>
* Unlike synchronizations added to the {@link #getSynchronizationRegistry() registry}, observers are not to be
* cleared on transaction completion.
*
* @param observer The observer to add.
*/
public void addObserver(TransactionObserver observer);
/**
* Removed an observer from the coordinator.
*
* @param observer The observer to remove.
*/
public void removeObserver(TransactionObserver observer);
/**
* Can we join to the underlying transaction?
*
* @return {@literal true} if the underlying transaction can be joined or is already joined; {@literal false}
* otherwise.
*
* @see TransactionFactory#isJoinableJtaTransaction(TransactionCoordinator, TransactionImplementor)
*/
public boolean isTransactionJoinable();
/**
* Is the underlying transaction already joined?
*
* @return {@literal true} if the underlying transaction is already joined; {@literal false} otherwise.
*/
public boolean isTransactionJoined();
/**
* Reset the transaction's join status.
*/
public void resetJoinStatus();
/**
* Are we "in" an active and joined transaction
*
* @return {@literal true} if there is currently a transaction in progress; {@literal false} otherwise.
*/
public boolean isTransactionInProgress();
/**
* Attempts to register JTA synchronization if possible and needed.
*/
public void pulse();
/**
* Close the transaction context, returning any user supplied connection from the underlying JDBC coordinator.
*
* @return The user supplied connection (if one).
*/
public Connection close();
/**
* Performs actions needed after execution of a non-transactional query.
*
* @param success Was the query successfully performed
*/
public void afterNonTransactionalQuery(boolean success);
public void setRollbackOnly();
public SynchronizationCallbackCoordinator getSynchronizationCallbackCoordinator();
public boolean isSynchronizationRegistered();
public boolean takeOwnership();
public void afterTransaction(TransactionImplementor hibernateTransaction, int status);
public void sendAfterTransactionBeginNotifications(TransactionImplementor hibernateTransaction);
public void sendBeforeTransactionCompletionNotifications(TransactionImplementor hibernateTransaction);
public void sendAfterTransactionCompletionNotifications(TransactionImplementor hibernateTransaction, int status);
public boolean isActive();
}

View File

@ -1,83 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.transaction.spi;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.service.Service;
/**
* Contract for transaction creation, as well as providing metadata and contextual information about that creation.
*
* @author Steve Ebersole
*/
public interface TransactionFactory<T extends TransactionImplementor> extends Service {
/**
* Construct a transaction instance compatible with this strategy.
*
* @param coordinator The coordinator for this transaction
*
* @return The appropriate transaction instance.
*
* @throws org.hibernate.HibernateException Indicates a problem constructing the transaction.
*/
public T createTransaction(TransactionCoordinator coordinator);
/**
* Can the transactions created from this strategy act as the driver? In other words can the user actually manage
* transactions with this strategy?
*
* @return {@literal true} if the transaction strategy represented by this factory can act as the driver callback;
* {@literal false} otherwise.
*/
public boolean canBeDriver();
/**
* Should we attempt to register JTA transaction {@link javax.transaction.Synchronization synchronizations}.
* <p/>
* In other words, is this strategy JTA-based?
*
* @return {@literal true} if the transaction strategy represented by this factory is compatible with registering
* {@link javax.transaction.Synchronization synchronizations}; {@literal false} otherwise.
*/
public boolean compatibleWithJtaSynchronization();
/**
* Can the underlying transaction represented by the passed Hibernate {@link TransactionImplementor} be joined?
*
* @param transactionCoordinator The transaction coordinator
* @param transaction The current Hibernate transaction
*
* @return {@literal true} is the transaction can be joined; {@literal false} otherwise.
*/
public boolean isJoinableJtaTransaction(TransactionCoordinator transactionCoordinator, T transaction);
/**
* Get the default connection release mode.
*
* @return The default release mode associated with this strategy
*/
public ConnectionReleaseMode getDefaultReleaseMode();
}

View File

@ -31,27 +31,22 @@ package org.hibernate.engine.transaction.spi;
public interface TransactionObserver {
/**
* Callback for processing the beginning of a transaction.
*
* <p/>
* Do not rely on this being called as the transaction mat be started in a manner other than through the
* {@link org.hibernate.Transaction} API.
*
* @param transaction The Hibernate transaction
*/
public void afterBegin(TransactionImplementor transaction);
public void afterBegin();
/**
* Callback for processing the initial phase of transaction completion.
*
* @param transaction The Hibernate transaction
*/
public void beforeCompletion(TransactionImplementor transaction);
public void beforeCompletion();
/**
* Callback for processing the last phase of transaction completion.
*
* @param successful Was the transaction successful?
* @param transaction The Hibernate transaction
*/
public void afterCompletion(boolean successful, TransactionImplementor transaction);
public void afterCompletion(boolean successful);
}

View File

@ -1,194 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.transaction.synchronization.internal;
import javax.transaction.SystemException;
import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.engine.transaction.spi.TransactionContext;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.engine.transaction.synchronization.spi.AfterCompletionAction;
import org.hibernate.engine.transaction.synchronization.spi.ExceptionMapper;
import org.hibernate.engine.transaction.synchronization.spi.ManagedFlushChecker;
import org.hibernate.engine.transaction.synchronization.spi.SynchronizationCallbackCoordinator;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
/**
* Manages callbacks from the {@link javax.transaction.Synchronization} registered by Hibernate.
*
* @author Steve Ebersole
*/
public class SynchronizationCallbackCoordinatorNonTrackingImpl implements SynchronizationCallbackCoordinator {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger(
SynchronizationCallbackCoordinatorNonTrackingImpl.class
);
private final TransactionCoordinator transactionCoordinator;
private ManagedFlushChecker managedFlushChecker;
private AfterCompletionAction afterCompletionAction;
private ExceptionMapper exceptionMapper;
public SynchronizationCallbackCoordinatorNonTrackingImpl(TransactionCoordinator transactionCoordinator) {
this.transactionCoordinator = transactionCoordinator;
reset();
}
public void reset() {
managedFlushChecker = STANDARD_MANAGED_FLUSH_CHECKER;
exceptionMapper = STANDARD_EXCEPTION_MAPPER;
afterCompletionAction = STANDARD_AFTER_COMPLETION_ACTION;
}
protected final TransactionCoordinator transactionCoordinator() {
return transactionCoordinator;
}
private TransactionContext transactionContext() {
return transactionCoordinator.getTransactionContext();
}
@Override
public void setManagedFlushChecker(ManagedFlushChecker managedFlushChecker) {
this.managedFlushChecker = managedFlushChecker;
}
@Override
public void setExceptionMapper(ExceptionMapper exceptionMapper) {
this.exceptionMapper = exceptionMapper;
}
@Override
public void setAfterCompletionAction(AfterCompletionAction afterCompletionAction) {
this.afterCompletionAction = afterCompletionAction;
}
// sync callbacks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public void beforeCompletion() {
LOG.trace( "Transaction before completion callback" );
if ( !transactionCoordinator.isActive() ) {
return;
}
boolean flush;
try {
final int status = transactionCoordinator.getTransactionContext().getTransactionEnvironment()
.getJtaPlatform().getCurrentStatus();
flush = managedFlushChecker.shouldDoManagedFlush( transactionCoordinator, status );
}
catch ( SystemException se ) {
setRollbackOnly();
throw exceptionMapper.mapStatusCheckFailure(
"could not determine transaction status in beforeCompletion()", se );
}
try {
if ( flush ) {
LOG.trace( "Automatically flushing session" );
transactionCoordinator.getTransactionContext().managedFlush();
}
}
catch ( RuntimeException re ) {
setRollbackOnly();
throw exceptionMapper.mapManagedFlushFailure( "error during managed flush", re );
}
finally {
transactionCoordinator.sendBeforeTransactionCompletionNotifications( null );
transactionCoordinator.getTransactionContext().beforeTransactionCompletion( null );
}
}
private void setRollbackOnly() {
transactionCoordinator.setRollbackOnly();
}
@Override
public void afterCompletion(int status) {
doAfterCompletion( status );
}
protected void doAfterCompletion(int status) {
LOG.tracef( "Starting transaction afterCompletion callback [status=%s]", status );
if ( !transactionCoordinator.isActive() ) {
return;
}
try {
afterCompletionAction.doAction( transactionCoordinator, status );
transactionCoordinator.afterTransaction( null, status );
}
finally {
reset();
if ( transactionContext().shouldAutoClose() && !transactionContext().isClosed() ) {
LOG.trace( "Automatically closing session" );
transactionContext().managedClose();
}
}
}
@Override
public void synchronizationRegistered() {
}
@Override
public void processAnyDelayedAfterCompletion() {
}
private static final ManagedFlushChecker STANDARD_MANAGED_FLUSH_CHECKER = new ManagedFlushChecker() {
@Override
public boolean shouldDoManagedFlush(TransactionCoordinator coordinator, int jtaStatus) {
return !coordinator.getTransactionContext().isClosed()
&& !coordinator.getTransactionContext().isFlushModeNever()
&& coordinator.getTransactionContext().isFlushBeforeCompletionEnabled()
&& !JtaStatusHelper.isRollback( jtaStatus );
}
};
private static final ExceptionMapper STANDARD_EXCEPTION_MAPPER = new ExceptionMapper() {
@Override
public RuntimeException mapStatusCheckFailure(String message, SystemException systemException) {
LOG.error( LOG.unableToDetermineTransactionStatus(), systemException );
return new TransactionException( "could not determine transaction status in beforeCompletion()",
systemException );
}
@Override
public RuntimeException mapManagedFlushFailure(String message, RuntimeException failure) {
LOG.unableToPerformManagedFlush( failure.getMessage() );
return failure;
}
};
private static final AfterCompletionAction STANDARD_AFTER_COMPLETION_ACTION = new AfterCompletionAction() {
@Override
public void doAction(TransactionCoordinator transactionCoordinator, int status) {
// nothing to do by default.
}
};
}

View File

@ -1,55 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.transaction.synchronization.spi;
import java.io.Serializable;
import javax.transaction.SystemException;
/**
* A pluggable strategy for defining how the {@link javax.transaction.Synchronization} registered by Hibernate handles
* exceptions.
*
* @author Steve Ebersole
*/
public interface ExceptionMapper extends Serializable {
/**
* Map a JTA {@link javax.transaction.SystemException} to the appropriate runtime-based exception.
*
* @param message The message to use for the returned exception
* @param systemException The causal exception
*
* @return The appropriate exception to throw
*/
public RuntimeException mapStatusCheckFailure(String message, SystemException systemException);
/**
* Map an exception encountered during a managed flush to the appropriate runtime-based exception.
*
* @param message The message to use for the returned exception
* @param failure The causal exception
*
* @return The appropriate exception to throw
*/
public RuntimeException mapManagedFlushFailure(String message, RuntimeException failure);
}

View File

@ -342,7 +342,7 @@ public abstract class AbstractFlushingEventListener implements Serializable {
// lazy collections during their processing.
// For more information, see HHH-2763
try {
session.getTransactionCoordinator().getJdbcCoordinator().flushBeginning();
session.getJdbcCoordinator().flushBeginning();
session.getPersistenceContext().setFlushing( true );
// we need to lock the collection caches before executing entity inserts/updates in order to
// account for bi-directional associations
@ -351,7 +351,7 @@ public abstract class AbstractFlushingEventListener implements Serializable {
}
finally {
session.getPersistenceContext().setFlushing( false );
session.getTransactionCoordinator().getJdbcCoordinator().flushEnding();
session.getJdbcCoordinator().flushEnding();
}
}

View File

@ -243,7 +243,7 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
Serializable id = key == null ? null : key.getIdentifier();
boolean inTxn = source.getTransactionCoordinator().isTransactionInProgress();
boolean inTxn = source.isTransactionInProgress();
boolean shouldDelayIdentityInserts = !inTxn && !requiresImmediateIdAccess;
// Put a placeholder in entries, so we don't recurse back and try to save() the

View File

@ -93,7 +93,7 @@ public class BasicExecutor implements StatementExecutor {
try {
try {
st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
Iterator paramSpecItr = parameterSpecifications.iterator();
int pos = 1;
while ( paramSpecItr.hasNext() ) {
@ -106,11 +106,12 @@ public class BasicExecutor implements StatementExecutor {
}
}
return session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
return session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
}
finally {
if ( st != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}

View File

@ -130,17 +130,18 @@ public class TableBasedDeleteHandlerImpl
int resultCount = 0;
try {
try {
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( idInsertSelect, false );
ps = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( idInsertSelect, false );
int pos = 1;
pos += handlePrependedParametersOnIdSelection( ps, session, pos );
for ( ParameterSpecification parameterSpecification : idSelectParameterSpecifications ) {
pos += parameterSpecification.bind( ps, queryParameters, session, pos );
}
resultCount = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
resultCount = session.getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
}
finally {
if ( ps != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}
@ -152,16 +153,17 @@ public class TableBasedDeleteHandlerImpl
for ( String delete : deletes ) {
try {
try {
ps = session.getTransactionCoordinator()
ps = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( delete, false );
handleAddedParametersOnDelete( ps, session );
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
}
finally {
if ( ps != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}

View File

@ -130,17 +130,18 @@ public class TableBasedUpdateHandlerImpl
int resultCount = 0;
try {
try {
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( idInsertSelect, false );
ps = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( idInsertSelect, false );
int sum = 1;
sum += handlePrependedParametersOnIdSelection( ps, session, sum );
for ( ParameterSpecification parameterSpecification : idSelectParameterSpecifications ) {
sum += parameterSpecification.bind( ps, queryParameters, session, sum );
}
resultCount = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
resultCount = session.getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
}
finally {
if ( ps != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}
@ -155,7 +156,7 @@ public class TableBasedUpdateHandlerImpl
}
try {
try {
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( updates[i], false );
ps = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( updates[i], false );
if ( assignmentParameterSpecifications[i] != null ) {
int position = 1; // jdbc params are 1-based
for ( int x = 0; x < assignmentParameterSpecifications[i].length; x++ ) {
@ -163,11 +164,12 @@ public class TableBasedUpdateHandlerImpl
}
handleAddedParametersOnUpdate( ps, session, position );
}
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
}
finally {
if ( ps != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}

View File

@ -61,20 +61,16 @@ public class Helper {
TemporaryTableCreationWork work = new TemporaryTableCreationWork( idTableInfo, session.getFactory() );
if ( ddlTransactionHandling == TempTableDdlTransactionHandling.NONE ) {
final Connection connection = session.getTransactionCoordinator()
.getJdbcCoordinator()
final Connection connection = session.getJdbcCoordinator()
.getLogicalConnection()
.getConnection();
.getPhysicalConnection();
work.execute( connection );
session.getTransactionCoordinator()
.getJdbcCoordinator()
.afterStatementExecution();
session.getJdbcCoordinator().afterStatementExecution();
}
else {
session.getTransactionCoordinator()
.getTransaction()
.createIsolationDelegate()
.delegateWork( work, ddlTransactionHandling == TempTableDdlTransactionHandling.ISOLATE_AND_TRANSACT );
}
@ -143,20 +139,16 @@ public class Helper {
if ( afterUseAction == AfterUseAction.DROP ) {
TemporaryTableDropWork work = new TemporaryTableDropWork( idTableInfo, session.getFactory() );
if ( ddlTransactionHandling == TempTableDdlTransactionHandling.NONE ) {
final Connection connection = session.getTransactionCoordinator()
.getJdbcCoordinator()
final Connection connection = session.getJdbcCoordinator()
.getLogicalConnection()
.getConnection();
.getPhysicalConnection();
work.execute( connection );
session.getTransactionCoordinator()
.getJdbcCoordinator()
.afterStatementExecution();
session.getJdbcCoordinator().afterStatementExecution();
}
else {
session.getTransactionCoordinator()
.getTransaction()
.createIsolationDelegate()
.delegateWork( work, ddlTransactionHandling == TempTableDdlTransactionHandling.ISOLATE_AND_TRANSACT );
}
@ -166,8 +158,8 @@ public class Helper {
PreparedStatement ps = null;
try {
final String sql = "delete from " + idTableInfo.getQualifiedIdTableName();
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
ps = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
}
catch( Throwable t ) {
log.unableToCleanupTemporaryIdTable(t);
@ -175,7 +167,7 @@ public class Helper {
finally {
if ( ps != null ) {
try {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
}
catch( Throwable ignore ) {
// ignore

View File

@ -53,9 +53,9 @@ public class GUIDGenerator implements IdentifierGenerator {
public Serializable generate(SessionImplementor session, Object obj) throws HibernateException {
final String sql = session.getFactory().getDialect().getSelectGUIDString();
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
final String result;
try {
if ( !rs.next() ) {
@ -64,13 +64,14 @@ public class GUIDGenerator implements IdentifierGenerator {
result = rs.getString(1);
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
LOG.guidGenerated(result);
return result;
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch (SQLException sqle) {

View File

@ -86,14 +86,14 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
}
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
return session.getTransactionCoordinator()
return session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( insertSQL, PreparedStatement.RETURN_GENERATED_KEYS );
}
public Serializable executeAndExtract(PreparedStatement insert, SessionImplementor session) throws SQLException {
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
ResultSet rs = null;
try {
rs = insert.getGeneratedKeys();
@ -105,7 +105,7 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
}
finally {
if ( rs != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, insert );
session.getJdbcCoordinator().getResourceRegistry().release( rs, insert );
}
}
}
@ -134,14 +134,14 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
}
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
return session.getTransactionCoordinator()
return session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( insertSQL, PreparedStatement.NO_GENERATED_KEYS );
}
public Serializable executeAndExtract(PreparedStatement insert, SessionImplementor session) throws SQLException {
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().execute( insert );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().execute( insert );
try {
return IdentifierGeneratorHelper.getGeneratedIdentity(
rs,
@ -150,7 +150,7 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
);
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, insert );
session.getJdbcCoordinator().getResourceRegistry().release( rs, insert );
}
}

View File

@ -124,9 +124,9 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
LOG.debugf( "Fetching initial value: %s", sql );
}
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if (rs.next()) previousValueHolder.initialize(rs, 0L).increment();
else previousValueHolder.initialize(1L);
@ -136,11 +136,12 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch (SQLException sqle) {

View File

@ -192,7 +192,7 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
//keep the behavior consistent even for boundary usages
IntegralDataTypeHolder value = null;
while ( value == null || value.lt( 1 ) ) {
value = session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork( work, true );
value = session.getTransactionCoordinator().createIsolationDelegate().delegateWork( work, true );
}
return value.makeValue();
}
@ -200,7 +200,7 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
return hiloOptimizer.generate(
new AccessCallback() {
public IntegralDataTypeHolder getNextValue() {
return session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork(
return session.getTransactionCoordinator().createIsolationDelegate().delegateWork(
work,
true
);

View File

@ -119,9 +119,9 @@ public class SequenceGenerator
protected IntegralDataTypeHolder generateHolder(SessionImplementor session) {
try {
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
rs.next();
IntegralDataTypeHolder result = buildHolder();
@ -130,11 +130,12 @@ public class SequenceGenerator
return result;
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}

View File

@ -108,12 +108,12 @@ public class SequenceIdentityGenerator
@Override
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
return session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( insertSQL, keyColumns );
return session.getJdbcCoordinator().getStatementPreparer().prepareStatement( insertSQL, keyColumns );
}
@Override
protected Serializable executeAndExtract(PreparedStatement insert, SessionImplementor session) throws SQLException {
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
return IdentifierGeneratorHelper.getGeneratedIdentity(
insert.getGeneratedKeys(),
getPersister().getRootTableKeyColumnNames()[0],

View File

@ -105,9 +105,9 @@ public class SequenceStructure implements DatabaseStructure {
public IntegralDataTypeHolder getNextValue() {
accessCounter++;
try {
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
final ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
final ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
rs.next();
final IntegralDataTypeHolder value = IdentifierGeneratorHelper.getIntegralDataTypeHolder( numberType );
@ -119,7 +119,7 @@ public class SequenceStructure implements DatabaseStructure {
}
finally {
try {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
catch( Throwable ignore ) {
// intentionally empty
@ -127,7 +127,8 @@ public class SequenceStructure implements DatabaseStructure {
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}

View File

@ -543,7 +543,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
new AccessCallback() {
@Override
public IntegralDataTypeHolder getNextValue() {
return session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork(
return session.getTransactionCoordinator().createIsolationDelegate().delegateWork(
new AbstractReturningWork<IntegralDataTypeHolder>() {
@Override
public IntegralDataTypeHolder execute(Connection connection) throws SQLException {

View File

@ -148,7 +148,7 @@ public class TableStructure implements DatabaseStructure {
return new AccessCallback() {
@Override
public IntegralDataTypeHolder getNextValue() {
return session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork(
return session.getTransactionCoordinator().createIsolationDelegate().delegateWork(
new AbstractReturningWork<IntegralDataTypeHolder>() {
@Override
public IntegralDataTypeHolder execute(Connection connection) throws SQLException {

View File

@ -79,6 +79,7 @@ public abstract class AbstractReturningDelegate implements InsertGeneratedIdenti
protected abstract Serializable executeAndExtract(PreparedStatement insert, SessionImplementor session) throws SQLException;
protected void releaseStatement(PreparedStatement insert, SessionImplementor session) throws SQLException {
session.getTransactionCoordinator().getJdbcCoordinator().release( insert );
session.getJdbcCoordinator().getResourceRegistry().release( insert );
session.getJdbcCoordinator().afterStatementExecution();
}
}

View File

@ -52,16 +52,17 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
Binder binder) {
try {
// prepare and execute the insert
PreparedStatement insert = session.getTransactionCoordinator()
PreparedStatement insert = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( insertSQL, PreparedStatement.NO_GENERATED_KEYS );
try {
binder.bindValues( insert );
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( insert );
session.getJdbcCoordinator().getResourceRegistry().release( insert );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException sqle ) {
@ -76,22 +77,23 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
try {
//fetch the generated id in a separate query
PreparedStatement idSelect = session.getTransactionCoordinator()
PreparedStatement idSelect = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( selectSQL, false );
try {
bindParameters( session, idSelect, binder.getEntity() );
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( idSelect );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( idSelect );
try {
return getResult( session, rs, binder.getEntity() );
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, idSelect );
session.getJdbcCoordinator().getResourceRegistry().release( rs, idSelect );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( idSelect );
session.getJdbcCoordinator().getResourceRegistry().release( idSelect );
session.getJdbcCoordinator().afterStatementExecution();
}
}

View File

@ -118,7 +118,8 @@ public abstract class AbstractScrollableResults implements ScrollableResults {
public final void close() {
// not absolutely necessary, but does help with aggressive release
//session.getJDBCContext().getConnectionManager().closeQueryStatement( ps, resultSet );
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
try {
session.getPersistenceContext().getLoadContexts().cleanup( resultSet );
}

View File

@ -26,9 +26,11 @@ package org.hibernate.internal;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.MultiTenancyStrategy;
@ -38,11 +40,14 @@ import org.hibernate.ScrollableResults;
import org.hibernate.SessionEventListener;
import org.hibernate.SessionException;
import org.hibernate.SharedSessionContract;
import org.hibernate.Transaction;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.cfg.Settings;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.query.spi.NativeSQLQueryPlan;
import org.hibernate.engine.query.spi.ParameterMetadata;
@ -53,8 +58,7 @@ import org.hibernate.engine.spi.NamedSQLQueryDefinition;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.transaction.spi.TransactionContext;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.engine.transaction.internal.TransactionImpl;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.jdbc.WorkExecutor;
import org.hibernate.jdbc.WorkExecutorVisitable;
@ -62,6 +66,14 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.ProcedureCallMemento;
import org.hibernate.procedure.internal.ProcedureCallImpl;
import org.hibernate.resource.jdbc.spi.JdbcObserver;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.jdbc.spi.JdbcSessionOwner;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.resource.transaction.TransactionCoordinatorBuilder;
import org.hibernate.resource.transaction.TransactionCoordinatorJtaBuilder;
import org.hibernate.resource.transaction.spi.TransactionStatus;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type;
/**
@ -70,11 +82,13 @@ import org.hibernate.type.Type;
* @author Gavin King
*/
public abstract class AbstractSessionImpl
implements Serializable, SharedSessionContract, SessionImplementor, TransactionContext {
implements Serializable, SharedSessionContract, SessionImplementor, JdbcSessionOwner {
protected transient SessionFactoryImpl factory;
private final String tenantIdentifier;
private boolean closed;
protected transient Transaction currentHibernateTransaction;
protected AbstractSessionImpl(SessionFactoryImpl factory, String tenantIdentifier) {
this.factory = factory;
this.tenantIdentifier = tenantIdentifier;
@ -94,14 +108,11 @@ public abstract class AbstractSessionImpl
return factory;
}
@Override
public TransactionEnvironment getTransactionEnvironment() {
return factory.getTransactionEnvironment();
}
public abstract boolean shouldAutoJoinTransaction();
@Override
public <T> T execute(final LobCreationContext.Callback<T> callback) {
return getTransactionCoordinator().getJdbcCoordinator().coordinateWork(
return getJdbcCoordinator().coordinateWork(
new WorkExecutorVisitable<T>() {
@Override
public T accept(WorkExecutor<T> workExecutor, Connection connection) throws SQLException {
@ -153,7 +164,9 @@ public abstract class AbstractSessionImpl
@Override
public SQLQuery createSQLQuery(NamedSQLQueryDefinition namedQueryDefinition) {
final ParameterMetadata parameterMetadata = factory.getQueryPlanCache().getSQLParameterMetadata( namedQueryDefinition.getQueryString() );
final ParameterMetadata parameterMetadata = factory.getQueryPlanCache().getSQLParameterMetadata(
namedQueryDefinition.getQueryString()
);
final SQLQuery query = new SQLQueryImpl(
namedQueryDefinition,
this,
@ -305,6 +318,16 @@ public abstract class AbstractSessionImpl
return factory.getQueryPlanCache().getNativeSQLQueryPlan( spec );
}
@Override
public Transaction getTransaction() throws HibernateException {
errorIfClosed();
if ( this.currentHibernateTransaction == null || this.currentHibernateTransaction.getStatus() != TransactionStatus.ACTIVE ) {
this.currentHibernateTransaction = new TransactionImpl( getTransactionCoordinator() );
}
getTransactionCoordinator().pulse();
return currentHibernateTransaction;
}
@Override
public List list(NativeSQLQuerySpecification spec, QueryParameters queryParameters)
throws HibernateException {
@ -447,4 +470,153 @@ public abstract class AbstractSessionImpl
return connectionProvider.supportsAggressiveRelease();
}
}
public class JdbcSessionContextImpl implements JdbcSessionContext {
private final SessionFactoryImpl sessionFactory;
private final StatementInspector inspector;
private final transient ServiceRegistry serviceRegistry;
private final transient JdbcObserver jdbcObserver;
public JdbcSessionContextImpl(SessionFactoryImpl sessionFactory, StatementInspector inspector) {
this.sessionFactory = sessionFactory;
this.inspector = inspector;
this.serviceRegistry = sessionFactory.getServiceRegistry();
this.jdbcObserver = new JdbcObserverImpl();
}
@Override
public boolean isScrollableResultSetsEnabled() {
return settings().isScrollableResultSetsEnabled();
}
@Override
public boolean isGetGeneratedKeysEnabled() {
return settings().isGetGeneratedKeysEnabled();
}
@Override
public int getFetchSize() {
return settings().getJdbcFetchSize();
}
@Override
public ConnectionReleaseMode getConnectionReleaseMode() {
return settings().getConnectionReleaseMode();
}
@Override
public ConnectionAcquisitionMode getConnectionAcquisitionMode() {
return null;
}
@Override
public StatementInspector getStatementInspector() {
return inspector;
}
@Override
public JdbcObserver getObserver() {
return this.jdbcObserver;
}
@Override
public SessionFactoryImplementor getSessionFactory() {
return this.sessionFactory;
}
@Override
public ServiceRegistry getServiceRegistry() {
return this.serviceRegistry;
}
private final Settings settings() {
return this.sessionFactory.getSettings();
}
}
public class JdbcObserverImpl implements JdbcObserver {
private final transient List<ConnectionObserver> observers;
public JdbcObserverImpl() {
this.observers = new ArrayList<ConnectionObserver>();
this.observers.add( new ConnectionObserverStatsBridge( factory ) );
}
@Override
public void jdbcConnectionAcquisitionStart() {
}
@Override
public void jdbcConnectionAcquisitionEnd(Connection connection) {
for ( ConnectionObserver observer : observers ) {
observer.physicalConnectionObtained( connection );
}
}
@Override
public void jdbcConnectionReleaseStart() {
}
@Override
public void jdbcConnectionReleaseEnd() {
for ( ConnectionObserver observer : observers ) {
observer.physicalConnectionReleased();
}
}
@Override
public void jdbcPrepareStatementStart() {
getEventListenerManager().jdbcPrepareStatementStart();
}
@Override
public void jdbcPrepareStatementEnd() {
for ( ConnectionObserver observer : observers ) {
observer.statementPrepared();
}
getEventListenerManager().jdbcPrepareStatementEnd();
}
@Override
public void jdbcExecuteStatementStart() {
getEventListenerManager().jdbcExecuteStatementStart();
}
@Override
public void jdbcExecuteStatementEnd() {
getEventListenerManager().jdbcExecuteStatementEnd();
}
@Override
public void jdbcExecuteBatchStart() {
getEventListenerManager().jdbcExecuteBatchStart();
}
@Override
public void jdbcExecuteBatchEnd() {
getEventListenerManager().jdbcExecuteBatchEnd();
}
}
@Override
public TransactionCoordinatorBuilder getTransactionCoordinatorBuilder() {
TransactionCoordinatorBuilder transactionCoordinatorBuilder = factory.getServiceRegistry()
.getService( TransactionCoordinatorBuilder.class );
if ( transactionCoordinatorBuilder instanceof TransactionCoordinatorJtaBuilder ) {
((TransactionCoordinatorJtaBuilder) transactionCoordinatorBuilder).setJtaPlatform(
factory.getSettings()
.getJtaPlatform()
).setAutoJoinTransactions( shouldAutoJoinTransaction() ).setPerformJtaThreadTracking(
factory.getSettings()
.isJtaTrackByThread()
).setPreferUserTransactions( factory.getSettings().isPreferUserTransaction() );
}
return transactionCoordinatorBuilder;
}
}

View File

@ -85,7 +85,8 @@ public final class IteratorImpl implements HibernateIterator {
public void close() throws JDBCException {
if (ps!=null) {
LOG.debug("Closing iterator");
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
ps = null;
rs = null;
hasNext = false;

View File

@ -23,6 +23,8 @@
*/
package org.hibernate.internal;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
@ -41,8 +43,8 @@ import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import org.jboss.logging.Logger;
import org.hibernate.AssertionFailure;
import org.hibernate.Cache;
@ -61,6 +63,7 @@ import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.StatelessSession;
import org.hibernate.StatelessSessionBuilder;
import org.hibernate.Transaction;
import org.hibernate.TypeHelper;
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
import org.hibernate.boot.cfgxml.spi.LoadedConfig;
@ -94,6 +97,7 @@ import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jndi.spi.JndiService;
@ -110,10 +114,7 @@ import org.hibernate.engine.spi.NamedSQLQueryDefinition;
import org.hibernate.engine.spi.SessionBuilderImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionOwner;
import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.engine.transaction.spi.TransactionFactory;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
@ -136,6 +137,7 @@ import org.hibernate.persister.entity.Queryable;
import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.persister.spi.PersisterFactory;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.resource.transaction.TransactionCoordinator;
import org.hibernate.secure.spi.GrantedPermission;
import org.hibernate.secure.spi.JaccPermissionDeclarations;
import org.hibernate.secure.spi.JaccService;
@ -153,8 +155,6 @@ import org.hibernate.type.AssociationType;
import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;
import org.jboss.logging.Logger;
/**
* Concrete implementation of the <tt>SessionFactory</tt> interface. Has the following
@ -182,7 +182,10 @@ import org.jboss.logging.Logger;
public final class SessionFactoryImpl
implements SessionFactoryImplementor {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, SessionFactoryImpl.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
SessionFactoryImpl.class.getName()
);
private static final IdentifierGenerator UUID_GENERATOR = UUIDGenerator.buildSessionFactoryUniqueIdentifierGenerator();
private final String name;
@ -213,7 +216,6 @@ public final class SessionFactoryImpl
private transient boolean isClosed;
private final transient TypeResolver typeResolver;
private final transient TypeHelper typeHelper;
private final transient TransactionEnvironment transactionEnvironment;
private final transient SessionFactoryOptions sessionFactoryOptions;
public SessionFactoryImpl(final MetadataImplementor metadata, SessionFactoryOptions options) {
@ -515,7 +517,6 @@ public final class SessionFactoryImpl
fetchProfiles.put( fetchProfile.getName(), fetchProfile );
}
this.transactionEnvironment = new TransactionEnvironmentImpl( this );
this.observer.sessionFactoryCreated( this );
SessionFactoryRegistry.INSTANCE.addSessionFactory(
@ -690,10 +691,6 @@ public final class SessionFactoryImpl
this.observer.addObserver( observer );
}
public TransactionEnvironment getTransactionEnvironment() {
return transactionEnvironment;
}
public Properties getProperties() {
return properties;
}
@ -1123,10 +1120,6 @@ public final class SessionFactoryImpl
return identifierGenerators.get(rootEntityName);
}
private TransactionFactory transactionFactory() {
return serviceRegistry.getService( TransactionFactory.class );
}
private boolean canAccessTransactionManager() {
try {
return serviceRegistry.getService( JtaPlatform.class ).retrieveTransactionManager() != null;
@ -1149,9 +1142,9 @@ public final class SessionFactoryImpl
}
if ( "jta".equals( impl ) ) {
if ( ! transactionFactory().compatibleWithJtaSynchronization() ) {
LOG.autoFlushWillNotWork();
}
// if ( ! transactionFactory().compatibleWithJtaSynchronization() ) {
// LOG.autoFlushWillNotWork();
// }
return new JTASessionContext( this );
}
else if ( "thread".equals( impl ) ) {
@ -1228,7 +1221,15 @@ public final class SessionFactoryImpl
listeners = settings.getBaselineSessionEventsListenerBuilder().buildBaselineList();
}
protected TransactionCoordinatorImpl getTransactionCoordinator() {
protected TransactionCoordinator getTransactionCoordinator() {
return null;
}
protected JdbcCoordinatorImpl getJdbcCoordinator() {
return null;
}
protected Transaction getTransaction() {
return null;
}
@ -1244,6 +1245,8 @@ public final class SessionFactoryImpl
sessionFactory,
sessionOwner,
getTransactionCoordinator(),
getJdbcCoordinator(),
getTransaction(),
getTransactionCompletionProcesses(),
autoJoinTransactions,
sessionFactory.settings.getRegionFactory().nextTimestamp(),

View File

@ -23,6 +23,8 @@
*/
package org.hibernate.internal;
import javax.persistence.EntityNotFoundException;
import javax.transaction.SystemException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
@ -42,7 +44,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityNotFoundException;
import org.jboss.logging.Logger;
import org.hibernate.AssertionFailure;
import org.hibernate.CacheMode;
@ -85,6 +88,8 @@ import org.hibernate.engine.internal.SessionEventListenerManagerImpl;
import org.hibernate.engine.internal.StatefulPersistenceContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.query.spi.FilterQueryPlan;
import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.query.spi.NativeSQLQueryPlan;
@ -99,9 +104,7 @@ import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionOwner;
import org.hibernate.engine.spi.Status;
import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.engine.transaction.spi.TransactionImplementor;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.engine.transaction.spi.TransactionObserver;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
@ -154,12 +157,15 @@ import org.hibernate.pretty.MessageHelper;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.resource.transaction.TransactionCoordinator;
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl;
import org.hibernate.resource.transaction.spi.TransactionStatus;
import org.hibernate.stat.SessionStatistics;
import org.hibernate.stat.internal.SessionStatisticsImpl;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/**
* Concrete implementation of a Session.
*
@ -180,9 +186,12 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
// a separate class responsible for generating/dispatching events just duplicates most of the Session methods...
// passing around separate interceptor, factory, actionQueue, and persistentContext is not manageable...
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, SessionImpl.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
SessionImpl.class.getName()
);
private static final boolean TRACE_ENABLED = LOG.isTraceEnabled();
private static final boolean TRACE_ENABLED = LOG.isTraceEnabled();
private transient long timestamp;
@ -190,7 +199,8 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
private transient ActionQueue actionQueue;
private transient StatefulPersistenceContext persistenceContext;
private transient TransactionCoordinatorImpl transactionCoordinator;
private transient TransactionCoordinator transactionCoordinator;
private transient JdbcCoordinatorImpl jdbcCoordinator;
private transient Interceptor interceptor;
private transient EntityNameResolver entityNameResolver = new CoordinatingEntityNameResolver();
@ -212,6 +222,8 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
private SessionEventListenerManagerImpl sessionEventsManager = new SessionEventListenerManagerImpl();
private transient JdbcSessionContext jdbcSessionContext;
/**
* Constructor used for openSession(...) processing, as well as construction
* of sessions for getCurrentSession().
@ -232,7 +244,9 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
final Connection connection,
final SessionFactoryImpl factory,
final SessionOwner sessionOwner,
final TransactionCoordinatorImpl transactionCoordinator,
final TransactionCoordinator transactionCoordinator,
final JdbcCoordinatorImpl jdbcCoordinator,
final Transaction transaction,
final ActionQueue.TransactionCompletionProcesses transactionCompletionProcesses,
final boolean autoJoinTransactions,
final long timestamp,
@ -250,22 +264,24 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
this.autoCloseSessionEnabled = autoCloseSessionEnabled;
this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;
this.jdbcSessionContext = new JdbcSessionContextImpl( factory, getStatementInspector() );
if ( transactionCoordinator == null ) {
this.isTransactionCoordinatorShared = false;
this.connectionReleaseMode = connectionReleaseMode;
this.autoJoinTransactions = autoJoinTransactions;
this.transactionCoordinator = new TransactionCoordinatorImpl( connection, this );
this.transactionCoordinator.getJdbcCoordinator().getLogicalConnection().addObserver(
new ConnectionObserverStatsBridge( factory )
);
this.jdbcCoordinator = new JdbcCoordinatorImpl( connection, this );
this.transactionCoordinator = getTransactionCoordinatorBuilder().buildTransactionCoordinator( this.jdbcCoordinator );
this.currentHibernateTransaction = getTransaction();
}
else {
if ( connection != null ) {
throw new SessionException( "Cannot simultaneously share transaction context and specify connection" );
}
this.transactionCoordinator = transactionCoordinator;
this.jdbcCoordinator = jdbcCoordinator;
this.currentHibernateTransaction = transaction;
this.isTransactionCoordinatorShared = true;
this.autoJoinTransactions = false;
if ( transactionCompletionProcesses != null ) {
@ -277,36 +293,39 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
"with sharing JDBC connection between sessions; ignoring"
);
}
if ( connectionReleaseMode != transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnectionReleaseMode() ) {
if ( connectionReleaseMode != this.jdbcCoordinator.getConnectionReleaseMode() ) {
LOG.debug(
"Session creation specified 'connectionReleaseMode', which is invalid in conjunction " +
"Session creation specified 'getConnectionReleaseMode', which is invalid in conjunction " +
"with sharing JDBC connection between sessions; ignoring"
);
}
this.connectionReleaseMode = transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnectionReleaseMode();
this.connectionReleaseMode = this.jdbcCoordinator.getConnectionReleaseMode();
// add a transaction observer so that we can handle delegating managed actions back to THIS session
// versus the session that created (and therefore "owns") the transaction coordinator
transactionObserver = new TransactionObserver() {
@Override
public void afterBegin(TransactionImplementor transaction) {
public void afterBegin() {
}
@Override
public void beforeCompletion(TransactionImplementor transaction) {
public void beforeCompletion() {
if ( isOpen() && flushBeforeCompletionEnabled ) {
SessionImpl.this.managedFlush();
}
beforeTransactionCompletion( transaction );
actionQueue.beforeTransactionCompletion();
try {
interceptor.beforeTransactionCompletion( currentHibernateTransaction );
}
catch (Throwable t) {
LOG.exceptionInBeforeTransactionCompletionInterceptor( t );
}
}
@Override
public void afterCompletion(boolean successful, TransactionImplementor transaction) {
afterTransactionCompletion( transaction, successful );
public void afterCompletion(boolean successful) {
afterTransactionCompletion( successful );
if ( isOpen() && autoCloseSessionEnabled ) {
managedClose();
}
transactionCoordinator.removeObserver( this );
}
};
@ -315,12 +334,14 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
loadQueryInfluencers = new LoadQueryInfluencers( factory );
if (factory.getStatistics().isStatisticsEnabled()) {
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor().openSession();
}
if ( TRACE_ENABLED )
LOG.tracef( "Opened session at timestamp: %s", timestamp );
if ( TRACE_ENABLED ) {
LOG.tracef( "Opened session at timestamp: %s", timestamp );
}
}
@Override
@ -367,14 +388,13 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
try {
if ( !isTransactionCoordinatorShared ) {
return transactionCoordinator.close();
return jdbcCoordinator.close();
}
else {
if ( getActionQueue().hasBeforeTransactionActions() || getActionQueue().hasAfterTransactionActions() ) {
LOG.warn( "On close, shared Session had before / after transaction actions that have not yet been processed" );
}
else {
transactionCoordinator.removeObserver( transactionObserver );
LOG.warn(
"On close, shared Session had before / after transaction actions that have not yet been processed"
);
}
return null;
}
@ -386,8 +406,8 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
}
@Override
public ConnectionReleaseMode getConnectionReleaseMode() {
return connectionReleaseMode;
public boolean isAutoCloseSessionEnabled() {
return autoCloseSessionEnabled;
}
@Override
@ -395,29 +415,17 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
return autoJoinTransactions;
}
@Override
public boolean isAutoCloseSessionEnabled() {
return autoCloseSessionEnabled;
}
@Override
public boolean isOpen() {
checkTransactionSynchStatus();
return !isClosed();
}
@Override
public boolean isFlushModeNever() {
private boolean isFlushModeNever() {
return FlushMode.isManualFlushMode( getFlushMode() );
}
@Override
public boolean isFlushBeforeCompletionEnabled() {
return flushBeforeCompletionEnabled;
}
@Override
public void managedFlush() {
private void managedFlush() {
if ( isClosed() ) {
LOG.trace( "Skipping auto-flush due to session closed" );
return;
@ -439,8 +447,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
}
}
@Override
public void managedClose() {
private void managedClose() {
LOG.trace( "Automatically closing session" );
close();
}
@ -448,27 +455,27 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
@Override
public Connection connection() throws HibernateException {
errorIfClosed();
return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnection();
return this.jdbcCoordinator.getLogicalConnection().getPhysicalConnection();
}
@Override
public boolean isConnected() {
checkTransactionSynchStatus();
return !isClosed() && transactionCoordinator.getJdbcCoordinator().getLogicalConnection().isOpen();
return !isClosed() && this.jdbcCoordinator.getLogicalConnection().isOpen();
}
@Override
public boolean isTransactionInProgress() {
checkTransactionSynchStatus();
return !isClosed() && transactionCoordinator.isTransactionInProgress();
return !isClosed() && transactionCoordinator.getTransactionDriverControl()
.getStatus() == TransactionStatus.ACTIVE && transactionCoordinator.isJoined();
}
@Override
public Connection disconnect() throws HibernateException {
errorIfClosed();
LOG.debug( "Disconnecting session" );
transactionCoordinator.getJdbcCoordinator().releaseResources();
return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().manualDisconnect();
return this.jdbcCoordinator.getLogicalConnection().manualDisconnect();
}
@Override
@ -476,7 +483,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
errorIfClosed();
LOG.debug( "Reconnecting session" );
checkTransactionSynchStatus();
transactionCoordinator.getJdbcCoordinator().getLogicalConnection().manualReconnect( conn );
this.jdbcCoordinator.getLogicalConnection().manualReconnect( conn );
}
@Override
@ -500,64 +507,11 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
* @param success Was the operation a success
*/
public void afterOperation(boolean success) {
if ( ! transactionCoordinator.isTransactionInProgress() ) {
transactionCoordinator.afterNonTransactionalQuery( success );
if ( ! isTransactionInProgress() ) {
jdbcCoordinator.afterTransaction();
}
}
@Override
public void afterTransactionBegin(TransactionImplementor hibernateTransaction) {
errorIfClosed();
interceptor.afterTransactionBegin( hibernateTransaction );
}
@Override
public void beforeTransactionCompletion(TransactionImplementor hibernateTransaction) {
LOG.trace( "before transaction completion" );
actionQueue.beforeTransactionCompletion();
try {
interceptor.beforeTransactionCompletion( hibernateTransaction );
}
catch (Throwable t) {
LOG.exceptionInBeforeTransactionCompletionInterceptor( t );
}
}
@Override
public void afterTransactionCompletion(TransactionImplementor hibernateTransaction, boolean successful) {
LOG.trace( "after transaction completion" );
persistenceContext.afterTransactionCompletion();
actionQueue.afterTransactionCompletion( successful );
getEventListenerManager().transactionCompletion( successful );
try {
interceptor.afterTransactionCompletion( hibernateTransaction );
}
catch (Throwable t) {
LOG.exceptionInAfterTransactionCompletionInterceptor( t );
}
if ( autoClear ) {
internalClear();
}
}
@Override
public String onPrepareStatement(String sql) {
errorIfClosed();
if ( StringHelper.isEmpty( sql ) ) {
throw new AssertionFailure( "SQL to prepare was null." );
}
sql = interceptor.onPrepareStatement( sql );
if ( StringHelper.isEmpty( sql ) ) {
throw new AssertionFailure( "Interceptor.onPrepareStatement() returned null or empty string." );
}
return sql;
}
@Override
public SessionEventListenerManagerImpl getEventListenerManager() {
return sessionEventsManager;
@ -568,36 +522,6 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
getEventListenerManager().addListener( listeners );
}
@Override
public void startPrepareStatement() {
getEventListenerManager().jdbcPrepareStatementStart();
}
@Override
public void endPrepareStatement() {
getEventListenerManager().jdbcPrepareStatementEnd();
}
@Override
public void startStatementExecution() {
getEventListenerManager().jdbcExecuteStatementStart();
}
@Override
public void endStatementExecution() {
getEventListenerManager().jdbcExecuteStatementEnd();
}
@Override
public void startBatchExecution() {
getEventListenerManager().jdbcExecuteBatchStart();
}
@Override
public void endBatchExecution() {
getEventListenerManager().jdbcExecuteBatchEnd();
}
/**
* clear all the internal collections, just
* to help the garbage collector, does not
@ -667,7 +591,9 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
}
private void delayedAfterCompletion() {
transactionCoordinator.getSynchronizationCallbackCoordinator().processAnyDelayedAfterCompletion();
if(transactionCoordinator instanceof JtaTransactionCoordinatorImpl) {
((JtaTransactionCoordinatorImpl)transactionCoordinator).getSynchronizationCallbackCoordinator().processAnyDelayedAfterCompletion();
}
}
// saveOrUpdate() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -766,7 +692,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
}
private void fireLock(String entityName, Object object, LockOptions options) {
fireLock( new LockEvent( entityName, object, options, this) );
fireLock( new LockEvent( entityName, object, options, this ) );
}
private void fireLock( Object object, LockOptions options) {
@ -1229,6 +1155,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
return false;
}
AutoFlushEvent event = new AutoFlushEvent( querySpaces, this );
listeners( EventType.AUTO_FLUSH );
for ( AutoFlushEventListener listener : listeners( EventType.AUTO_FLUSH ) ) {
listener.onAutoFlush( event );
}
@ -1329,7 +1256,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
success = true;
}
finally {
afterOperation(success);
afterOperation( success );
delayedAfterCompletion();
}
return result;
@ -1352,7 +1279,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
result = plan.performExecuteUpdate(queryParameters, this);
success = true;
} finally {
afterOperation(success);
afterOperation( success );
delayedAfterCompletion();
}
return result;
@ -1464,12 +1391,6 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
this.cacheMode= cacheMode;
}
@Override
public Transaction getTransaction() throws HibernateException {
errorIfClosed();
return transactionCoordinator.getTransaction();
}
@Override
public Transaction beginTransaction() throws HibernateException {
errorIfClosed();
@ -1995,7 +1916,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
@Override
public void cancelQuery() throws HibernateException {
errorIfClosed();
getTransactionCoordinator().getJdbcCoordinator().cancelLastQuery();
this.jdbcCoordinator.cancelLastQuery();
}
@Override
@ -2098,7 +2019,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
}
private <T> T doWork(WorkExecutorVisitable<T> work) throws HibernateException {
return transactionCoordinator.getJdbcCoordinator().coordinateWork( work );
return this.jdbcCoordinator.coordinateWork( work );
}
@Override
@ -2112,6 +2033,11 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
return transactionCoordinator;
}
@Override
public JdbcCoordinator getJdbcCoordinator() {
return this.jdbcCoordinator;
}
@Override
public LoadQueryInfluencers getLoadQueryInfluencers() {
return loadQueryInfluencers;
@ -2212,26 +2138,29 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
* @throws IOException Indicates a general IO stream exception
* @throws ClassNotFoundException Indicates a class resolution issue
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException, SQLException {
LOG.trace( "Deserializing session" );
ois.defaultReadObject();
entityNameResolver = new CoordinatingEntityNameResolver();
connectionReleaseMode = ConnectionReleaseMode.parse( ( String ) ois.readObject() );
connectionReleaseMode = ConnectionReleaseMode.parse( (String) ois.readObject() );
autoClear = ois.readBoolean();
autoJoinTransactions = ois.readBoolean();
flushMode = FlushMode.valueOf( ( String ) ois.readObject() );
cacheMode = CacheMode.valueOf( ( String ) ois.readObject() );
flushMode = FlushMode.valueOf( (String) ois.readObject() );
cacheMode = CacheMode.valueOf( (String) ois.readObject() );
flushBeforeCompletionEnabled = ois.readBoolean();
autoCloseSessionEnabled = ois.readBoolean();
interceptor = ( Interceptor ) ois.readObject();
interceptor = (Interceptor) ois.readObject();
factory = SessionFactoryImpl.deserialize( ois );
sessionOwner = ( SessionOwner ) ois.readObject();
this.jdbcSessionContext = new JdbcSessionContextImpl( factory, interceptor );
sessionOwner = (SessionOwner) ois.readObject();
transactionCoordinator = TransactionCoordinatorImpl.deserialize( ois, this );
jdbcCoordinator = JdbcCoordinatorImpl.deserialize( ois, this );
this.transactionCoordinator = getTransactionCoordinatorBuilder().buildTransactionCoordinator( jdbcCoordinator );
persistenceContext = StatefulPersistenceContext.deserialize( ois, this );
actionQueue = ActionQueue.deserialize( ois, this );
@ -2253,7 +2182,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
* @throws IOException Indicates a general IO stream exception
*/
private void writeObject(ObjectOutputStream oos) throws IOException {
if ( ! transactionCoordinator.getJdbcCoordinator().isReadyForSerialization() ) {
if ( !jdbcCoordinator.isReadyForSerialization() ) {
throw new IllegalStateException( "Cannot serialize a session while connected" );
}
@ -2274,7 +2203,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
factory.serialize( oos );
oos.writeObject( sessionOwner );
transactionCoordinator.serialize( oos );
jdbcCoordinator.serialize( oos );
persistenceContext.serialize( oos );
actionQueue.serialize( oos );
@ -2298,6 +2227,58 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
private transient LobHelperImpl lobHelper;
@Override
public JdbcSessionContext getJdbcSessionContext() {
return this.jdbcSessionContext;
}
private StatementInspector getStatementInspector() {
return this.interceptor;
}
@Override
public void beforeTransactionCompletion() {
LOG.trace( "before transaction completion" );
flushBeforeTransactionCompletion();
actionQueue.beforeTransactionCompletion();
try {
interceptor.beforeTransactionCompletion( currentHibernateTransaction );
}
catch (Throwable t) {
LOG.exceptionInBeforeTransactionCompletionInterceptor( t );
}
}
@Override
public void afterTransactionCompletion(boolean successful) {
LOG.trace( "after transaction completion" );
persistenceContext.afterTransactionCompletion();
actionQueue.afterTransactionCompletion( successful );
getEventListenerManager().transactionCompletion( successful );
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor().endTransaction( successful );
}
try {
interceptor.afterTransactionCompletion( currentHibernateTransaction );
}
catch (Throwable t) {
LOG.exceptionInAfterTransactionCompletionInterceptor( t );
}
if ( shouldAutoClose() && !isClosed() ) {
managedClose();
}
if ( autoClear ) {
internalClear();
}
}
private static class LobHelperImpl implements LobHelper {
private final SessionImpl session;
@ -2360,10 +2341,20 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
}
@Override
protected TransactionCoordinatorImpl getTransactionCoordinator() {
protected TransactionCoordinator getTransactionCoordinator() {
return shareTransactionContext ? session.transactionCoordinator : super.getTransactionCoordinator();
}
@Override
protected JdbcCoordinatorImpl getJdbcCoordinator() {
return shareTransactionContext ? session.jdbcCoordinator : super.getJdbcCoordinator();
}
@Override
protected Transaction getTransaction() {
return shareTransactionContext ? session.currentHibernateTransaction : super.getTransaction();
}
@Override
protected ActionQueue.TransactionCompletionProcesses getTransactionCompletionProcesses() {
return shareTransactionContext ?
@ -2844,4 +2835,33 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
return null;
}
}
@Override
public void afterTransactionBegin() {
errorIfClosed();
interceptor.afterTransactionBegin( currentHibernateTransaction );
}
@Override
public void flushBeforeTransactionCompletion() {
boolean flush = false;
try {
flush = (!isFlushModeNever() &&
!flushBeforeCompletionEnabled) || (
!isClosed()
&& !isFlushModeNever()
&& flushBeforeCompletionEnabled
&& !JtaStatusHelper.isRollback(
getSessionFactory().getSettings()
.getJtaPlatform()
.getCurrentStatus()
));
}
catch (SystemException se) {
throw new HibernateException( "could not determine transaction status in beforeCompletion()", se );
}
if ( flush ) {
managedFlush();
}
}
}

View File

@ -23,6 +23,7 @@
*/
package org.hibernate.internal;
import javax.transaction.SystemException;
import java.io.Serializable;
import java.sql.Connection;
import java.util.Collections;
@ -30,8 +31,9 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jboss.logging.Logger;
import org.hibernate.CacheMode;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.Criteria;
import org.hibernate.EmptyInterceptor;
import org.hibernate.EntityMode;
@ -51,6 +53,8 @@ import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.SessionEventListenerManagerImpl;
import org.hibernate.engine.internal.StatefulPersistenceContext;
import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.query.spi.NativeSQLQueryPlan;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
@ -59,10 +63,7 @@ import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.engine.transaction.spi.TransactionImplementor;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.loader.criteria.CriteriaLoader;
import org.hibernate.loader.custom.CustomLoader;
@ -71,10 +72,11 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.transaction.TransactionCoordinator;
import org.hibernate.resource.transaction.spi.TransactionStatus;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/**
* @author Gavin King
*/
@ -83,8 +85,11 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, StatelessSessionImpl.class.getName());
private TransactionCoordinator transactionCoordinator;
private transient JdbcCoordinator jdbcCoordinator;
private PersistenceContext temporaryPersistenceContext = new StatefulPersistenceContext( this );
private long timestamp;
private JdbcSessionContext jdbcSessionContext;
StatelessSessionImpl(
Connection connection,
@ -99,20 +104,27 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
SessionFactoryImpl factory,
long timestamp) {
super( factory, tenantIdentifier );
this.transactionCoordinator = new TransactionCoordinatorImpl( connection, this );
this.jdbcSessionContext = new JdbcSessionContextImpl( factory, EmptyInterceptor.INSTANCE );
this.jdbcCoordinator = new JdbcCoordinatorImpl( connection, this );
this.transactionCoordinator = getTransactionCoordinatorBuilder().buildTransactionCoordinator( jdbcCoordinator );
this.currentHibernateTransaction = getTransaction();
this.timestamp = timestamp;
}
// TransactionContext ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public TransactionCoordinator getTransactionCoordinator() {
return transactionCoordinator;
}
@Override
public TransactionEnvironment getTransactionEnvironment() {
return factory.getTransactionEnvironment();
public JdbcCoordinator getJdbcCoordinator() {
return this.jdbcCoordinator;
}
@Override
public boolean shouldAutoJoinTransaction() {
return true;
}
// inserts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -153,16 +165,16 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
@Override
public void delete(Object entity) {
errorIfClosed();
delete(null, entity);
delete( null, entity );
}
@Override
public void delete(String entityName, Object entity) {
errorIfClosed();
EntityPersister persister = getEntityPersister(entityName, entity);
EntityPersister persister = getEntityPersister( entityName, entity );
Serializable id = persister.getIdentifier( entity, this );
Object version = persister.getVersion( entity );
persister.delete(id, version, entity, this);
persister.delete( id, version, entity, this );
}
@ -343,69 +355,32 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
managedClose();
}
@Override
public ConnectionReleaseMode getConnectionReleaseMode() {
return factory.getSettings().getConnectionReleaseMode();
}
@Override
public boolean shouldAutoJoinTransaction() {
return true;
}
@Override
public boolean isAutoCloseSessionEnabled() {
return factory.getSettings().isAutoCloseSessionEnabled();
}
@Override
public boolean isFlushBeforeCompletionEnabled() {
return true;
}
@Override
public boolean isFlushModeNever() {
return false;
}
@Override
public void managedClose() {
if ( isClosed() ) {
throw new SessionException( "Session was already closed!" );
}
transactionCoordinator.close();
setClosed();
}
@Override
public void managedFlush() {
errorIfClosed();
getTransactionCoordinator().getJdbcCoordinator().executeBatch();
}
@Override
public boolean shouldAutoClose() {
return isAutoCloseSessionEnabled() && !isClosed();
}
@Override
public void afterTransactionBegin(TransactionImplementor hibernateTransaction) {
// nothing to do here
private boolean isFlushModeNever() {
return false;
}
@Override
public void beforeTransactionCompletion(TransactionImplementor hibernateTransaction) {
// nothing to do here
private void managedClose() {
if ( isClosed() ) {
throw new SessionException( "Session was already closed!" );
}
jdbcCoordinator.close();
setClosed();
}
@Override
public void afterTransactionCompletion(TransactionImplementor hibernateTransaction, boolean successful) {
// nothing to do here
}
@Override
public String onPrepareStatement(String sql) {
return sql;
private void managedFlush() {
errorIfClosed();
jdbcCoordinator.executeBatch();
}
private SessionEventListenerManagerImpl sessionEventsManager;
@ -418,30 +393,6 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
return sessionEventsManager;
}
@Override
public void startPrepareStatement() {
}
@Override
public void endPrepareStatement() {
}
@Override
public void startStatementExecution() {
}
@Override
public void endStatementExecution() {
}
@Override
public void startBatchExecution() {
}
@Override
public void endBatchExecution() {
}
@Override
public String bestGuessEntityName(Object object) {
if (object instanceof HibernateProxy) {
@ -453,7 +404,7 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
@Override
public Connection connection() {
errorIfClosed();
return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnection();
return jdbcCoordinator.getLogicalConnection().getPhysicalConnection();
}
@Override
@ -556,12 +507,13 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
@Override
public boolean isConnected() {
return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().isPhysicallyConnected();
return jdbcCoordinator.getLogicalConnection().isPhysicallyConnected();
}
@Override
public boolean isTransactionInProgress() {
return transactionCoordinator.isTransactionInProgress();
return !isClosed() && transactionCoordinator.isJoined() && transactionCoordinator.getTransactionDriverControl()
.getStatus() == TransactionStatus.ACTIVE;
}
@Override
@ -584,12 +536,6 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
throw new UnsupportedOperationException();
}
@Override
public Transaction getTransaction() throws HibernateException {
errorIfClosed();
return transactionCoordinator.getTransaction();
}
@Override
public Transaction beginTransaction() throws HibernateException {
errorIfClosed();
@ -636,8 +582,8 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
}
public void afterOperation(boolean success) {
if ( ! transactionCoordinator.isTransactionInProgress() ) {
transactionCoordinator.afterNonTransactionalQuery( success );
if ( ! isTransactionInProgress() ) {
jdbcCoordinator.afterTransaction();
}
}
@ -804,4 +750,48 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
temporaryPersistenceContext.clear();
return result;
}
@Override
public JdbcSessionContext getJdbcSessionContext() {
return this.jdbcSessionContext;
}
@Override
public void afterTransactionBegin() {
}
@Override
public void beforeTransactionCompletion() {
flushBeforeTransactionCompletion();
}
@Override
public void afterTransactionCompletion(boolean successful) {
if ( shouldAutoClose()
&& !isClosed() ) {
managedClose();
}
}
@Override
public void flushBeforeTransactionCompletion() {
boolean flush = false;
try {
flush = (
!isClosed()
&& !isFlushModeNever()
&& !JtaStatusHelper.isRollback(
factory.getSettings()
.getJtaPlatform()
.getCurrentStatus()
));
}
catch (SystemException se) {
throw new HibernateException( "could not determine transaction status in beforeCompletion()", se );
}
if ( flush ) {
managedFlush();
}
}
}

View File

@ -1,82 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.internal;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.engine.transaction.spi.TransactionFactory;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.stat.spi.StatisticsImplementor;
/**
* @author Steve Ebersole
*/
public class TransactionEnvironmentImpl implements TransactionEnvironment {
private final SessionFactoryImpl sessionFactory;
private final transient StatisticsImplementor statisticsImplementor;
private final transient ServiceRegistry serviceRegistry;
private final transient JdbcServices jdbcServices;
private final transient JtaPlatform jtaPlatform;
private final transient TransactionFactory transactionFactory;
public TransactionEnvironmentImpl(SessionFactoryImpl sessionFactory) {
this.sessionFactory = sessionFactory;
this.statisticsImplementor = sessionFactory.getStatisticsImplementor();
this.serviceRegistry = sessionFactory.getServiceRegistry();
this.jdbcServices = serviceRegistry.getService( JdbcServices.class );
this.jtaPlatform = serviceRegistry.getService( JtaPlatform.class );
this.transactionFactory = serviceRegistry.getService( TransactionFactory.class );
}
@Override
public SessionFactoryImplementor getSessionFactory() {
return sessionFactory;
}
protected ServiceRegistry serviceRegistry() {
return serviceRegistry;
}
@Override
public JdbcServices getJdbcServices() {
return jdbcServices;
}
@Override
public JtaPlatform getJtaPlatform() {
return jtaPlatform;
}
@Override
public TransactionFactory getTransactionFactory() {
return transactionFactory;
}
@Override
public StatisticsImplementor getStatisticsImplementor() {
return statisticsImplementor;
}
}

View File

@ -921,7 +921,8 @@ public abstract class Loader {
return processResultSet( rs, queryParameters, session, returnProxies, forcedResultTransformer, maxRows, afterLoadActions );
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
@ -1880,7 +1881,7 @@ public abstract class Loader {
boolean callable = queryParameters.isCallable();
final ScrollMode scrollMode = getScrollMode( scroll, hasFirstRow, useLimitOffset, queryParameters );
PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareQueryStatement(
PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareQueryStatement(
sql,
callable,
scrollMode
@ -1933,11 +1934,13 @@ public abstract class Loader {
LOG.tracev( "Bound [{0}] parameters total", col );
}
catch ( SQLException sqle ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
throw sqle;
}
catch ( HibernateException he ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
throw he;
}
@ -2061,7 +2064,7 @@ public abstract class Loader {
throws SQLException, HibernateException {
try {
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
rs = wrapResultSetIfEnabled( rs , session );
if ( !limitHandler.supportsLimitOffset() || !LimitHelper.useLimit( limitHandler, selection ) ) {
@ -2074,7 +2077,8 @@ public abstract class Loader {
return rs;
}
catch ( SQLException sqle ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
throw sqle;
}
}

View File

@ -261,7 +261,8 @@ public class DynamicBatchingCollectionInitializerBuilder extends BatchingCollect
processResultSet( rs, queryParameters, session, true, null, maxRows, afterLoadActions );
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}

View File

@ -263,7 +263,8 @@ public class DynamicBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuil
return processResultSet( rs, queryParameters, session, false, null, maxRows, afterLoadActions );
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}

View File

@ -153,11 +153,12 @@ public abstract class AbstractLoadPlanBasedLoader {
}
finally {
if ( wrapper != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release(
session.getJdbcCoordinator().getResourceRegistry().release(
wrapper.getResultSet(),
wrapper.getStatement()
);
session.getTransactionCoordinator().getJdbcCoordinator().release( wrapper.getStatement() );
session.getJdbcCoordinator().getResourceRegistry().release( wrapper.getStatement() );
session.getJdbcCoordinator().afterStatementExecution();
}
persistenceContext.afterLoad();
}
@ -252,7 +253,7 @@ public abstract class AbstractLoadPlanBasedLoader {
final boolean callable = queryParameters.isCallable();
final ScrollMode scrollMode = getScrollMode( scroll, hasFirstRow, useLimitOffset, queryParameters );
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator()
final PreparedStatement st = session.getJdbcCoordinator()
.getStatementPreparer().prepareQueryStatement( sql, callable, scrollMode );
try {
@ -303,11 +304,13 @@ public abstract class AbstractLoadPlanBasedLoader {
}
}
catch ( SQLException sqle ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
throw sqle;
}
catch ( HibernateException he ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
throw he;
}
@ -444,7 +447,7 @@ public abstract class AbstractLoadPlanBasedLoader {
throws SQLException, HibernateException {
try {
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
rs = wrapResultSetIfEnabled( rs , session );
if ( !limitHandler.supportsLimitOffset() || !LimitHelper.useLimit( limitHandler, selection ) ) {
@ -457,7 +460,8 @@ public abstract class AbstractLoadPlanBasedLoader {
return rs;
}
catch ( SQLException sqle ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
throw sqle;
}
}

View File

@ -1190,13 +1190,13 @@ public abstract class AbstractCollectionPersister
expectation
);
}
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getBatch( removeBatchKey )
.getBatchStatement( sql, callable );
}
else {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, callable );
@ -1207,24 +1207,25 @@ public abstract class AbstractCollectionPersister
writeKey( st, id, offset, session );
if ( useBatch ) {
session.getTransactionCoordinator()
session
.getJdbcCoordinator()
.getBatch( removeBatchKey )
.addToBatch();
}
else {
expectation.verifyOutcome( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
}
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
@ -1290,13 +1291,13 @@ public abstract class AbstractCollectionPersister
expectation
);
}
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getBatch( recreateBatchKey )
.getBatchStatement( sql, callable );
}
else {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, callable );
@ -1316,13 +1317,13 @@ public abstract class AbstractCollectionPersister
loc = writeElement( st, collection.getElement( entry ), loc, session );
if ( useBatch ) {
session.getTransactionCoordinator()
session
.getJdbcCoordinator()
.getBatch( recreateBatchKey )
.addToBatch();
}
else {
expectation.verifyOutcome( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
}
collection.afterRowInsert( this, entry, i );
@ -1330,13 +1331,14 @@ public abstract class AbstractCollectionPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
@ -1407,13 +1409,13 @@ public abstract class AbstractCollectionPersister
expectation
);
}
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getBatch( deleteBatchKey )
.getBatchStatement( sql, callable );
}
else {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, callable );
@ -1438,25 +1440,26 @@ public abstract class AbstractCollectionPersister
}
if ( useBatch ) {
session.getTransactionCoordinator()
session
.getJdbcCoordinator()
.getBatch( deleteBatchKey )
.addToBatch();
}
else {
expectation.verifyOutcome( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
}
count++;
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
@ -1526,14 +1529,14 @@ public abstract class AbstractCollectionPersister
);
}
if ( st == null ) {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getBatch( insertBatchKey )
.getBatchStatement( sql, callable );
}
}
else {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, callable );
@ -1552,23 +1555,24 @@ public abstract class AbstractCollectionPersister
writeElement( st, collection.getElement( entry ), offset, session );
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().getBatch( insertBatchKey ).addToBatch();
session.getJdbcCoordinator().getBatch( insertBatchKey ).addToBatch();
}
else {
expectation.verifyOutcome( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
}
collection.afterRowInsert( this, entry, i );
count++;
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}
@ -1936,22 +1940,23 @@ public abstract class AbstractCollectionPersister
@Override
public int getSize(Serializable key, SessionImplementor session) {
try {
PreparedStatement st = session.getTransactionCoordinator()
PreparedStatement st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sqlSelectSizeString );
try {
getKeyType().nullSafeSet( st, key, 1, session );
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
return rs.next() ? rs.getInt( 1 ) - baseIndex : 0;
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException sqle ) {
@ -1976,26 +1981,27 @@ public abstract class AbstractCollectionPersister
private boolean exists(Serializable key, Object indexOrElement, Type indexOrElementType, String sql, SessionImplementor session) {
try {
PreparedStatement st = session.getTransactionCoordinator()
PreparedStatement st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql );
try {
getKeyType().nullSafeSet( st, key, 1, session );
indexOrElementType.nullSafeSet( st, indexOrElement, keyColumnNames.length + 1, session );
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
return rs.next();
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
}
catch ( TransientObjectException e ) {
return false;
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException sqle ) {
@ -2011,14 +2017,14 @@ public abstract class AbstractCollectionPersister
@Override
public Object getElementByIndex(Serializable key, Object index, SessionImplementor session, Object owner) {
try {
PreparedStatement st = session.getTransactionCoordinator()
PreparedStatement st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sqlSelectRowByIndexString );
try {
getKeyType().nullSafeSet( st, key, 1, session );
getIndexType().nullSafeSet( st, incrementIndexByBase( index ), keyColumnNames.length + 1, session );
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( rs.next() ) {
return getElementType().nullSafeGet( rs, elementColumnAliases, session, owner );
@ -2028,11 +2034,12 @@ public abstract class AbstractCollectionPersister
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException sqle ) {

View File

@ -232,13 +232,13 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
expectation
);
}
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getBatch( updateBatchKey )
.getBatchStatement( sql, callable );
}
else {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, callable );
@ -261,24 +261,25 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
}
if ( useBatch ) {
session.getTransactionCoordinator()
session
.getJdbcCoordinator()
.getBatch( updateBatchKey )
.addToBatch();
}
else {
expectation.verifyOutcome( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
}
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
count++;

View File

@ -225,13 +225,13 @@ public class OneToManyPersister extends AbstractCollectionPersister {
expectation
);
}
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getBatch( recreateBatchKey )
.getBatchStatement( sql, callable );
}
else {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, callable );
@ -246,24 +246,25 @@ public class OneToManyPersister extends AbstractCollectionPersister {
offset = writeElement( st, collection.getElement( entry ), offset, session );
if ( useBatch ) {
session.getTransactionCoordinator()
session
.getJdbcCoordinator()
.getBatch( recreateBatchKey )
.addToBatch();
}
else {
expectation.verifyOutcome( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
}
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
@ -331,13 +332,13 @@ public class OneToManyPersister extends AbstractCollectionPersister {
Object entry = entries.next();
if ( collection.needsUpdating( entry, i, elementType ) ) { // will still be issued when it used to be null
if ( useBatch ) {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getBatch( deleteRowBatchKey )
.getBatchStatement( sql, isDeleteCallable() );
}
else {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, isDeleteCallable() );
@ -345,13 +346,13 @@ public class OneToManyPersister extends AbstractCollectionPersister {
int loc = writeKey( st, id, offset, session );
writeElementToWhere( st, collection.getSnapshotElement(entry, i), loc, session );
if ( useBatch ) {
session.getTransactionCoordinator()
session
.getJdbcCoordinator()
.getBatch( deleteRowBatchKey )
.addToBatch();
}
else {
deleteExpectation.verifyOutcome( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
deleteExpectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
}
count++;
}
@ -360,13 +361,14 @@ public class OneToManyPersister extends AbstractCollectionPersister {
}
catch ( SQLException e ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw e;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}
@ -393,13 +395,13 @@ public class OneToManyPersister extends AbstractCollectionPersister {
int offset = 1;
if ( collection.needsUpdating( entry, i, elementType ) ) {
if ( useBatch ) {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getBatch( insertRowBatchKey )
.getBatchStatement( sql, callable );
}
else {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, callable );
@ -415,10 +417,10 @@ public class OneToManyPersister extends AbstractCollectionPersister {
writeElementToWhere( st, collection.getElement( entry ), loc, session );
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().getBatch( insertRowBatchKey ).addToBatch();
session.getJdbcCoordinator().getBatch( insertRowBatchKey ).addToBatch();
}
else {
insertExpectation.verifyOutcome( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
insertExpectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
}
count++;
}
@ -427,13 +429,14 @@ public class OneToManyPersister extends AbstractCollectionPersister {
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}

View File

@ -938,12 +938,11 @@ 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.getTransactionCoordinator()
.getJdbcCoordinator()
ps = session.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( lazySelect );
getIdentifierType().nullSafeSet( ps, id, 1, session );
rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( ps );
rs = session.getJdbcCoordinator().getResultSetReturn().extract( ps );
rs.next();
}
final Object[] snapshot = entry.getLoadedState();
@ -956,13 +955,14 @@ public abstract class AbstractEntityPersister
}
finally {
if ( rs != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, ps );
session.getJdbcCoordinator().getResourceRegistry().release( rs, ps );
}
}
}
finally {
if ( ps != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
@ -1188,14 +1188,14 @@ public abstract class AbstractEntityPersister
}
try {
PreparedStatement ps = session.getTransactionCoordinator()
PreparedStatement ps = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( getSQLSnapshotSelectString() );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
//if ( isVersioned() ) getVersionType().nullSafeSet( ps, version, getIdentifierColumnSpan()+1, session );
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( ps );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( ps );
try {
//if there is no resulting row, return null
if ( !rs.next() ) {
@ -1213,11 +1213,12 @@ public abstract class AbstractEntityPersister
return values;
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, ps );
session.getJdbcCoordinator().getResourceRegistry().release( rs, ps );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException e ) {
@ -1249,13 +1250,13 @@ public abstract class AbstractEntityPersister
Type propertyType = getSubclassPropertyType( propertyIndex );
try {
PreparedStatement ps = session.getTransactionCoordinator()
PreparedStatement ps = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( generateIdByUniqueKeySelectString( uniquePropertyName ) );
try {
propertyType.nullSafeSet( ps, key, 1, session );
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( ps );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( ps );
try {
//if there is no resulting row, return null
if ( !rs.next() ) {
@ -1264,11 +1265,12 @@ public abstract class AbstractEntityPersister
return (Serializable) getIdentifierType().nullSafeGet( rs, getIdentifierAliases(), session, null );
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, ps );
session.getJdbcCoordinator().getResourceRegistry().release( rs, ps );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException e ) {
@ -1496,7 +1498,7 @@ public abstract class AbstractEntityPersister
String versionIncrementString = generateVersionIncrementUpdateString();
PreparedStatement st = null;
try {
st = session.getTransactionCoordinator()
st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( versionIncrementString, false );
@ -1504,13 +1506,14 @@ public abstract class AbstractEntityPersister
getVersionType().nullSafeSet( st, nextVersion, 1, session );
getIdentifierType().nullSafeSet( st, id, 2, session );
getVersionType().nullSafeSet( st, currentVersion, 2 + getIdentifierColumnSpan(), session );
int rows = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
int rows = session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
if ( rows != 1 ) {
throw new StaleObjectStateException( getEntityName(), id );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException sqle ) {
@ -1547,13 +1550,13 @@ public abstract class AbstractEntityPersister
}
try {
PreparedStatement st = session.getTransactionCoordinator()
PreparedStatement st = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( getVersionSelectString() );
try {
getIdentifierType().nullSafeSet( st, id, 1, session );
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( !rs.next() ) {
return null;
@ -1564,11 +1567,12 @@ public abstract class AbstractEntityPersister
return getVersionType().nullSafeGet( rs, getVersionColumnName(), session, null );
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
session.getJdbcCoordinator().getResourceRegistry().release( st );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException e ) {
@ -2514,12 +2518,12 @@ 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.getTransactionCoordinator()
sequentialSelect = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql );
rootPersister.getIdentifierType().nullSafeSet( sequentialSelect, id, 1, session );
sequentialResultSet = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( sequentialSelect );
sequentialResultSet = session.getJdbcCoordinator().getResultSetReturn().extract( sequentialSelect );
if ( !sequentialResultSet.next() ) {
// TODO: Deal with the "optional" attribute in the <join> mapping;
// this code assumes that optional defaults to "true" because it
@ -2576,7 +2580,7 @@ public abstract class AbstractEntityPersister
}
if ( sequentialResultSet != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( sequentialResultSet, sequentialSelect );
session.getJdbcCoordinator().getResourceRegistry().release( sequentialResultSet, sequentialSelect );
}
return values;
@ -2584,7 +2588,8 @@ public abstract class AbstractEntityPersister
}
finally {
if ( sequentialSelect != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( sequentialSelect );
session.getJdbcCoordinator().getResourceRegistry().release( sequentialSelect );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}
@ -2700,13 +2705,13 @@ public abstract class AbstractEntityPersister
// Render the SQL query
final PreparedStatement insert;
if ( useBatch ) {
insert = session.getTransactionCoordinator()
insert = session
.getJdbcCoordinator()
.getBatch( inserBatchKey )
.getBatchStatement( sql, callable );
}
else {
insert = session.getTransactionCoordinator()
insert = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, callable );
@ -2722,22 +2727,23 @@ public abstract class AbstractEntityPersister
dehydrate( id, fields, null, notNull, propertyColumnInsertable, j, insert, session, index, false );
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().getBatch( inserBatchKey ).addToBatch();
session.getJdbcCoordinator().getBatch( inserBatchKey ).addToBatch();
}
else {
expectation.verifyOutcome( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( insert ), insert, -1 );
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( insert ), insert, -1 );
}
}
catch ( SQLException e ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw e;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( insert );
session.getJdbcCoordinator().getResourceRegistry().release( insert );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}
@ -2830,13 +2836,13 @@ public abstract class AbstractEntityPersister
int index = 1; // starting index
final PreparedStatement update;
if ( useBatch ) {
update = session.getTransactionCoordinator()
update = session
.getJdbcCoordinator()
.getBatch( updateBatchKey )
.getBatchStatement( sql, callable );
}
else {
update = session.getTransactionCoordinator()
update = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, callable );
@ -2879,23 +2885,24 @@ public abstract class AbstractEntityPersister
}
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().getBatch( updateBatchKey ).addToBatch();
session.getJdbcCoordinator().getBatch( updateBatchKey ).addToBatch();
return true;
}
else {
return check( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( update ), id, j, expectation, update );
return check( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( update ), id, j, expectation, update );
}
}
catch ( SQLException e ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw e;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( update );
session.getJdbcCoordinator().getResourceRegistry().release( update );
session.getJdbcCoordinator().afterStatementExecution();
}
}
@ -2957,13 +2964,13 @@ public abstract class AbstractEntityPersister
PreparedStatement delete;
int index = 1;
if ( useBatch ) {
delete = session.getTransactionCoordinator()
delete = session
.getJdbcCoordinator()
.getBatch( deleteBatchKey )
.getBatchStatement( sql, callable );
}
else {
delete = session.getTransactionCoordinator()
delete = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql, callable );
@ -2998,22 +3005,23 @@ public abstract class AbstractEntityPersister
}
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().getBatch( deleteBatchKey ).addToBatch();
session.getJdbcCoordinator().getBatch( deleteBatchKey ).addToBatch();
}
else {
check( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( delete ), id, j, expectation, delete );
check( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( delete ), id, j, expectation, delete );
}
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
session.getJdbcCoordinator().abortBatch();
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( delete );
session.getJdbcCoordinator().getResourceRegistry().release( delete );
session.getJdbcCoordinator().afterStatementExecution();
}
}
@ -4432,16 +4440,16 @@ public abstract class AbstractEntityPersister
String selectionSQL,
GenerationTiming matchTiming) {
// force immediate execution of the insert batch (if one)
session.getTransactionCoordinator().getJdbcCoordinator().executeBatch();
session.getJdbcCoordinator().executeBatch();
try {
PreparedStatement ps = session.getTransactionCoordinator()
PreparedStatement ps = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( selectionSQL );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( ps );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( ps );
try {
if ( !rs.next() ) {
throw new HibernateException(
@ -4474,12 +4482,13 @@ public abstract class AbstractEntityPersister
}
finally {
if ( rs != null ) {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, ps );
session.getJdbcCoordinator().getResourceRegistry().release( rs, ps );
}
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch( SQLException e ) {
@ -4565,13 +4574,13 @@ public abstract class AbstractEntityPersister
Object[] snapshot = new Object[ naturalIdPropertyCount ];
try {
PreparedStatement ps = session.getTransactionCoordinator()
PreparedStatement ps = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( ps );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( ps );
try {
//if there is no resulting row, return null
if ( !rs.next() ) {
@ -4588,11 +4597,12 @@ public abstract class AbstractEntityPersister
return snapshot;
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, ps );
session.getJdbcCoordinator().getResourceRegistry().release( rs, ps );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException e ) {
@ -4621,7 +4631,7 @@ public abstract class AbstractEntityPersister
final String sqlEntityIdByNaturalIdString = determinePkByNaturalIdQuery( valueNullness );
try {
PreparedStatement ps = session.getTransactionCoordinator()
PreparedStatement ps = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sqlEntityIdByNaturalIdString );
@ -4636,7 +4646,7 @@ public abstract class AbstractEntityPersister
positions += type.getColumnSpan( session.getFactory() );
}
}
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( ps );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( ps );
try {
// if there is no resulting row, return null
if ( !rs.next() ) {
@ -4647,11 +4657,12 @@ public abstract class AbstractEntityPersister
return (Serializable) getIdentifierType().resolve( hydratedId, session, null );
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, ps );
session.getJdbcCoordinator().getResourceRegistry().release( rs, ps );
}
}
finally {
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch ( SQLException e ) {

View File

@ -39,6 +39,7 @@ import org.hibernate.QueryException;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -311,11 +312,12 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
}
if ( parameterStrategy == ParameterStrategy.UNKNOWN ) {
// protect to only do this check once
final ExtractedDatabaseMetaData databaseMetaData = getSession().getTransactionCoordinator()
final ExtractedDatabaseMetaData databaseMetaData = getSession()
.getJdbcCoordinator()
.getLogicalConnection()
.getJdbcServices()
.getExtractedMetaDataSupport();
.getJdbcSessionOwner()
.getJdbcSessionContext()
.getServiceRegistry().getService( JdbcEnvironment.class )
.getExtractedDatabaseMetaData();
if ( ! databaseMetaData.supportsNamedParameters() ) {
LOG.unsupportedNamedParameters();
}
@ -404,7 +406,7 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
);
try {
final CallableStatement statement = (CallableStatement) getSession().getTransactionCoordinator()
final CallableStatement statement = (CallableStatement) getSession()
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( call, true );

View File

@ -194,10 +194,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
session.getPersistenceContext().setDefaultReadOnly( true );
session.setFlushMode( FlushMode.MANUAL );
boolean isJTA = session.getTransactionCoordinator()
.getTransactionContext().getTransactionEnvironment()
.getTransactionFactory()
.compatibleWithJtaSynchronization();
boolean isJTA = session.getTransactionCoordinator().getTransactionCoordinatorBuilder().isJta();
if ( !isJTA ) {
// Explicitly handle the transactions only if we're not in

View File

@ -0,0 +1,66 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.jdbc;
import java.sql.Connection;
/**
* Models the logical notion of a JDBC Connection. We may release/re-acquire physical JDBC connections under the
* covers, but this logically represents the overall access to the JDBC Connection.
*
* @author Steve Ebersole
*/
public interface LogicalConnection {
/**
* Is this (logical) JDBC Connection still open/active. In other words, has {@link #close} not been called yet?
*
* @return {@code true} if still open ({@link #close} has not been called yet); {@code false} if not open
* (({@link #close} has been called).
*/
public boolean isOpen();
/**
* Closes the JdbcSession, making it inactive and forcing release of any held resources
*
* @return Legacy :( Returns the JDBC Connection *if* the user passed in a Connection originally.
*/
public Connection close();
/**
* Is this JdbcSession currently physically connected (meaning does it currently hold a JDBC Connection)?
*
* @return {@code true} if the JdbcSession currently hold a JDBC Connection; {@code false} if it does not.
*/
public boolean isPhysicallyConnected();
/**
* Provides access to the registry of JDBC resources associated with this LogicalConnection.
*
* @return The JDBC resource registry.
*
* @throws org.hibernate.ResourceClosedException if the LogicalConnection is closed
*/
public ResourceRegistry getResourceRegistry();
}

View File

@ -0,0 +1,94 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.jdbc;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.NClob;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* A registry for tracking JDBC resources
*
* @author Steve Ebersole
*/
public interface ResourceRegistry {
/**
* Does this registry currently have any registered resources?
*
* @return True if the registry does have registered resources; false otherwise.
*/
public boolean hasRegisteredResources();
public void releaseResources();
/**
* Register a JDBC statement.
*
* @param statement The statement to register.
* @param cancelable Is the statement being registered capable of being cancelled? In other words,
* should we register it to be the target of subsequent {@link #cancelLastQuery()} calls?
*/
public void register(Statement statement, boolean cancelable);
/**
* Release a previously registered statement.
*
* @param statement The statement to release.
*/
public void release(Statement statement);
/**
* Register a JDBC result set.
* <p/>
* Implementation note: Second parameter has been introduced to prevent
* multiple registrations of the same statement in case {@link java.sql.ResultSet#getStatement()}
* does not return original {@link java.sql.Statement} object.
*
* @param resultSet The result set to register.
* @param statement Statement from which {@link java.sql.ResultSet} has been generated.
*/
public void register(ResultSet resultSet, Statement statement);
/**
* Release a previously registered result set.
*
* @param resultSet The result set to release.
* @param statement Statement from which {@link java.sql.ResultSet} has been generated.
*/
public void release(ResultSet resultSet, Statement statement);
public void register(Blob blob);
public void release(Blob blob);
public void register(Clob clob);
public void release(Clob clob);
public void register(NClob nclob);
public void release(NClob nclob);
public void cancelLastQuery();
}

View File

@ -0,0 +1,134 @@
package org.hibernate.resource.jdbc.internal;
import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.ResourceClosedException;
import org.hibernate.TransactionException;
import org.hibernate.resource.jdbc.ResourceRegistry;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.resource.jdbc.spi.PhysicalJdbcTransaction;
import org.hibernate.resource.transaction.spi.TransactionStatus;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public abstract class AbstractLogicalConnectionImplementor implements LogicalConnectionImplementor, PhysicalJdbcTransaction {
private static final Logger log = Logger.getLogger( AbstractLogicalConnectionImplementor.class );
private TransactionStatus status = TransactionStatus.NOT_ACTIVE;
protected ResourceRegistry resourceRegistry;
@Override
public PhysicalJdbcTransaction getPhysicalJdbcTransaction() {
errorIfClosed();
return this;
}
protected void errorIfClosed() {
if ( !isOpen() ) {
throw new ResourceClosedException( this.toString() + " is closed" );
}
}
@Override
public ResourceRegistry getResourceRegistry() {
return resourceRegistry;
}
@Override
public void afterStatement() {
log.trace( "LogicalConnection#afterStatement" );
}
@Override
public void afterTransaction() {
log.trace( "LogicalConnection#afterTransaction" );
resourceRegistry.releaseResources();
}
// PhysicalJdbcTransaction impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
protected abstract Connection getConnectionForTransactionManagement();
@Override
public void begin() {
try {
log.trace( "Preparing to begin transaction via JDBC Connection.setAutoCommit(false)" );
getConnectionForTransactionManagement().setAutoCommit( false );
status = TransactionStatus.ACTIVE;
log.trace( "Transaction begun via JDBC Connection.setAutoCommit(false)" );
}
catch( SQLException e ) {
throw new TransactionException( "JDBC begin transaction failed: ", e );
}
}
@Override
public void commit() {
try {
log.trace( "Preparing to commit transaction via JDBC Connection.commit()" );
getConnectionForTransactionManagement().commit();
status = TransactionStatus.COMMITTED;
log.trace( "Transaction committed via JDBC Connection.commit()" );
}
catch( SQLException e ) {
status = TransactionStatus.FAILED_COMMIT;
throw new TransactionException( "Unable to commit against JDBC Connection", e );
}
afterCompletion();
}
protected void afterCompletion() {
// by default, nothing to do
}
protected void resetConnection(boolean initiallyAutoCommit) {
try {
if ( initiallyAutoCommit ) {
log.trace( "re-enabling auto-commit on JDBC Connection after completion of JDBC-based transaction" );
getConnectionForTransactionManagement().setAutoCommit( true );
status = TransactionStatus.NOT_ACTIVE;
}
}
catch ( Exception e ) {
log.debug(
"Could not re-enable auto-commit on JDBC Connection after completion of JDBC-based transaction : " + e
);
}
}
@Override
public void rollback() {
try {
log.trace( "Preparing to rollback transaction via JDBC Connection.rollback()" );
getConnectionForTransactionManagement().rollback();
status = TransactionStatus.ROLLED_BACK;
log.trace( "Transaction rolled-back via JDBC Connection.rollback()" );
}
catch( SQLException e ) {
throw new TransactionException( "Unable to rollback against JDBC Connection", e );
}
afterCompletion();
}
protected static boolean determineInitialAutoCommitMode(Connection providedConnection) {
try {
return providedConnection.getAutoCommit();
}
catch (SQLException e) {
log.debug( "Unable to ascertain initial auto-commit state of provided connection; assuming auto-commit" );
return true;
}
}
@Override
public TransactionStatus getStatus(){
return status;
}
}

View File

@ -0,0 +1,241 @@
package org.hibernate.resource.jdbc.internal;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.sql.SQLException;
import org.jboss.logging.Logger;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.ResourceClosedException;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.resource.jdbc.ResourceRegistry;
import org.hibernate.resource.jdbc.spi.JdbcObserver;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
/**
* Represents a LogicalConnection where we manage obtaining and releasing the Connection as needed.
*
* @author Steve Ebersole
*/
public class LogicalConnectionManagedImpl extends AbstractLogicalConnectionImplementor {
private static final Logger log = Logger.getLogger( LogicalConnectionManagedImpl.class );
private final transient JdbcConnectionAccess jdbcConnectionAccess;
private final transient JdbcObserver observer;
private final transient SqlExceptionHelper sqlExceptionHelper;
private final transient ConnectionReleaseMode connectionReleaseMode;
private transient Connection physicalConnection;
private boolean closed;
public LogicalConnectionManagedImpl(
JdbcConnectionAccess jdbcConnectionAccess,
JdbcSessionContext jdbcSessionContext) {
this( jdbcConnectionAccess, jdbcSessionContext, new ResourceRegistryStandardImpl() );
}
public LogicalConnectionManagedImpl(
JdbcConnectionAccess jdbcConnectionAccess,
JdbcSessionContext jdbcSessionContext,
ResourceRegistry resourceRegistry) {
this.jdbcConnectionAccess = jdbcConnectionAccess;
this.observer = jdbcSessionContext.getObserver();
this.sqlExceptionHelper = jdbcSessionContext.getServiceRegistry()
.getService( JdbcServices.class )
.getSqlExceptionHelper();
this.connectionReleaseMode = jdbcSessionContext.getConnectionReleaseMode();
this.resourceRegistry = resourceRegistry;
if ( jdbcSessionContext.getConnectionAcquisitionMode() == JdbcSessionContext.ConnectionAcquisitionMode.IMMEDIATELY ) {
if ( jdbcSessionContext.getConnectionReleaseMode() != ConnectionReleaseMode.ON_CLOSE ) {
throw new IllegalStateException(
"Illegal combination of ConnectionAcquisitionMode#IMMEDIATELY with !ConnectionReleaseMode.ON_CLOSE"
);
}
acquireConnectionIfNeeded();
}
}
private LogicalConnectionManagedImpl(
JdbcConnectionAccess jdbcConnectionAccess,
JdbcSessionContext jdbcSessionContext,
boolean closed) {
this( jdbcConnectionAccess, jdbcSessionContext, new ResourceRegistryStandardImpl() );
this.closed = closed;
}
private Connection acquireConnectionIfNeeded() {
if ( physicalConnection == null ) {
// todo : is this the right place for these observer calls?
observer.jdbcConnectionAcquisitionStart();
try {
physicalConnection = jdbcConnectionAccess.obtainConnection();
}
catch (SQLException e) {
throw sqlExceptionHelper.convert( e, "Unable to acquire JDBC Connection" );
}
finally {
observer.jdbcConnectionAcquisitionEnd( physicalConnection );
}
}
return physicalConnection;
}
@Override
public boolean isOpen() {
return !closed;
}
@Override
public boolean isPhysicallyConnected() {
return physicalConnection != null;
}
@Override
public Connection getPhysicalConnection() {
errorIfClosed();
return acquireConnectionIfNeeded();
}
@Override
public void afterStatement() {
super.afterStatement();
if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT ) {
if ( getResourceRegistry().hasRegisteredResources() ) {
log.debug( "Skipping aggressive release of JDBC Connection after-statement due to held resources" );
}
else {
log.debug( "Initiating JDBC connection release from afterStatement" );
releaseConnection();
}
}
}
@Override
public void afterTransaction() {
super.afterTransaction();
if ( connectionReleaseMode != ConnectionReleaseMode.ON_CLOSE ) {
// NOTE : we check for !ON_CLOSE here (rather than AFTER_TRANSACTION) to also catch AFTER_STATEMENT cases
// that were circumvented due to held resources
log.debug( "Initiating JDBC connection release from afterTransaction" );
releaseConnection();
}
}
@Override
public Connection manualDisconnect() {
if ( closed ) {
throw new ResourceClosedException( "Logical connection is closed" );
}
final Connection c = physicalConnection;
releaseConnection();
return c;
}
@Override
public void manualReconnect(Connection suppliedConnection) {
if ( closed ) {
throw new ResourceClosedException( "Logical connection is closed" );
}
throw new IllegalStateException( "Cannot manually reconnect unless Connection was originally supplied by user" );
}
private void releaseConnection() {
if ( physicalConnection == null ) {
return;
}
// todo : is this the right place for these observer calls?
observer.jdbcConnectionReleaseStart();
try {
if ( !physicalConnection.isClosed() ) {
sqlExceptionHelper.logAndClearWarnings( physicalConnection );
}
jdbcConnectionAccess.releaseConnection( physicalConnection );
}
catch (SQLException e) {
throw sqlExceptionHelper.convert( e, "Unable to release JDBC Connection" );
}
finally {
observer.jdbcConnectionReleaseEnd();
physicalConnection = null;
getResourceRegistry().releaseResources();
}
}
@Override
public LogicalConnectionImplementor makeShareableCopy() {
errorIfClosed();
// todo : implement
return null;
}
@Override
public void serialize(ObjectOutputStream oos) throws IOException {
oos.writeBoolean( closed );
}
public static LogicalConnectionManagedImpl deserialize(
ObjectInputStream ois,
JdbcConnectionAccess jdbcConnectionAccess,
JdbcSessionContext jdbcSessionContext) throws IOException, ClassNotFoundException {
final boolean isClosed = ois.readBoolean();
return new LogicalConnectionManagedImpl( jdbcConnectionAccess, jdbcSessionContext, isClosed );
}
@Override
public Connection close() {
if ( closed ) {
return null;
}
getResourceRegistry().releaseResources();
log.trace( "Closing logical connection" );
try {
releaseConnection();
}
finally {
// no matter what
closed = true;
log.trace( "Logical connection closed" );
}
return null;
}
// PhysicalJdbcTransaction impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
protected Connection getConnectionForTransactionManagement() {
return getPhysicalConnection();
}
boolean initiallyAutoCommit;
@Override
public void begin() {
initiallyAutoCommit = determineInitialAutoCommitMode( getConnectionForTransactionManagement() );
super.begin();
}
@Override
protected void afterCompletion() {
afterTransaction();
resetConnection( initiallyAutoCommit );
initiallyAutoCommit = false;
}
}

View File

@ -0,0 +1,164 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.jdbc.internal;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.resource.jdbc.LogicalConnection;
import org.hibernate.resource.jdbc.ResourceRegistry;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public class LogicalConnectionProvidedImpl extends AbstractLogicalConnectionImplementor {
private static final Logger log = Logger.getLogger( LogicalConnection.class );
private transient Connection providedConnection;
private final boolean initiallyAutoCommit;
private boolean closed;
public LogicalConnectionProvidedImpl(Connection providedConnection) {
this( providedConnection, new ResourceRegistryStandardImpl() );
}
public LogicalConnectionProvidedImpl(Connection providedConnection, ResourceRegistry resourceRegistry) {
this.resourceRegistry = resourceRegistry;
if ( providedConnection == null ) {
throw new IllegalArgumentException( "Provided Connection cannot be null" );
}
this.providedConnection = providedConnection;
this.initiallyAutoCommit = determineInitialAutoCommitMode( providedConnection );
}
private LogicalConnectionProvidedImpl(boolean closed, boolean initiallyAutoCommit) {
this.resourceRegistry = new ResourceRegistryStandardImpl();
this.closed = closed;
this.initiallyAutoCommit = initiallyAutoCommit;
}
@Override
public boolean isOpen() {
return !closed;
}
@Override
public Connection close() {
log.trace( "Closing logical connection" );
getResourceRegistry().releaseResources();
try {
return providedConnection;
}
finally {
providedConnection = null;
closed = true;
log.trace( "Logical connection closed" );
}
}
@Override
public boolean isPhysicallyConnected() {
return providedConnection != null;
}
@Override
public Connection getPhysicalConnection() {
errorIfClosed();
return providedConnection;
}
@Override
public LogicalConnectionImplementor makeShareableCopy() {
errorIfClosed();
return new LogicalConnectionProvidedImpl( providedConnection );
}
@Override
public void serialize(ObjectOutputStream oos) throws IOException {
oos.writeBoolean( closed );
oos.writeBoolean( initiallyAutoCommit );
}
public static LogicalConnectionProvidedImpl deserialize(
ObjectInputStream ois) throws IOException, ClassNotFoundException {
final boolean isClosed = ois.readBoolean();
final boolean initiallyAutoCommit = ois.readBoolean();
return new LogicalConnectionProvidedImpl( isClosed, initiallyAutoCommit );
}
@Override
public Connection manualDisconnect() {
errorIfClosed();
try {
resourceRegistry.releaseResources();
return providedConnection;
}
finally {
this.providedConnection = null;
}
}
@Override
public void manualReconnect(Connection connection) {
errorIfClosed();
if ( connection == null ) {
throw new IllegalArgumentException( "cannot reconnect using a null connection" );
}
else if ( connection == providedConnection ) {
// likely an unmatched reconnect call (no matching disconnect call)
log.debug( "reconnecting the same connection that is already connected; should this connection have been disconnected?" );
}
else if ( providedConnection != null ) {
throw new IllegalArgumentException(
"cannot reconnect to a new user-supplied connection because currently connected; must disconnect before reconnecting."
);
}
providedConnection = connection;
log.debug( "Manually reconnected logical connection" );
}
@Override
protected Connection getConnectionForTransactionManagement() {
return providedConnection;
}
@Override
protected void afterCompletion() {
afterTransaction();
resetConnection( initiallyAutoCommit );
}
}

View File

@ -0,0 +1,337 @@
package org.hibernate.resource.jdbc.internal;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.NClob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.resource.jdbc.ResourceRegistry;
/**
* @author Steve Ebersole
*/
public class ResourceRegistryStandardImpl implements ResourceRegistry {
private static final CoreMessageLogger log = CoreLogging.messageLogger( ResourceRegistryStandardImpl.class );
private final Map<Statement, Set<ResultSet>> xref = new HashMap<Statement, Set<ResultSet>>();
private final Set<ResultSet> unassociatedResultSets = new HashSet<ResultSet>();
private List<Blob> blobs;
private List<Clob> clobs;
private List<NClob> nclobs;
private Statement lastQuery;
@Override
public boolean hasRegisteredResources() {
return hasRegistered( xref )
|| hasRegistered( unassociatedResultSets )
|| hasRegistered( blobs )
|| hasRegistered( clobs )
|| hasRegistered( nclobs );
}
@Override
public void register(Statement statement, boolean cancelable) {
log.tracef( "Registering statement [%s]", statement );
if ( xref.containsKey( statement ) ) {
throw new HibernateException( "JDBC Statement already registered" );
}
xref.put( statement, null );
if ( cancelable ) {
lastQuery = statement;
}
}
@Override
public void release(Statement statement) {
log.tracev( "Releasing statement [{0}]", statement );
// Keep this at DEBUG level, rather than warn. Numerous connection pool implementations can return a
// proxy/wrapper around the JDBC Statement, causing excessive logging here. See HHH-8210.
if ( log.isDebugEnabled() && !xref.containsKey( statement ) ) {
log.unregisteredStatement();
}
else {
final Set<ResultSet> resultSets = xref.get( statement );
if ( resultSets != null ) {
closeAll( resultSets );
}
xref.remove( statement );
}
close( statement );
if ( lastQuery == statement ) {
lastQuery = null;
}
}
@Override
public void release(ResultSet resultSet, Statement statement) {
log.tracef( "Releasing result set [%s]", resultSet );
if ( statement == null ) {
try {
statement = resultSet.getStatement();
}
catch (SQLException e) {
throw convert( e, "unable to access Statement from ResultSet" );
}
}
if ( statement != null ) {
final Set<ResultSet> resultSets = xref.get( statement );
if ( resultSets == null ) {
log.unregisteredStatement();
}
else {
resultSets.remove( resultSet );
if ( resultSets.isEmpty() ) {
xref.remove( statement );
}
}
}
else {
final boolean removed = unassociatedResultSets.remove( resultSet );
if ( !removed ) {
log.unregisteredResultSetWithoutStatement();
}
}
close( resultSet );
}
protected void closeAll(Set<ResultSet> resultSets) {
for ( ResultSet resultSet : resultSets ) {
close( resultSet );
}
resultSets.clear();
}
@SuppressWarnings({"unchecked"})
public static void close(ResultSet resultSet) {
log.tracef( "Closing result set [%s]", resultSet );
try {
resultSet.close();
}
catch (SQLException e) {
log.debugf( "Unable to release JDBC result set [%s]", e.getMessage() );
}
catch (Exception e) {
// try to handle general errors more elegantly
log.debugf( "Unable to release JDBC result set [%s]", e.getMessage() );
}
}
@SuppressWarnings({"unchecked"})
public static void close(Statement statement) {
log.tracef( "Closing prepared statement [%s]", statement );
try {
// if we are unable to "clean" the prepared statement,
// we do not close it
try {
if ( statement.getMaxRows() != 0 ) {
statement.setMaxRows( 0 );
}
if ( statement.getQueryTimeout() != 0 ) {
statement.setQueryTimeout( 0 );
}
}
catch (SQLException sqle) {
// there was a problem "cleaning" the prepared statement
if ( log.isDebugEnabled() ) {
log.debugf( "Exception clearing maxRows/queryTimeout [%s]", sqle.getMessage() );
}
// EARLY EXIT!!!
return;
}
statement.close();
}
catch (SQLException e) {
log.debugf( "Unable to release JDBC statement [%s]", e.getMessage() );
}
catch (Exception e) {
// try to handle general errors more elegantly
log.debugf( "Unable to release JDBC statement [%s]", e.getMessage() );
}
}
@Override
public void register(ResultSet resultSet, Statement statement) {
log.tracef( "Registering result set [%s]", resultSet );
if ( statement == null ) {
try {
statement = resultSet.getStatement();
}
catch (SQLException e) {
throw convert( e, "unable to access Statement from ResultSet" );
}
}
if ( statement != null ) {
// Keep this at DEBUG level, rather than warn. Numerous connection pool implementations can return a
// proxy/wrapper around the JDBC Statement, causing excessive logging here. See HHH-8210.
if ( log.isDebugEnabled() && !xref.containsKey( statement ) ) {
log.debug( "ResultSet statement was not registered (on register)" );
}
Set<ResultSet> resultSets = xref.get( statement );
if ( resultSets == null ) {
resultSets = new HashSet<ResultSet>();
xref.put( statement, resultSets );
}
resultSets.add( resultSet );
}
else {
unassociatedResultSets.add( resultSet );
}
}
private JDBCException convert(SQLException e, String s) {
// todo : implement
return null;
}
@Override
public void register(Blob blob) {
if ( blobs == null ) {
blobs = new ArrayList<Blob>();
}
blobs.add( blob );
}
@Override
public void release(Blob blob) {
if ( blobs == null ) {
log.debug( "Request to release Blob, but appears no Blobs have ever been registered" );
return;
}
blobs.remove( blob );
}
@Override
public void register(Clob clob) {
if ( clobs == null ) {
clobs = new ArrayList<Clob>();
}
clobs.add( clob );
}
@Override
public void release(Clob clob) {
if ( clobs == null ) {
log.debug( "Request to release Clob, but appears no Clobs have ever been registered" );
return;
}
clobs.remove( clob );
}
@Override
public void register(NClob nclob) {
// todo : just store them in clobs?
if ( nclobs == null ) {
nclobs = new ArrayList<NClob>();
}
nclobs.add( nclob );
}
@Override
public void release(NClob nclob) {
// todo : just store them in clobs?
if ( nclobs == null ) {
log.debug( "Request to release NClob, but appears no NClobs have ever been registered" );
return;
}
nclobs.remove( nclob );
}
@Override
public void cancelLastQuery() {
try {
if ( lastQuery != null ) {
lastQuery.cancel();
}
}
catch (SQLException e) {
throw convert( e, "Cannot cancel query" );
}
finally {
lastQuery = null;
}
}
@Override
public void releaseResources() {
log.trace( "Releasing JDBC resources" );
for ( Map.Entry<Statement, Set<ResultSet>> entry : xref.entrySet() ) {
if ( entry.getValue() != null ) {
closeAll( entry.getValue() );
}
close( entry.getKey() );
}
xref.clear();
closeAll( unassociatedResultSets );
if ( blobs != null ) {
for ( Blob blob : blobs ) {
try {
blob.free();
}
catch (SQLException e) {
log.debugf( "Unable to free JDBC Blob reference [%s]", e.getMessage() );
}
}
blobs.clear();
}
if ( clobs != null ) {
for ( Clob clob : clobs ) {
try {
clob.free();
}
catch (SQLException e) {
log.debugf( "Unable to free JDBC Clob reference [%s]", e.getMessage() );
}
}
clobs.clear();
}
if ( nclobs != null ) {
for ( NClob nclob : nclobs ) {
try {
nclob.free();
}
catch (SQLException e) {
log.debugf( "Unable to free JDBC NClob reference [%s]", e.getMessage() );
}
}
nclobs.clear();
}
}
private boolean hasRegistered(Map resource) {
return resource != null && !resource.isEmpty();
}
private boolean hasRegistered(Collection resource) {
return resource != null && !resource.isEmpty();
}
}

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.jdbc.spi;
import java.sql.Connection;
/**
* @author Steve Ebersole
*/
public interface JdbcObserver {
public void jdbcConnectionAcquisitionStart();
public void jdbcConnectionAcquisitionEnd(Connection connection);
public void jdbcConnectionReleaseStart();
public void jdbcConnectionReleaseEnd();
public void jdbcPrepareStatementStart();
public void jdbcPrepareStatementEnd();
public void jdbcExecuteStatementStart();
public void jdbcExecuteStatementEnd();
public void jdbcExecuteBatchStart();
public void jdbcExecuteBatchEnd();
}

View File

@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* Copyright (c) 2013, 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.
@ -21,51 +21,44 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.transaction.spi;
package org.hibernate.resource.jdbc.spi;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.service.ServiceRegistry;
/**
* Provides access to transactional services.
* Provides the JdbcSession implementation with contextual information it needs during its lifecycle.
*
* @author Steve Ebersole
*/
public interface TransactionEnvironment {
public interface JdbcSessionContext {
public boolean isScrollableResultSetsEnabled();
public boolean isGetGeneratedKeysEnabled();
public int getFetchSize();
public ConnectionReleaseMode getConnectionReleaseMode();
public ConnectionAcquisitionMode getConnectionAcquisitionMode();
public StatementInspector getStatementInspector();
public JdbcObserver getObserver();
/**
* Retrieve the session factory for this environment.
*
* @return The session factory
*/
* Retrieve the session factory for this environment.
*
* @return The session factory
*/
public SessionFactoryImplementor getSessionFactory();
/**
* Retrieve the JDBC services for this environment.
*
* @return The JDBC services
*/
public JdbcServices getJdbcServices();
public ServiceRegistry getServiceRegistry();
/**
* Retrieve the JTA platform for this environment.
*
* @return The JTA platform
*/
public JtaPlatform getJtaPlatform();
/**
* Retrieve the transaction factory for this environment.
*
* @return The transaction factory
*/
public TransactionFactory getTransactionFactory();
/**
* Get access to the statistics collector
*
* @return The statistics collector
*/
public StatisticsImplementor getStatisticsImplementor();
public static enum ConnectionAcquisitionMode {
IMMEDIATELY,
AS_NEEDED,
DEFAULT
}
}

View File

@ -0,0 +1,62 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.jdbc.spi;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.resource.transaction.TransactionCoordinatorBuilder;
/**
* @author Steve Ebersole
*/
public interface JdbcSessionOwner {
/**
* Obtain the builder for TransactionCoordinator instances
*
* @return The TransactionCoordinatorBuilder
*/
public TransactionCoordinatorBuilder getTransactionCoordinatorBuilder();
public JdbcSessionContext getJdbcSessionContext();
public JdbcConnectionAccess getJdbcConnectionAccess();
/**
* A after-begin callback from the coordinator to its owner.
*/
public void afterTransactionBegin();
/**
* A before-completion callback to the owner.
*/
public void beforeTransactionCompletion();
/**
* An after-completion callback to the owner.
*
* @param successful Was the transaction successful?
*/
public void afterTransactionCompletion(boolean successful);
public void flushBeforeTransactionCompletion();
}

View File

@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* Copyright (c) 2013, 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.
@ -21,52 +21,39 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.spi;
package org.hibernate.resource.jdbc.spi;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.JDBCException;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.resource.jdbc.LogicalConnection;
/**
* The "internal" contract for LogicalConnection
*
* @author Steve Ebersole
* @author Brett Meyer
*/
public interface LogicalConnectionImplementor extends LogicalConnection {
/**
* Obtains the JDBC services associated with this logical connection.
*
* @return JDBC services
*/
public JdbcServices getJdbcServices();
// todo : expose the Connection as below? or accept(WorkInConnection) where WorkInConnection is given access to Connection?
public Connection getPhysicalConnection();
/**
* Add an observer interested in notification of connection events.
*
* @param observer The observer.
* Notification indicating a JDBC statement has been executed to trigger
* {@link org.hibernate.ConnectionReleaseMode#AFTER_STATEMENT} releasing if needed
*/
public void addObserver(ConnectionObserver observer);
public void afterStatement();
/**
* Remove an observer
*
* @param connectionObserver The observer to remove.
* Notification indicating a transaction has completed to trigger
* {@link org.hibernate.ConnectionReleaseMode#AFTER_TRANSACTION} releasing if needed
*/
public void removeObserver(ConnectionObserver connectionObserver);
/**
* The release mode under which this logical connection is operating.
*
* @return the release mode.
*/
public ConnectionReleaseMode getConnectionReleaseMode();
public void afterTransaction();
/**
* 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 maintained here at time of disconnect. Null if
* @return The connection maintained here at time of disconnect. {@code null} if
* there was no connection cached internally.
*/
public Connection manualDisconnect();
@ -80,33 +67,20 @@ public interface LogicalConnectionImplementor extends LogicalConnection {
public void manualReconnect(Connection suppliedConnection);
/**
* Perform an aggressive release
*/
public void aggressiveRelease();
/**
* Release any held connection.
* Creates a shareable copy of itself for use in "shared sessions"
*
* @throws JDBCException Indicates a problem releasing the connection
* @return The shareable copy.
*/
public void releaseConnection() throws JDBCException;
public LogicalConnectionImplementor makeShareableCopy();
public PhysicalJdbcTransaction getPhysicalJdbcTransaction();
/**
* Is this logical connection in auto-commit mode?
* Serialization hook
*
* @return {@code true} if auto-commit
*/
public boolean isAutoCommit();
/**
* Callback to notify all registered observers of a connection being prepared.
*/
public void notifyObserversStatementPrepared();
/**
* Does this logical connection wrap a user/application supplied connection?
* @param oos The stream to write out state to
*
* @return {@code true} if the underlying connection was user supplied.
* @throws java.io.IOException Problem accessing stream
*/
public boolean isUserSuppliedConnection();
public void serialize(ObjectOutputStream oos) throws IOException;
}

View File

@ -0,0 +1,34 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.jdbc.spi;
import org.hibernate.resource.transaction.backend.store.spi.DataStoreTransaction;
/**
* Provides access to manage "transactionality" via the JDBC Connection
*
* @author Steve Ebersole
*/
public interface PhysicalJdbcTransaction extends DataStoreTransaction {
}

View File

@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* Copyright (c) 2013, 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.
@ -21,27 +21,21 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.transaction.synchronization.spi;
import java.io.Serializable;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
package org.hibernate.resource.jdbc.spi;
/**
* A pluggable strategy for defining how the {@link javax.transaction.Synchronization} registered by Hibernate determines
* whether to perform a managed flush. An exceptions from either this delegate or the subsequent flush are routed
* through the sister strategy {@link ExceptionMapper}.
* Contract to allow inspection (and swapping) of SQL to be prepared
*
* @author Steve Ebersole
*/
public interface ManagedFlushChecker extends Serializable {
public interface StatementInspector {
/**
* Check whether we should perform the managed flush
* Inspect the given SQL, possibly returning a different SQL to be used instead. Note that returning {@code null}
* is interpreted as returning the same SQL as was passed.
*
* @param coordinator The transaction coordinator
* @param jtaStatus The status of the current JTA transaction.
* @param sql The SQL to inspect
*
* @return True to indicate to perform the managed flush; false otherwise.
* @return The SQL to use; may be {@code null}
*/
public boolean shouldDoManagedFlush(TransactionCoordinator coordinator, int jtaStatus);
public String inspect(String sql);
}

View File

@ -0,0 +1,37 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.transaction;
import org.hibernate.HibernateException;
/**
* Wraps an exception thrown from a "local synchronization" (one registered in the SynchronizationRegistry).
*
* @author Steve Ebersole
*/
public class LocalSynchronizationException extends HibernateException {
public LocalSynchronizationException(String message, Throwable cause) {
super( message, cause );
}
}

View File

@ -0,0 +1,41 @@
/*
* 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.resource.transaction;
import org.hibernate.HibernateException;
/**
* Indicates an attempt to register a null synchronization. Basically a glorified {@link NullPointerException}
*
* @author Steve Ebersole
*/
public class NullSynchronizationException extends HibernateException {
public NullSynchronizationException() {
this( "Synchronization to register cannot be null" );
}
public NullSynchronizationException(String s) {
super( s );
}
}

View File

@ -21,18 +21,23 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.transaction.synchronization.spi;
package org.hibernate.resource.transaction;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import java.io.Serializable;
import javax.transaction.Synchronization;
/**
* A pluggable strategy for defining any actions to be performed during
* {@link javax.transaction.Synchronization#afterCompletion} processing from the the
* {@link javax.transaction.Synchronization} registered by Hibernate with the underlying JTA platform.
* Manages a registry of (local) JTA {@link Synchronization} instances
*
* @author Steve Ebersole
*/
public interface AfterCompletionAction {
public void doAction(TransactionCoordinator transactionCoordinator, int status);
public interface SynchronizationRegistry extends Serializable {
/**
* Register a {@link Synchronization} callback for this transaction.
*
* @param synchronization The synchronization callback to register.
*
* @throws NullSynchronizationException if the synchronization is {@code null}
*/
void registerSynchronization(Synchronization synchronization);
}

View File

@ -0,0 +1,150 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.transaction;
import org.hibernate.engine.transaction.spi.IsolationDelegate;
import org.hibernate.engine.transaction.spi.TransactionObserver;
import org.hibernate.resource.transaction.spi.TransactionStatus;
/**
* Models the coordination of all transaction related flows.
*
* @author Steve Ebersole
*/
public interface TransactionCoordinator {
/**
* Indicates an explicit request to join a transaction. This is mainly intended to handle the JPA requirement
* around {@link javax.persistence.EntityManager#joinTransaction()}, and generally speaking only has an impact in
* JTA environments
*/
public void explicitJoin();
/**
* Determine if there is an active transaction that this coordinator is already joined to.
*
* @return {@code true} if there is an active transaction this coordinator is already joined to; {@code false}
* otherwise.
*/
public boolean isJoined();
/**
* Used by owner of the JdbcSession as a means to indicate that implicit joining should be done if needed.
*/
public void pulse();
/**
* Get the delegate used by the local transaction driver to control the underlying transaction
*
* @return The control delegate.
*/
public LocalInflow getTransactionDriverControl();
/**
* Get access to the local registry of Synchronization instances
*
* @return The local Synchronization registry
*/
public SynchronizationRegistry getLocalSynchronizations();
/**
* Is this transaction still active?
* <p/>
* Answers on a best effort basis. For example, in the case of JDBC based transactions we cannot know that a
* transaction is active when it is initiated directly through the JDBC {@link java.sql.Connection}, only when
* it is initiated from here.
*
* @return {@code true} if the transaction is still active; {@code false} otherwise.
*
* @throws org.hibernate.HibernateException Indicates a problem checking the transaction status.
*/
public boolean isActive();
/**
* Retrieve an isolation delegate appropriate for this transaction strategy.
*
* @return An isolation delegate.
*/
public IsolationDelegate createIsolationDelegate();
/**
* Adds an observer to the coordinator.
* <p/>
* observers are not to be cleared on transaction completion.
*
* @param observer The observer to add.
*/
public void addObserver(TransactionObserver observer);
/**
* Removed an observer from the coordinator.
*
* @param observer The observer to remove.
*/
public void removeObserver(TransactionObserver observer);
/**
*
* @return
*/
public TransactionCoordinatorBuilder getTransactionCoordinatorBuilder();
public void setTimeOut(int seconds);
public int getTimeOut();
/**
* Provides the means for "local transactions" (as transaction drivers) to control the
* underlying "physical transaction" currently associated with the TransactionCoordinator.
*
* @author Steve Ebersole
*/
public interface LocalInflow {
/**
* Begin the physical transaction
*/
public void begin();
/**
* Commit the physical transaction
*/
public void commit();
/**
* Rollback the physical transaction
*/
public void rollback();
public TransactionStatus getStatus();
public void markRollbackOnly();
// todo : org.hibernate.Transaction will need access to register local Synchronizations.
// depending on how we integrate TransactionCoordinator/TransactionDriverControl with
// org.hibernate.Transaction that might be best done by:
// 1) exposing registerSynchronization here (if the Transaction is just passed this)
// 2) using the exposed TransactionCoordinator#getLocalSynchronizations (if the Transaction is passed the TransactionCoordinator)
//
// if
}
}

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.transaction;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.transaction.TransactionCoordinator;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorOwner;
import org.hibernate.service.Service;
import static org.hibernate.resource.jdbc.spi.JdbcSessionContext.ConnectionAcquisitionMode;
/**
* Builder for TransactionCoordinator instances
*
* @author Steve Ebersole
*/
public interface TransactionCoordinatorBuilder extends Service {
public TransactionCoordinator buildTransactionCoordinator(TransactionCoordinatorOwner owner);
public boolean isJta();
public ConnectionReleaseMode getDefaultConnectionReleaseMode();
public ConnectionAcquisitionMode getDefaultConnectionAcquisitionMode();
}

View File

@ -0,0 +1,64 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.transaction;
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl;
import org.hibernate.resource.transaction.backend.store.internal.ResourceLocalTransactionCoordinatorBuilderImpl;
/**
* Factory for obtaining instances of standard TransactionCoordinatorBuilder implementations
*
* @author Steve Ebersole
*/
public class TransactionCoordinatorBuilderFactory {
/**
* Singleton access
*/
public static final TransactionCoordinatorBuilderFactory INSTANCE = new TransactionCoordinatorBuilderFactory();
/**
* Private constructor for the factory
*/
private TransactionCoordinatorBuilderFactory() {
}
/**
* Obtain a TransactionCoordinatorBuilder specific to resource-local environments
*
* @return The resource-local specific TransactionCoordinatorBuilder
*/
public TransactionCoordinatorResourceLocalBuilder forResourceLocal() {
return new ResourceLocalTransactionCoordinatorBuilderImpl();
}
/**
* Obtain a TransactionCoordinatorBuilder specific to JTA environments
*
* @return The JTA specific TransactionCoordinatorBuilder
*/
public TransactionCoordinatorJtaBuilder forJta() {
return new JtaTransactionCoordinatorBuilderImpl();
}
}

View File

@ -0,0 +1,77 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.transaction;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
/**
* A builder of TransactionCoordinator instances intended for use in JTA environments.
*
* @author Steve Ebersole
*/
public interface TransactionCoordinatorJtaBuilder extends TransactionCoordinatorBuilder {
/**
* Specifies the JtaPlatform to use.
*
* @param jtaPlatform The JtaPlatform to use.
*
* @return {@code this}, for method chaining
*/
public TransactionCoordinatorJtaBuilder setJtaPlatform(JtaPlatform jtaPlatform);
/**
* Should JTA transactions be automatically joined? Or should we wait for (JPA-style) explicit joining? The
* default is to auto-join ({@code true}).
*
* @param autoJoinTransactions {@code true} (default) indicates that JTA transactions should be auto joined;
* {@code false} indicated we should wait for an explicit join
*
* @return {@code this}, for method chaining
*/
public TransactionCoordinatorJtaBuilder setAutoJoinTransactions(boolean autoJoinTransactions);
/**
* Should we prefer to use UserTransactions (over TransactionManager) for managing transactions (mainly for calling
* begin, commit, rollback)? We will try both, this controls which to check first. The default is to prefer
* accessing the TransactionManager
*
* @param preferUserTransactions {@code true} indicates to look for UserTransactions first; {@code false} (the
* default) indicates to looks for the TransactionManager first,
*
* @return {@code this}, for method chaining
*/
public TransactionCoordinatorJtaBuilder setPreferUserTransactions(boolean preferUserTransactions);
/**
* Should we track threads in order to protect against the JTA system calling us from a different thread? This
* might often be the case for JTA systems which implement timeout rollbacks from separate "reaper" threads. The
* default is to track threads.
*
* @param performJtaThreadTracking {@code true} (the default) indicates that the thread should be tracked;
* {@code false} indicates it should not.
*
* @return {@code this}, for method chaining
*/
public TransactionCoordinatorJtaBuilder setPerformJtaThreadTracking(boolean performJtaThreadTracking);
}

View File

@ -0,0 +1,51 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.resource.transaction;
import org.hibernate.resource.transaction.backend.store.spi.DataStoreTransactionAccess;
/**
* A builder of TransactionCoordinator instances intended for use in resource-local mode (non-JTA transactions local
* to the underlying data store).
* <p/>
* NOTE : Ideally I'd love to specialize the {@link #buildTransactionCoordinator(org.hibernate.resource.transaction.spi.TransactionCoordinatorOwner)}
* method here to only accept TransactionCoordinatorOwner arguments that are specifically
* {@link org.hibernate.resource.transaction.backend.store.spi.DataStoreTransactionAccess} instances. Not sure how to
* best achieve that. For now we just cast and let the exception happen, but directing the user via the contract
* would be MUCH preferable.
*
* @author Steve Ebersole
*/
public interface TransactionCoordinatorResourceLocalBuilder extends TransactionCoordinatorBuilder {
/**
* Provides the TransactionCoordinator we are building with access to the ResourceLocalTransaction used to control
* transactions.
* <p/>
* An alternative is for the owner passed to {@link #buildTransactionCoordinator} to implement the
* ResourceLocalTransactionAccess contract.
*
* @param dataStoreTransactionAccess Access
*/
public void setResourceLocalTransactionAccess(DataStoreTransactionAccess dataStoreTransactionAccess);
}

View File

@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* Copyright (c) {DATE}, 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.
@ -21,20 +21,19 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.transaction.internal.jta;
package org.hibernate.resource.transaction.backend.jta.internal;
import java.sql.Connection;
import java.sql.SQLException;
import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.transaction.spi.IsolationDelegate;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.jdbc.WorkExecutor;
@ -43,39 +42,34 @@ import org.hibernate.jdbc.WorkExecutorVisitable;
/**
* An isolation delegate for JTA environments.
*
* @author Steve Ebersole
* @author Andrea Boriero
*/
public class JtaIsolationDelegate implements IsolationDelegate {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( JtaIsolationDelegate.class );
private final TransactionCoordinator transactionCoordinator;
private final JdbcConnectionAccess connectionAccess;
private final SqlExceptionHelper sqlExceptionHelper;
private final TransactionManager transactionManager;
public JtaIsolationDelegate(TransactionCoordinator transactionCoordinator) {
this.transactionCoordinator = transactionCoordinator;
}
protected TransactionManager transactionManager() {
return transactionCoordinator.getTransactionContext()
.getTransactionEnvironment()
.getJtaPlatform()
.retrieveTransactionManager();
public JtaIsolationDelegate(
JdbcConnectionAccess connectionAccess,
SqlExceptionHelper sqlExceptionHelper,
TransactionManager transactionManager) {
this.connectionAccess = connectionAccess;
this.sqlExceptionHelper = sqlExceptionHelper;
this.transactionManager = transactionManager;
}
protected JdbcConnectionAccess jdbcConnectionAccess() {
return transactionCoordinator.getTransactionContext().getJdbcConnectionAccess();
return this.connectionAccess;
}
protected SqlExceptionHelper sqlExceptionHelper() {
return transactionCoordinator.getTransactionContext()
.getTransactionEnvironment()
.getJdbcServices()
.getSqlExceptionHelper();
return this.sqlExceptionHelper;
}
@Override
public <T> T delegateWork(WorkExecutorVisitable<T> work, boolean transacted) throws HibernateException {
TransactionManager transactionManager = transactionManager();
try {
// First we suspend any current JTA transaction
Transaction surroundingTransaction = transactionManager.suspend();
@ -91,7 +85,7 @@ public class JtaIsolationDelegate implements IsolationDelegate {
return doTheWorkInNoTransaction( work );
}
}
catch ( HibernateException e ) {
catch (HibernateException e) {
hadProblems = true;
throw e;
}
@ -100,7 +94,7 @@ public class JtaIsolationDelegate implements IsolationDelegate {
transactionManager.resume( surroundingTransaction );
LOG.debugf( "Surrounding JTA transaction resumed [%s]", surroundingTransaction );
}
catch( Throwable t ) {
catch (Throwable t) {
// if the actually work had an error use that, otherwise error based on t
if ( !hadProblems ) {
//noinspection ThrowFromFinallyBlock
@ -109,7 +103,7 @@ public class JtaIsolationDelegate implements IsolationDelegate {
}
}
}
catch ( SystemException e ) {
catch (SystemException e) {
throw new HibernateException( "Unable to suspend current JTA transaction", e );
}
}
@ -125,20 +119,20 @@ public class JtaIsolationDelegate implements IsolationDelegate {
transactionManager.commit();
return result;
}
catch ( Exception e ) {
catch (Exception e) {
try {
transactionManager.rollback();
}
catch ( Exception ignore ) {
catch (Exception ignore) {
LOG.unableToRollbackIsolatedTransaction( e, ignore );
}
throw new HibernateException( "Could not apply work", e );
}
}
catch ( SystemException e ) {
catch (SystemException e) {
throw new HibernateException( "Unable to start isolated transaction", e );
}
catch ( NotSupportedException e ) {
catch (NotSupportedException e) {
throw new HibernateException( "Unable to start isolated transaction", e );
}
}
@ -155,10 +149,10 @@ public class JtaIsolationDelegate implements IsolationDelegate {
// do the actual work
return work.accept( new WorkExecutor<T>(), connection );
}
catch ( HibernateException e ) {
catch (HibernateException e) {
throw e;
}
catch ( Exception e ) {
catch (Exception e) {
throw new HibernateException( "Unable to perform isolated work", e );
}
finally {
@ -166,14 +160,13 @@ public class JtaIsolationDelegate implements IsolationDelegate {
// no matter what, release the connection (handle)
jdbcConnectionAccess().releaseConnection( connection );
}
catch ( Throwable ignore ) {
catch (Throwable ignore) {
LOG.unableToReleaseIsolatedConnection( ignore );
}
}
}
catch ( SQLException e ) {
catch (SQLException e) {
throw sqlExceptionHelper().convert( e, "unable to obtain isolated JDBC connection" );
}
}
}

View File

@ -0,0 +1,45 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.resource.transaction.backend.jta.internal;
import org.jboss.logging.Logger;
import org.jboss.logging.annotations.MessageLogger;
import org.jboss.logging.annotations.ValidIdRange;
/**
* Acts as the {@link org.jboss.logging.annotations.MessageLogger} related to
* JTA transaction processing
*
* @author Steve Ebersole
*/
@MessageLogger( projectCode = "HHH" )
@ValidIdRange( min = 10001001, max = 10002000 )
public interface JtaMessageLogger {
public static final JtaMessageLogger INSTANCE = Logger.getMessageLogger(
JtaMessageLogger.class,
"org.hibernate.orm.txn.backend.jta"
);
}

Some files were not shown because too many files have changed in this diff Show More