diff --git a/build.gradle b/build.gradle
index efada05429..7929ef22b2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -67,6 +67,7 @@ libraries = [
jcl: 'commons-logging:commons-logging:99.0-does-not-exist',
// testing
+ atomikos: 'com.atomikos:transactions-jdbc:3.7.0',
junit: 'junit:junit:3.8.2',
testng: 'org.testng:testng:5.8:jdk15',
jpa_modelgen: 'org.hibernate:hibernate-jpamodelgen:1.1.0.Final',
@@ -106,6 +107,7 @@ subprojects { subProject ->
dependencies {
compile( libraries.slf4j_api )
testCompile( libraries.junit )
+ testCompile( libraries.atomikos )
testRuntime( libraries.slf4j_simple )
testRuntime( libraries.jcl_slf4j )
testRuntime( libraries.jcl_api )
@@ -151,12 +153,8 @@ subprojects { subProject ->
sourceCompatibility = "1.6"
ideaModule {
- // treat our "provided" configuration dependencies as "Compile" scope dependencies in IntelliJ
+ // treat our "provided" configuration dependencies as "compile" scope dependencies in IntelliJ
scopes.COMPILE.plus.add( configurations.provided )
- // Use explicitly separate compilation output directories for Gradle and IntelliJ
- File baseDirectory = new File( subProject.buildDir, "idea/classes" )
- outputDir = new File( baseDirectory, "main" )
- testOutputDir = new File( baseDirectory, "test" )
whenConfigured { module ->
module.dependencies*.exported = true
}
diff --git a/hibernate-core/hibernate-core.gradle b/hibernate-core/hibernate-core.gradle
index 7263d71648..23defc1a7b 100644
--- a/hibernate-core/hibernate-core.gradle
+++ b/hibernate-core/hibernate-core.gradle
@@ -96,4 +96,9 @@ task installTesting(type:Upload, dependsOn: [testingJar,testingSourcesJar]) {
}
install.dependsOn installTesting
-uploadTesting.dependsOn installTesting
\ No newline at end of file
+uploadTesting.dependsOn installTesting
+
+// temporary
+test {
+ ignoreFailures = true
+}
\ No newline at end of file
diff --git a/hibernate-core/src/main/java/org/hibernate/HibernateException.java b/hibernate-core/src/main/java/org/hibernate/HibernateException.java
index 4699d28dc7..5e75777632 100644
--- a/hibernate-core/src/main/java/org/hibernate/HibernateException.java
+++ b/hibernate-core/src/main/java/org/hibernate/HibernateException.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * 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 Middleware LLC.
+ * 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
@@ -20,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
package org.hibernate;
@@ -35,6 +34,9 @@ package org.hibernate;
* @author Gavin King
*/
public class HibernateException extends RuntimeException {
+ public HibernateException(String s) {
+ super(s);
+ }
public HibernateException(Throwable root) {
super(root);
@@ -43,10 +45,6 @@ public class HibernateException extends RuntimeException {
public HibernateException(String string, Throwable root) {
super(string, root);
}
-
- public HibernateException(String s) {
- super(s);
- }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/JRun4TransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/ResourceClosedException.java
similarity index 66%
rename from hibernate-core/src/main/java/org/hibernate/transaction/JRun4TransactionManagerLookup.java
rename to hibernate-core/src/main/java/org/hibernate/ResourceClosedException.java
index 5f0bf15fd0..800d478cf0 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/JRun4TransactionManagerLookup.java
+++ b/hibernate-core/src/main/java/org/hibernate/ResourceClosedException.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * 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 Middleware LLC.
+ * 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
@@ -20,22 +20,20 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
-package org.hibernate.transaction;
+package org.hibernate;
/**
- * {@link TransactionManagerLookup} strategy for JRun4 AS
+ * Indicates an attempt was made to use a closed resource (Session, SessionFactory, etc).
*
- * @author Joseph Bissen
+ * @author Steve Ebersole
*/
-public class JRun4TransactionManagerLookup extends JNDITransactionManagerLookup {
-
- protected String getName() {
- return "java:/TransactionManager";
+public class ResourceClosedException extends HibernateException {
+ public ResourceClosedException(String s) {
+ super( s );
}
- public String getUserTransactionName() {
- return "java:comp/UserTransaction";
+ public ResourceClosedException(String string, Throwable root) {
+ super( string, root );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/SessionFactory.java b/hibernate-core/src/main/java/org/hibernate/SessionFactory.java
index af193fc35e..c097bfb29f 100644
--- a/hibernate-core/src/main/java/org/hibernate/SessionFactory.java
+++ b/hibernate-core/src/main/java/org/hibernate/SessionFactory.java
@@ -119,8 +119,7 @@ public interface SessionFactory extends Referenceable, Serializable {
* for use.
*
* Note that for backwards compatibility, if a {@link org.hibernate.context.CurrentSessionContext}
- * is not configured but a JTA {@link org.hibernate.transaction.TransactionManagerLookup}
- * is configured this will default to the {@link org.hibernate.context.JTASessionContext}
+ * is not configured but JTA is configured this will default to the {@link org.hibernate.context.JTASessionContext}
* impl.
*
* @return The current session.
diff --git a/hibernate-core/src/main/java/org/hibernate/Transaction.java b/hibernate-core/src/main/java/org/hibernate/Transaction.java
index 38635007c1..cbed4ea957 100644
--- a/hibernate-core/src/main/java/org/hibernate/Transaction.java
+++ b/hibernate-core/src/main/java/org/hibernate/Transaction.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * 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 Middleware LLC.
+ * 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
@@ -20,109 +20,140 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
package org.hibernate;
+import org.hibernate.engine.transaction.spi.LocalStatus;
+
import javax.transaction.Synchronization;
/**
- * Allows the application to define units of work, while
- * maintaining abstraction from the underlying transaction
- * implementation (eg. JTA, JDBC).
- *
- * A transaction is associated with a Session and is
- * usually instantiated by a call to Session.beginTransaction().
- * A single session might span multiple transactions since
- * the notion of a session (a conversation between the application
- * and the datastore) is of coarser granularity than the notion of
- * a transaction. However, it is intended that there be at most one
- * uncommitted Transaction associated with a particular
- * Session at any time.
- *
- * Implementors are not intended to be threadsafe.
+ * Defines the contract for abstracting applications from the configured underlying means of transaction management.
+ * Allows the application to define units of work, while maintaining abstraction from the underlying transaction
+ * implementation (eg. JTA, JDBC).
+ *
+ * A transaction is associated with a {@link Session} and is usually initiated by a call to
+ * {@link org.hibernate.Session#beginTransaction()}. A single session might span multiple transactions since
+ * the notion of a session (a conversation between the application and the datastore) is of coarser granularity than
+ * the notion of a transaction. However, it is intended that there be at most one uncommitted transaction associated
+ * with a particular {@link Session} at any time.
+ *
+ * Implementers are not intended to be thread-safe.
*
- * @see Session#beginTransaction()
- * @see org.hibernate.transaction.TransactionFactory
* @author Anton van Straaten
+ * @author Steve Ebersole
*/
public interface Transaction {
-
/**
- * Begin a new transaction.
+ * Is this transaction the initiator of any underlying transaction?
+ *
+ * @return {@literal true} if this transaction initiated the underlying transaction; {@literal false} otherwise.
*/
- public void begin() throws HibernateException;
+ public boolean isInitiator();
/**
- * Flush the associated Session and end the unit of work (unless
- * we are in {@link FlushMode#MANUAL}.
- *
- * This method will commit the underlying transaction if and only
- * if the underlying transaction was initiated by this object.
+ * Begin this transaction. No-op if the transaction has already been begun. Note that this is not necessarily
+ * symmetrical since usually multiple calls to {@link #commit} or {@link #rollback} will error.
*
- * @throws HibernateException
+ * @throws HibernateException Indicates a problem beginning the transaction.
*/
- public void commit() throws HibernateException;
+ public void begin();
/**
- * Force the underlying transaction to roll back.
+ * Commit this transaction. This might entail a number of things depending on the context:
+ * -
+ * If this transaction is the {@link #isInitiator initiator}, {@link Session#flush} the {@link Session}
+ * with which it is associated (unless {@link Session} is in {@link FlushMode#MANUAL}).
+ *
+ * -
+ * If this transaction is the {@link #isInitiator initiator}, commit the underlying transaction.
+ *
+ * -
+ * Coordinate various callbacks
+ *
+ *
*
- * @throws HibernateException
+ * @throws HibernateException Indicates a problem committing the transaction.
*/
- public void rollback() throws HibernateException;
+ public void commit();
+
+ /**
+ * Rollback this transaction. Either rolls back the underlying transaction or ensures it cannot later commit
+ * (depending on the actual underlying strategy).
+ *
+ * @throws HibernateException Indicates a problem rolling back the transaction.
+ */
+ public void rollback();
+
+ /**
+ * Get the current local status of this transaction.
+ *
+ * This only accounts for the local view of the transaction status. In other words it does not check the status
+ * of the actual underlying transaction.
+ *
+ * @return The current local status.
+ */
+ public LocalStatus getLocalStatus();
+
+ /**
+ * Is this transaction still active?
+ *
+ * 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 {@literal true} if the transaction is still active; {@literal false} otherwise.
+ *
+ * @throws HibernateException Indicates a problem checking the transaction status.
+ */
+ public boolean isActive();
+
+ /**
+ * Was this transaction committed?
+ *
+ * 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 {@literal true} if the transaction is rolled back; {@literal false} otherwise.
+ *
+ * @throws HibernateException Indicates a problem checking the transaction status.
+ */
+ public boolean wasCommitted();
/**
* Was this transaction rolled back or set to rollback only?
*
- * This only accounts for actions initiated from this local transaction.
- * If, for example, the underlying transaction is forced to rollback via
- * some other means, this method still reports false because the rollback
- * was not initiated from here.
+ * 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 boolean True if the transaction was rolled back via this
- * local transaction; false otherwise.
- * @throws HibernateException
- */
- public boolean wasRolledBack() throws HibernateException;
-
- /**
- * Check if this transaction was successfully committed.
- *
- * This method could return false even after successful invocation
- * of {@link #commit}. As an example, JTA based strategies no-op on
- * {@link #commit} calls if they did not start the transaction; in that case,
- * they also report {@link #wasCommitted} as false.
+ * @return {@literal true} if the transaction is rolled back; {@literal false} otherwise.
*
- * @return boolean True if the transaction was (unequivocally) committed
- * via this local transaction; false otherwise.
- * @throws HibernateException
+ * @throws HibernateException Indicates a problem checking the transaction status.
*/
- public boolean wasCommitted() throws HibernateException;
-
- /**
- * Is this transaction still active?
- *
- * Again, this only returns information in relation to the
- * local transaction, not the actual underlying transaction.
- *
- * @return boolean Treu if this local transaction is still active.
- */
- public boolean isActive() throws HibernateException;
+ public boolean wasRolledBack();
/**
* Register a user synchronization callback for this transaction.
*
* @param synchronization The Synchronization callback to register.
- * @throws HibernateException
+ *
+ * @throws HibernateException Indicates a problem registering the synchronization.
*/
- public void registerSynchronization(Synchronization synchronization)
- throws HibernateException;
+ public void registerSynchronization(Synchronization synchronization) throws HibernateException;
/**
- * Set the transaction timeout for any transaction started by
- * a subsequent call to begin() on this instance.
+ * Set the transaction timeout for any transaction started by a subsequent call to {@link #begin} on this instance.
*
* @param seconds The number of seconds before a timeout.
*/
public void setTimeout(int seconds);
+
+ /**
+ * Retrieve the transaction timeout set for this transaction. A negative indicates no timeout has been set.
+ *
+ * @return The timeout, in seconds.
+ */
+ public int getTimeout();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java b/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java
index 2e71eab331..ba64ce4900 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java
@@ -1842,7 +1842,7 @@ public class Configuration implements Serializable {
Properties copy = new Properties();
copy.putAll( properties );
ConfigurationHelper.resolvePlaceHolders( copy );
- Settings settings = buildSettings( copy, serviceRegistry.getService( JdbcServices.class ) );
+ Settings settings = buildSettings( copy, serviceRegistry );
return new SessionFactoryImpl(
this,
@@ -2825,18 +2825,18 @@ public class Configuration implements Serializable {
*
* @return The build settings
*/
- public Settings buildSettings(JdbcServices jdbcServices) {
+ public Settings buildSettings(ServiceRegistry serviceRegistry) {
Properties clone = ( Properties ) properties.clone();
ConfigurationHelper.resolvePlaceHolders( clone );
- return buildSettingsInternal( clone, jdbcServices );
+ return buildSettingsInternal( clone, serviceRegistry );
}
- public Settings buildSettings(Properties props, JdbcServices jdbcServices) throws HibernateException {
- return buildSettingsInternal( props, jdbcServices );
+ public Settings buildSettings(Properties props, ServiceRegistry serviceRegistry) throws HibernateException {
+ return buildSettingsInternal( props, serviceRegistry );
}
- private Settings buildSettingsInternal(Properties props, JdbcServices jdbcServices) {
- final Settings settings = settingsFactory.buildSettings( props, jdbcServices );
+ private Settings buildSettingsInternal(Properties props, ServiceRegistry serviceRegistry) {
+ final Settings settings = settingsFactory.buildSettings( props, serviceRegistry );
settings.setEntityTuplizerFactory( this.getEntityTuplizerFactory() );
// settings.setComponentTuplizerFactory( this.getComponentTuplizerFactory() );
return settings;
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Environment.java b/hibernate-core/src/main/java/org/hibernate/cfg/Environment.java
index e2e670501c..51a7628170 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/Environment.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/Environment.java
@@ -164,7 +164,7 @@ import org.hibernate.util.ConfigHelper;
*
* hibernate.transaction.factory_class |
* the factory to use for instantiating Transactions.
- * (Defaults to JDBCTransactionFactory.) |
+ * (Defaults to JdbcTransactionFactory.)
*
*
* hibernate.query.substitutions | query language token substitutions |
@@ -376,7 +376,8 @@ public final class Environment {
*/
public static final String CURRENT_SESSION_CONTEXT_CLASS = "hibernate.current_session_context_class";
/**
- * TransactionFactory implementor to use for creating Transactions
+ * Names the implementation of {@link org.hibernate.engine.transaction.spi.TransactionContext} to use for
+ * creating {@link org.hibernate.Transaction} instances
*/
public static final String TRANSACTION_STRATEGY = "hibernate.transaction.factory_class";
/**
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Settings.java b/hibernate-core/src/main/java/org/hibernate/cfg/Settings.java
index 5e8056a6b5..fbc5e31eac 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/Settings.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/Settings.java
@@ -23,20 +23,18 @@
*/
package org.hibernate.cfg;
-import java.util.Map;
-
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.EntityMode;
import org.hibernate.cache.QueryCacheFactory;
import org.hibernate.cache.RegionFactory;
import org.hibernate.engine.jdbc.JdbcSupport;
-import org.hibernate.engine.jdbc.batch.internal.BatchBuilder;
import org.hibernate.hql.QueryTranslatorFactory;
import org.hibernate.jdbc.util.SQLStatementLogger;
-import org.hibernate.transaction.TransactionFactory;
-import org.hibernate.transaction.TransactionManagerLookup;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
import org.hibernate.tuple.entity.EntityTuplizerFactory;
+import java.util.Map;
+
/**
* Settings that affect the behaviour of Hibernate at runtime.
*
@@ -75,9 +73,6 @@ public final class Settings {
private ConnectionReleaseMode connectionReleaseMode;
private RegionFactory regionFactory;
private QueryCacheFactory queryCacheFactory;
- private TransactionFactory transactionFactory;
- private TransactionManagerLookup transactionManagerLookup;
- private BatchBuilder batchBuilder;
private QueryTranslatorFactory queryTranslatorFactory;
private boolean wrapResultSetsEnabled;
private boolean orderUpdatesEnabled;
@@ -94,6 +89,8 @@ public final class Settings {
private JdbcSupport jdbcSupport;
private String importFiles;
+ private JtaPlatform jtaPlatform;
+
/**
* Package protected constructor
*/
@@ -162,10 +159,6 @@ public final class Settings {
return jdbcFetchSize;
}
- public TransactionFactory getTransactionFactory() {
- return transactionFactory;
- }
-
public String getSessionFactoryName() {
return sessionFactoryName;
}
@@ -190,10 +183,6 @@ public final class Settings {
return regionFactory;
}
- public TransactionManagerLookup getTransactionManagerLookup() {
- return transactionManagerLookup;
- }
-
public boolean isQueryCacheEnabled() {
return queryCacheEnabled;
}
@@ -226,10 +215,6 @@ public final class Settings {
return flushBeforeCompletionEnabled;
}
- public BatchBuilder getBatchBuilder() {
- return batchBuilder;
- }
-
public boolean isAutoCloseSessionEnabled() {
return autoCloseSessionEnabled;
}
@@ -349,10 +334,6 @@ public final class Settings {
jdbcFetchSize = integer;
}
- void setTransactionFactory(TransactionFactory factory) {
- transactionFactory = factory;
- }
-
void setSessionFactoryName(String string) {
sessionFactoryName = string;
}
@@ -377,10 +358,6 @@ public final class Settings {
this.regionFactory = regionFactory;
}
- void setTransactionManagerLookup(TransactionManagerLookup lookup) {
- transactionManagerLookup = lookup;
- }
-
void setQueryCacheEnabled(boolean b) {
queryCacheEnabled = b;
}
@@ -413,10 +390,6 @@ public final class Settings {
this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;
}
- void setBatcherBuilder(BatchBuilder batchBuilder) {
- this.batchBuilder = batchBuilder;
- }
-
void setAutoCloseSessionEnabled(boolean autoCloseSessionEnabled) {
this.autoCloseSessionEnabled = autoCloseSessionEnabled;
}
@@ -496,4 +469,13 @@ public final class Settings {
// void setBytecodeProvider(BytecodeProvider bytecodeProvider) {
// this.bytecodeProvider = bytecodeProvider;
// }
+
+
+ public JtaPlatform getJtaPlatform() {
+ return jtaPlatform;
+ }
+
+ void setJtaPlatform(JtaPlatform jtaPlatform) {
+ this.jtaPlatform = jtaPlatform;
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java b/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java
index ca2a34f396..73801f2b98 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java
@@ -39,16 +39,14 @@ import org.hibernate.cache.QueryCacheFactory;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.impl.NoCachingRegionFactory;
import org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge;
-import org.hibernate.engine.jdbc.batch.internal.BatchBuilder;
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.spi.JdbcServices;
+import org.hibernate.engine.transaction.spi.TransactionFactory;
import org.hibernate.hql.QueryTranslatorFactory;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jdbc.util.SQLStatementLogger;
-import org.hibernate.transaction.TransactionFactory;
-import org.hibernate.transaction.TransactionFactoryFactory;
-import org.hibernate.transaction.TransactionManagerLookup;
-import org.hibernate.transaction.TransactionManagerLookupFactory;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.service.spi.ServiceRegistry;
import org.hibernate.util.ReflectHelper;
import org.hibernate.util.StringHelper;
@@ -66,7 +64,8 @@ public class SettingsFactory implements Serializable {
protected SettingsFactory() {
}
- public Settings buildSettings(Properties props, JdbcServices jdbcServices) {
+ public Settings buildSettings(Properties props, ServiceRegistry serviceRegistry) {
+ final JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
Settings settings = new Settings();
//SessionFactory name:
@@ -90,10 +89,7 @@ public class SettingsFactory implements Serializable {
settings.setJdbcSupport( new JdbcSupport( ! ConfigurationHelper.getBoolean( Environment.NON_CONTEXTUAL_LOB_CREATION, properties ) ) );
// Transaction settings:
-
- TransactionFactory transactionFactory = createTransactionFactory(properties);
- settings.setTransactionFactory(transactionFactory);
- settings.setTransactionManagerLookup( createTransactionManagerLookup(properties) );
+ settings.setJtaPlatform( serviceRegistry.getService( JtaPlatform.class ) );
boolean flushBeforeCompletion = ConfigurationHelper.getBoolean(Environment.FLUSH_BEFORE_COMPLETION, properties);
log.info("Automatic flush during beforeCompletion(): " + enabledDisabled(flushBeforeCompletion) );
@@ -112,7 +108,6 @@ public class SettingsFactory implements Serializable {
boolean jdbcBatchVersionedData = ConfigurationHelper.getBoolean(Environment.BATCH_VERSIONED_DATA, properties, false);
if (batchSize>0) log.info("JDBC batch updates for versioned data: " + enabledDisabled(jdbcBatchVersionedData) );
settings.setJdbcBatchVersionedData(jdbcBatchVersionedData);
- settings.setBatcherBuilder( createBatchBuilder(properties, batchSize) );
boolean useScrollableResultSets = ConfigurationHelper.getBoolean(Environment.USE_SCROLLABLE_RESULTSET, properties, meta.supportsScrollableResults());
log.info("Scrollable result sets: " + enabledDisabled(useScrollableResultSets) );
@@ -134,7 +129,7 @@ public class SettingsFactory implements Serializable {
log.info( "Connection release mode: " + releaseModeName );
ConnectionReleaseMode releaseMode;
if ( "auto".equals(releaseModeName) ) {
- releaseMode = transactionFactory.getDefaultReleaseMode();
+ releaseMode = serviceRegistry.getService( TransactionFactory.class ).getDefaultReleaseMode();
}
else {
releaseMode = ConnectionReleaseMode.parse( releaseModeName );
@@ -301,7 +296,9 @@ public class SettingsFactory implements Serializable {
}
public static RegionFactory createRegionFactory(Properties properties, boolean cachingEnabled) {
- String regionFactoryClassName = ConfigurationHelper.getString( Environment.CACHE_REGION_FACTORY, properties, null );
+ String regionFactoryClassName = ConfigurationHelper.getString(
+ Environment.CACHE_REGION_FACTORY, properties, null
+ );
if ( regionFactoryClassName == null && cachingEnabled ) {
String providerClassName = ConfigurationHelper.getString( Environment.CACHE_PROVIDER, properties, null );
if ( providerClassName != null ) {
@@ -346,33 +343,4 @@ public class SettingsFactory implements Serializable {
}
}
- protected BatchBuilder createBatchBuilder(Properties properties, int batchSize) {
- String batchBuilderClass = properties.getProperty(Environment.BATCH_STRATEGY);
- BatchBuilder batchBuilder;
- if (batchBuilderClass==null) {
- batchBuilder = batchSize > 0
- ? new BatchBuilder( batchSize )
- : new BatchBuilder();
- }
- else {
- log.info("Batch factory: " + batchBuilderClass);
- try {
- batchBuilder = (BatchBuilder) ReflectHelper.classForName(batchBuilderClass).newInstance();
- }
- catch (Exception cnfe) {
- throw new HibernateException("could not instantiate BatchBuilder: " + batchBuilderClass, cnfe);
- }
- }
- batchBuilder.setJdbcBatchSize( batchSize );
- return batchBuilder;
- }
-
- protected TransactionFactory createTransactionFactory(Properties properties) {
- return TransactionFactoryFactory.buildTransactionFactory(properties);
- }
-
- protected TransactionManagerLookup createTransactionManagerLookup(Properties properties) {
- return TransactionManagerLookupFactory.getTransactionManagerLookup(properties);
- }
-
}
diff --git a/hibernate-core/src/main/java/org/hibernate/context/JTASessionContext.java b/hibernate-core/src/main/java/org/hibernate/context/JTASessionContext.java
index 7b7f7fc7e8..058882c5cc 100644
--- a/hibernate-core/src/main/java/org/hibernate/context/JTASessionContext.java
+++ b/hibernate-core/src/main/java/org/hibernate/context/JTASessionContext.java
@@ -28,7 +28,8 @@ import org.hibernate.HibernateException;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.classic.Session;
import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.util.JTAHelper;
+import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -76,7 +77,8 @@ public class JTASessionContext implements CurrentSessionContext {
* {@inheritDoc}
*/
public Session currentSession() throws HibernateException {
- TransactionManager transactionManager = factory.getTransactionManager();
+ final JtaPlatform jtaPlatform = factory.getServiceRegistry().getService( JtaPlatform.class );
+ final TransactionManager transactionManager = jtaPlatform.retrieveTransactionManager();
if ( transactionManager == null ) {
throw new HibernateException( "No TransactionManagerLookup specified" );
}
@@ -87,9 +89,9 @@ public class JTASessionContext implements CurrentSessionContext {
if ( txn == null ) {
throw new HibernateException( "Unable to locate current JTA transaction" );
}
- if ( !JTAHelper.isInProgress( txn.getStatus() ) ) {
+ if ( !JtaStatusHelper.isActive( txn.getStatus() ) ) {
// We could register the session against the transaction even though it is
- // not started, but we'd have no guarentee of ever getting the map
+ // not started, but we'd have no guarantee of ever getting the map
// entries cleaned up (aside from spawning threads).
throw new HibernateException( "Current transaction is not in progress" );
}
@@ -101,9 +103,7 @@ public class JTASessionContext implements CurrentSessionContext {
throw new HibernateException( "Problem locating/validating JTA transaction", t );
}
- final Object txnIdentifier = factory.getSettings().getTransactionManagerLookup() == null
- ? txn
- : factory.getSettings().getTransactionManagerLookup().getTransactionIdentifier( txn );
+ final Object txnIdentifier = jtaPlatform.getTransactionIdentifier( txn );
Session currentSession = ( Session ) currentSessionMap.get( txnIdentifier );
diff --git a/hibernate-core/src/main/java/org/hibernate/context/ThreadLocalSessionContext.java b/hibernate-core/src/main/java/org/hibernate/context/ThreadLocalSessionContext.java
index a0613d8a6f..f3bbe79cd9 100644
--- a/hibernate-core/src/main/java/org/hibernate/context/ThreadLocalSessionContext.java
+++ b/hibernate-core/src/main/java/org/hibernate/context/ThreadLocalSessionContext.java
@@ -43,6 +43,10 @@ import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.jdbc.LobCreationContext;
+import org.hibernate.engine.transaction.spi.TransactionContext;
+import org.hibernate.event.EventSource;
/**
* A {@link CurrentSessionContext} impl which scopes the notion of current
@@ -74,11 +78,11 @@ public class ThreadLocalSessionContext implements CurrentSessionContext {
private static final Logger log = LoggerFactory.getLogger( ThreadLocalSessionContext.class );
private static final Class[] SESSION_PROXY_INTERFACES = new Class[] {
- org.hibernate.classic.Session.class,
- org.hibernate.engine.SessionImplementor.class,
- org.hibernate.engine.jdbc.spi.JDBCContext.Context.class,
- org.hibernate.event.EventSource.class,
- org.hibernate.engine.jdbc.LobCreationContext.class
+ Session.class,
+ SessionImplementor.class,
+ EventSource.class,
+ TransactionContext.class,
+ LobCreationContext.class
};
/**
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java
index 12e7b4c575..d8db93be62 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java
@@ -78,7 +78,7 @@ public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingS
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java
index 9d473ca9b9..19976b0898 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java
@@ -94,7 +94,7 @@ public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
}
SessionFactoryImplementor factory = session.getFactory();
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java
index d7cd8e96c2..a280a88526 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java
@@ -78,7 +78,7 @@ public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLocking
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java
index 47d9af492c..d59c619e24 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java
@@ -94,7 +94,7 @@ public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
}
SessionFactoryImplementor factory = session.getFactory();
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java
index 65e563f76b..dbca19411f 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java
@@ -73,7 +73,7 @@ public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
final String sql = determineSql( timeout );
SessionFactoryImplementor factory = session.getFactory();
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
if ( getLockable().isVersioned() ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java
index a8c7e2b47d..d68b79b0a7 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java
@@ -92,7 +92,7 @@ public class UpdateLockingStrategy implements LockingStrategy {
// todo : should we additionally check the current isolation mode explicitly?
SessionFactoryImplementor factory = session.getFactory();
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
lockable.getVersionType().nullSafeSet( st, version, 1, session );
int offset = 2;
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/ActionQueue.java b/hibernate-core/src/main/java/org/hibernate/engine/ActionQueue.java
index 56b5bcb939..92c8709fa5 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/ActionQueue.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/ActionQueue.java
@@ -265,7 +265,7 @@ public class ActionQueue {
execute( ( Executable ) list.get( i ) );
}
list.clear();
- session.getJDBCContext().getConnectionManager().executeBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().executeBatch();
}
public void execute(Executable executable) {
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/SessionFactoryImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/SessionFactoryImplementor.java
index 4a8eba6789..a72b2aee50 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/SessionFactoryImplementor.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/SessionFactoryImplementor.java
@@ -52,6 +52,7 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.SQLFunctionRegistry;
import org.hibernate.exception.SQLExceptionConverter;
import org.hibernate.id.IdentifierGenerator;
+import org.hibernate.service.spi.ServiceRegistry;
import org.hibernate.stat.StatisticsImplementor;
import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;
@@ -145,13 +146,6 @@ public interface SessionFactoryImplementor extends Mapping, SessionFactory {
*/
public String getImportedClassName(String name);
-
- /**
- * Get the JTA transaction manager
- */
- public TransactionManager getTransactionManager();
-
-
/**
* Get the default query cache
*/
@@ -262,4 +256,5 @@ public interface SessionFactoryImplementor extends Mapping, SessionFactory {
*/
public FetchProfile getFetchProfile(String name);
+ public ServiceRegistry getServiceRegistry();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/SessionImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/SessionImplementor.java
index ca3a585439..a566ce401c 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/SessionImplementor.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/SessionImplementor.java
@@ -39,9 +39,9 @@ import org.hibernate.Query;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Transaction;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
import org.hibernate.collection.PersistentCollection;
+import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.event.EventListeners;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.loader.custom.CustomQuery;
@@ -157,20 +157,6 @@ public interface SessionImplementor extends Serializable {
*/
public Object getEntityUsingInterceptor(EntityKey key) throws HibernateException;
- /**
- * Notify the session that the transaction completed, so we no longer
- * own the old locks. (Also we should release cache softlocks.) May
- * be called multiple times during the transaction completion process.
- * Also called after an autocommit, in which case the second argument
- * is null.
- */
- public void afterTransactionCompletion(boolean successful, Transaction tx);
-
- /**
- * Notify the session that the transaction is about to complete
- */
- public void beforeTransactionCompletion(Transaction tx);
-
/**
* Return the identifier of the persistent object, or null if
* not associated with the session
@@ -340,11 +326,16 @@ public interface SessionImplementor extends Serializable {
*/
public void setFetchProfile(String name);
- public JDBCContext getJDBCContext();
+ /**
+ * Retrieve access to the session's transaction coordinator.
+ *
+ * @return The transaction coordinator.
+ */
+ public TransactionCoordinator getTransactionCoordinator();
/**
- * Determine whether the session is closed. Provided seperately from
- * {@link #isOpen()} as this method does not attempt any JTA synch
+ * Determine whether the session is closed. Provided separately from
+ * {@link #isOpen()} as this method does not attempt any JTA synchronization
* registration, where as {@link #isOpen()} does; which makes this one
* nicer to use for most internal purposes.
*
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/TransactionHelper.java b/hibernate-core/src/main/java/org/hibernate/engine/TransactionHelper.java
index 0c7df45cdc..d820594a9a 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/TransactionHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/TransactionHelper.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2008-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 Middleware LLC.
+ * 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
@@ -20,19 +20,16 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
package org.hibernate.engine;
+import org.hibernate.HibernateException;
+import org.hibernate.jdbc.Work;
+
import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
-import org.hibernate.HibernateException;
-import org.hibernate.engine.transaction.IsolatedWork;
-import org.hibernate.engine.transaction.Isolater;
-import org.hibernate.exception.JDBCExceptionHelper;
-
/**
* Allows work to be done outside the current transaction, by suspending it,
* and performing work in a new transaction
@@ -41,7 +38,7 @@ import org.hibernate.exception.JDBCExceptionHelper;
*/
public abstract class TransactionHelper {
- // todo : remove this and just have subclasses use Isolater/IsolatedWork directly...
+ // todo : remove this and just have subclasses use IsolationDelegate directly...
/**
* The work to be done
@@ -51,26 +48,27 @@ public abstract class TransactionHelper {
/**
* Suspend the current transaction and perform work in a new transaction
*/
- public Serializable doWorkInNewTransaction(final SessionImplementor session)
- throws HibernateException {
- class Work implements IsolatedWork {
+ public Serializable doWorkInNewTransaction(final SessionImplementor session) throws HibernateException {
+ class WorkToDo implements Work {
Serializable generatedValue;
- public void doWork(Connection connection) throws HibernateException {
+
+ @Override
+ public void execute(Connection connection) throws SQLException {
String sql = null;
try {
generatedValue = doWorkInCurrentTransaction( connection, sql );
}
- catch( SQLException sqle ) {
+ catch( SQLException e ) {
throw session.getFactory().getSQLExceptionHelper().convert(
- sqle,
+ e,
"could not get or update next value",
sql
- );
+ );
}
}
}
- Work work = new Work();
- Isolater.doIsolatedWork( work, session );
+ WorkToDo work = new WorkToDo();
+ session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork( work, true );
return work.generatedValue;
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/AbstractBatchImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/AbstractBatchImpl.java
index 5d171f4a38..a0c4bd2b97 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/AbstractBatchImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/AbstractBatchImpl.java
@@ -23,19 +23,20 @@
*/
package org.hibernate.engine.jdbc.batch.internal;
+import org.hibernate.engine.jdbc.batch.spi.Batch;
+import org.hibernate.engine.jdbc.batch.spi.BatchKey;
+import org.hibernate.engine.jdbc.batch.spi.BatchObserver;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
+import org.hibernate.engine.jdbc.spi.SQLStatementLogger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.engine.jdbc.batch.spi.Batch;
-import org.hibernate.engine.jdbc.batch.spi.BatchObserver;
-import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
-import org.hibernate.engine.jdbc.spi.SQLStatementLogger;
-
/**
* Convenience base class for implementors of the Batch interface.
*
@@ -44,21 +45,20 @@ import org.hibernate.engine.jdbc.spi.SQLStatementLogger;
public abstract class AbstractBatchImpl implements Batch {
private static final Logger log = LoggerFactory.getLogger( AbstractBatchImpl.class );
- private final SQLStatementLogger statementLogger;
- private final SQLExceptionHelper exceptionHelper;
- private Object key;
+ private final BatchKey key;
+ private final JdbcCoordinator jdbcCoordinator;
private LinkedHashMap statements = new LinkedHashMap();
private LinkedHashSet observers = new LinkedHashSet();
- protected AbstractBatchImpl(Object key,
- SQLStatementLogger statementLogger,
- SQLExceptionHelper exceptionHelper) {
- if ( key == null || statementLogger == null || exceptionHelper == null ) {
- throw new IllegalArgumentException( "key, statementLogger, and exceptionHelper must be non-null." );
+ protected AbstractBatchImpl(BatchKey key, JdbcCoordinator jdbcCoordinator) {
+ if ( key == null ) {
+ throw new IllegalArgumentException( "batch key cannot be null" );
+ }
+ if ( jdbcCoordinator == null ) {
+ throw new IllegalArgumentException( "JDBC coordinator cannot be null" );
}
this.key = key;
- this.statementLogger = statementLogger;
- this.exceptionHelper = exceptionHelper;
+ this.jdbcCoordinator = jdbcCoordinator;
}
/**
@@ -74,8 +74,12 @@ public abstract class AbstractBatchImpl implements Batch {
*
* @return The underlying SQLException helper.
*/
- protected SQLExceptionHelper getSqlExceptionHelper() {
- return exceptionHelper;
+ protected SQLExceptionHelper sqlExceptionHelper() {
+ return jdbcCoordinator.getTransactionCoordinator()
+ .getTransactionContext()
+ .getTransactionEnvironment()
+ .getJdbcServices()
+ .getSqlExceptionHelper();
}
/**
@@ -83,8 +87,12 @@ public abstract class AbstractBatchImpl implements Batch {
*
* @return The underlying JDBC services.
*/
- protected SQLStatementLogger getSqlStatementLogger() {
- return statementLogger;
+ protected SQLStatementLogger sqlStatementLogger() {
+ return jdbcCoordinator.getTransactionCoordinator()
+ .getTransactionContext()
+ .getTransactionEnvironment()
+ .getJdbcServices()
+ .getSqlStatementLogger();
}
/**
@@ -96,62 +104,49 @@ public abstract class AbstractBatchImpl implements Batch {
return statements;
}
- /**
- * {@inheritDoc}
- */
- public final Object getKey() {
+ @Override
+ public final BatchKey getKey() {
return key;
}
- /**
- * {@inheritDoc}
- */
+ @Override
public void addObserver(BatchObserver observer) {
observers.add( observer );
}
- /**
- * {@inheritDoc}
- */
- public final PreparedStatement getBatchStatement(Object key, String sql) {
- checkConsistentBatchKey( key );
+ @Override
+ public PreparedStatement getBatchStatement(String sql, boolean callable) {
if ( sql == null ) {
throw new IllegalArgumentException( "sql must be non-null." );
}
PreparedStatement statement = statements.get( sql );
- if ( statement != null ) {
- log.debug( "reusing prepared statement" );
- statementLogger.logStatement( sql );
- }
+ if ( statement == null ) {
+ statement = buildBatchStatement( sql, callable );
+ statements.put( sql, statement );
+ }
+ else {
+ log.debug( "reusing batch statement" );
+ sqlStatementLogger().logStatement( sql );
+ }
return statement;
}
- /**
- * {@inheritDoc}
- */
- // TODO: should this be final???
+ private PreparedStatement buildBatchStatement(String sql, boolean callable) {
+ try {
+ if ( callable ) {
+ return jdbcCoordinator.getLogicalConnection().getShareableConnectionProxy().prepareCall( sql );
+ }
+ else {
+ return jdbcCoordinator.getLogicalConnection().getShareableConnectionProxy().prepareStatement( sql );
+ }
+ }
+ catch ( SQLException sqle ) {
+ log.error( "sqlexception escaped proxy", sqle );
+ throw sqlExceptionHelper().convert( sqle, "could not prepare batch statement", sql );
+ }
+ }
+
@Override
- public void addBatchStatement(Object key, String sql, PreparedStatement preparedStatement) {
- checkConsistentBatchKey( key );
- if ( sql == null ) {
- throw new IllegalArgumentException( "sql must be non-null." );
- }
- if ( statements.put( sql, preparedStatement ) != null ) {
- log.error( "PreparedStatement was already in the batch, [" + sql + "]." );
- }
- }
-
- protected void checkConsistentBatchKey(Object key) {
- if ( ! this.key.equals( key ) ) {
- throw new IllegalStateException(
- "specified key ["+ key + "] is different from internal batch key [" + this.key + "]."
- );
- }
- }
-
- /**
- * {@inheritDoc}
- */
public final void execute() {
notifyObserversExplicitExecution();
if ( statements.isEmpty() ) {
@@ -162,7 +157,7 @@ public abstract class AbstractBatchImpl implements Batch {
doExecuteBatch();
}
finally {
- release();
+ releaseStatements();
}
}
finally {
@@ -176,14 +171,16 @@ public abstract class AbstractBatchImpl implements Batch {
statement.close();
}
catch ( SQLException e ) {
- log.error( "unable to release batch statement..." );
- log.error( "sqlexception escaped proxy", e );
+ log.error( "unable to release batch statement; sqlexception escaped proxy", e );
}
}
getStatements().clear();
}
- private void notifyObserversExplicitExecution() {
+ /**
+ * Convenience method to notify registered observers of an explicit execution of this batch.
+ */
+ protected final void notifyObserversExplicitExecution() {
for ( BatchObserver observer : observers ) {
observer.batchExplicitlyExecuted();
}
@@ -192,12 +189,13 @@ public abstract class AbstractBatchImpl implements Batch {
/**
* Convenience method to notify registered observers of an implicit execution of this batch.
*/
- protected void notifyObserversImplicitExecution() {
+ protected final void notifyObserversImplicitExecution() {
for ( BatchObserver observer : observers ) {
observer.batchImplicitlyExecuted();
}
}
+ @Override
public void release() {
if ( getStatements() != null && !getStatements().isEmpty() ) {
log.info( "On release of batch it still contained JDBC statements" );
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BasicBatchKey.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BasicBatchKey.java
new file mode 100644
index 0000000000..0cff7e330a
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BasicBatchKey.java
@@ -0,0 +1,89 @@
+/*
+ * 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.jdbc.batch.internal;
+
+import org.hibernate.engine.jdbc.batch.spi.BatchKey;
+import org.hibernate.jdbc.Expectation;
+
+/**
+ * @author Steve Ebersole
+ */
+public class BasicBatchKey implements BatchKey {
+ private final String comparison;
+ private final int statementCount;
+ private final Expectation expectation;
+
+// public BasicBatchKey(String comparison, int statementCount, Expectation expectation) {
+// this.comparison = comparison;
+// this.statementCount = statementCount;
+// this.expectations = new Expectation[statementCount];
+// Arrays.fill( this.expectations, expectation );
+// }
+//
+// public BasicBatchKey(String comparison, Expectation... expectations) {
+// this.comparison = comparison;
+// this.statementCount = expectations.length;
+// this.expectations = expectations;
+// }
+
+ public BasicBatchKey(String comparison, Expectation expectation) {
+ this.comparison = comparison;
+ this.statementCount = 1;
+ this.expectation = expectation;
+ }
+
+ @Override
+ public Expectation getExpectation() {
+ return expectation;
+ }
+
+ @Override
+ public int getBatchedStatementCount() {
+ return statementCount;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ BasicBatchKey that = (BasicBatchKey) o;
+
+ if ( !comparison.equals( that.comparison ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return comparison.hashCode();
+ }
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchBuilder.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchBuilderImpl.java
similarity index 59%
rename from hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchBuilder.java
rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchBuilderImpl.java
index e01a7047b3..71157a798f 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchBuilder.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchBuilderImpl.java
@@ -23,28 +23,37 @@
*/
package org.hibernate.engine.jdbc.batch.internal;
+import org.hibernate.cfg.Environment;
+import org.hibernate.engine.jdbc.batch.spi.Batch;
+import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
+import org.hibernate.engine.jdbc.batch.spi.BatchKey;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.internal.util.config.ConfigurationHelper;
+import org.hibernate.service.spi.Configurable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.hibernate.engine.jdbc.batch.spi.Batch;
-import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
-import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
-import org.hibernate.engine.jdbc.spi.SQLStatementLogger;
+import java.util.Map;
/**
* A builder for {@link Batch} instances.
*
* @author Steve Ebersole
*/
-public class BatchBuilder {
- private static final Logger log = LoggerFactory.getLogger( BatchBuilder.class );
+public class BatchBuilderImpl implements BatchBuilder, Configurable {
+ private static final Logger log = LoggerFactory.getLogger( BatchBuilderImpl.class );
private int size;
- public BatchBuilder() {
+ public BatchBuilderImpl() {
}
- public BatchBuilder(int size) {
+ @Override
+ public void configure(Map configurationValues) {
+ size = ConfigurationHelper.getInt( Environment.STATEMENT_BATCH_SIZE, configurationValues, size );
+ }
+
+ public BatchBuilderImpl(int size) {
this.size = size;
}
@@ -52,13 +61,27 @@ public class BatchBuilder {
this.size = size;
}
- public Batch buildBatch(Object key,
- SQLStatementLogger statementLogger,
- SQLExceptionHelper exceptionHelper) {
+ @Override
+ public Batch buildBatch(BatchKey key, JdbcCoordinator jdbcCoordinator) {
log.trace( "building batch [size={}]", size );
return size > 1
- ? new BatchingBatch( key, statementLogger, exceptionHelper, size )
- : new NonBatchingBatch( key, statementLogger, exceptionHelper );
+ ? new BatchingBatch( key, jdbcCoordinator, size )
+ : new NonBatchingBatch( key, jdbcCoordinator );
+ }
+
+ @Override
+ public String getManagementDomain() {
+ return null; // use Hibernate default domain
+ }
+
+ @Override
+ public String getManagementServiceType() {
+ return null; // use Hibernate default scheme
+ }
+
+ @Override
+ public Object getManagementBean() {
+ return this;
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchBuilderInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchBuilderInitiator.java
new file mode 100644
index 0000000000..26b5c4f3bd
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchBuilderInitiator.java
@@ -0,0 +1,69 @@
+/*
+ * 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.jdbc.batch.internal;
+
+import org.hibernate.cfg.Environment;
+import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
+import org.hibernate.internal.util.config.ConfigurationHelper;
+import org.hibernate.service.classloading.spi.ClassLoaderService;
+import org.hibernate.service.spi.ServiceException;
+import org.hibernate.service.spi.ServiceInitiator;
+import org.hibernate.service.spi.ServiceRegistry;
+
+import java.util.Map;
+
+/**
+ * @author Steve Ebersole
+ */
+public class BatchBuilderInitiator implements ServiceInitiator {
+ public static final BatchBuilderInitiator INSTANCE = new BatchBuilderInitiator();
+ public static final String BUILDER = "hibernate.jdbc.batch.builder";
+
+ @Override
+ public Class getServiceInitiated() {
+ return BatchBuilder.class;
+ }
+
+ @Override
+ public BatchBuilder initiateService(Map configurationValues, ServiceRegistry registry) {
+ final Object builder = configurationValues.get( BUILDER );
+ if ( builder == null ) {
+ return new BatchBuilderImpl(
+ ConfigurationHelper.getInt( Environment.STATEMENT_BATCH_SIZE, configurationValues, 1 )
+ );
+ }
+
+ if ( BatchBuilder.class.isInstance( builder ) ) {
+ return (BatchBuilder) builder;
+ }
+
+ final String builderClassName = builder.toString();
+ try {
+ return (BatchBuilder) registry.getService( ClassLoaderService.class ).classForName( builderClassName ).newInstance();
+ }
+ catch (Exception e) {
+ throw new ServiceException( "Could not build explicit BatchBuilder [" + builderClassName + "]", e );
+ }
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchingBatch.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchingBatch.java
index 9dc1b27020..1b91a78b0a 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchingBatch.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchingBatch.java
@@ -23,173 +23,116 @@
*/
package org.hibernate.engine.jdbc.batch.internal;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
+import org.hibernate.HibernateException;
+import org.hibernate.engine.jdbc.batch.spi.BatchKey;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.hibernate.AssertionFailure;
-import org.hibernate.HibernateException;
-import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
-import org.hibernate.engine.jdbc.spi.SQLStatementLogger;
-import org.hibernate.jdbc.Expectation;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Map;
/**
- * A {@link org.hibernate.engine.jdbc.batch.spi.Batch} implementation which does
- * batching based on a given size. Once the batch size is reached for a statement
- * in the batch, the entire batch is implicitly executed.
+ * A {@link org.hibernate.engine.jdbc.batch.spi.Batch} implementation which does bathing based on a given size. Once
+ * the batch size is reached for a statement in the batch, the entire batch is implicitly executed.
*
* @author Steve Ebersole
*/
public class BatchingBatch extends AbstractBatchImpl {
private static final Logger log = LoggerFactory.getLogger( BatchingBatch.class );
+ // IMPL NOTE : Until HHH-5797 is fixed, there will only be 1 statement in a batch
+
private final int batchSize;
+ private int batchPosition;
+ private int statementPosition;
- // TODO: A Map is used for expectations so it is possible to track when a batch
- // is full (i.e., when the batch for a particular statement exceeds batchSize)
- // Until HHH-5797 is fixed, there will only be 1 statement in a batch, so it won't
- // be necessary to track expectations by statement.
- private Map> expectationsBySql;
- private int maxBatchPosition;
-
- public BatchingBatch(Object key,
- SQLStatementLogger statementLogger,
- SQLExceptionHelper exceptionHelper,
- int batchSize) {
- super( key, statementLogger, exceptionHelper );
- this.batchSize = batchSize;
- this.expectationsBySql = new HashMap>();
- }
-
- /**
- * {@inheritDoc}
- */
- public void addToBatch(Object key, String sql, Expectation expectation) {
- checkConsistentBatchKey( key );
- if ( sql == null || expectation == null ) {
- throw new AssertionFailure( "sql or expection was null." );
- }
- if ( ! expectation.canBeBatched() ) {
+ public BatchingBatch(
+ BatchKey key,
+ JdbcCoordinator jdbcCoordinator,
+ int batchSize) {
+ super( key, jdbcCoordinator );
+ if ( ! key.getExpectation().canBeBatched() ) {
throw new HibernateException( "attempting to batch an operation which cannot be batched" );
}
- final PreparedStatement statement = getStatements().get( sql );
+ this.batchSize = batchSize;
+ }
+
+ private String currentStatementSql;
+ private PreparedStatement currentStatement;
+
+ @Override
+ public PreparedStatement getBatchStatement(String sql, boolean callable) {
+ currentStatementSql = sql;
+ currentStatement = super.getBatchStatement( sql, callable );
+ return currentStatement;
+ }
+
+ @Override
+ public void addToBatch() {
try {
- statement.addBatch();
+ currentStatement.addBatch();
}
catch ( SQLException e ) {
- log.error( "sqlexception escaped proxy", e );
- throw getSqlExceptionHelper().convert( e, "could not perform addBatch", sql );
+ log.debug( "sqlexception escaped proxy", e );
+ throw sqlExceptionHelper().convert( e, "could not perform addBatch", currentStatementSql );
}
- List expectations = expectationsBySql.get( sql );
- if ( expectations == null ) {
- expectations = new ArrayList( batchSize );
- expectationsBySql.put( sql, expectations );
- }
- expectations.add( expectation );
- maxBatchPosition = Math.max( maxBatchPosition, expectations.size() );
-
- // TODO: When HHH-5797 is fixed the following if-block should probably be moved before
- // adding the batch to the current statement (to detect that we have finished
- // with the previous entity).
- if ( maxBatchPosition == batchSize ) {
- notifyObserversImplicitExecution();
- doExecuteBatch();
+ statementPosition++;
+ if ( statementPosition >= getKey().getBatchedStatementCount() ) {
+ batchPosition++;
+ if ( batchPosition == batchSize ) {
+ notifyObserversImplicitExecution();
+ performExecution();
+ batchPosition = 0;
+ }
+ statementPosition = 0;
}
}
- /**
- * {@inheritDoc}
- */
+ @Override
protected void doExecuteBatch() {
- if ( maxBatchPosition == 0 ) {
+ if ( batchPosition == 0 ) {
log.debug( "no batched statements to execute" );
}
else {
if ( log.isDebugEnabled() ) {
- log.debug( "Executing {} statements with maximum batch size {} ",
- getStatements().size(), maxBatchPosition
- );
- }
- try {
- executeStatements();
- }
- catch ( RuntimeException re ) {
- log.error( "Exception executing batch [{}]", re.getMessage() );
- throw re;
- }
- finally {
- for ( List expectations : expectationsBySql.values() ) {
- expectations.clear();
- }
- maxBatchPosition = 0;
+ log.debug( "Executing batch size: " + batchPosition );
}
+ performExecution();
}
}
- private void executeStatements() {
- for ( Map.Entry entry : getStatements().entrySet() ) {
- final String sql = entry.getKey();
- final PreparedStatement statement = entry.getValue();
- final List expectations = expectationsBySql.get( sql );
- if ( batchSize < expectations.size() ) {
- throw new IllegalStateException(
- "Number of expectations [" + expectations.size() +
- "] is greater than batch size [" + batchSize +
- "] for statement [" + sql +
- "]"
- );
- }
- if ( expectations.size() > 0 ) {
- if ( log.isDebugEnabled() ) {
- log.debug( "Executing with batch of size {}: {}", expectations.size(), sql );
- }
- executeStatement( sql, statement, expectations );
- expectations.clear();
- }
- else {
- if ( log.isDebugEnabled() ) {
- log.debug( "Skipped executing because batch size is 0: ", sql );
- }
- }
- }
- }
-
- private void executeStatement(String sql, PreparedStatement ps, List expectations) {
+ private void performExecution() {
try {
- checkRowCounts( sql, ps.executeBatch(), ps, expectations );
+ for ( Map.Entry entry : getStatements().entrySet() ) {
+ try {
+ final PreparedStatement statement = entry.getValue();
+ checkRowCounts( statement.executeBatch(), statement );
+ }
+ catch ( SQLException e ) {
+ log.debug( "sqlexception escaped proxy", e );
+ throw sqlExceptionHelper().convert( e, "could not perform addBatch", entry.getKey() );
+ }
+ }
}
- catch ( SQLException e ) {
- log.error( "sqlexception escaped proxy", e );
- throw getSqlExceptionHelper()
- .convert( e, "could not execute statement: " + sql );
+ catch ( RuntimeException re ) {
+ log.error( "Exception executing batch [{}]", re.getMessage() );
+ throw re;
+ }
+ finally {
+ batchPosition = 0;
}
}
- private void checkRowCounts(String sql, int[] rowCounts, PreparedStatement ps, List expectations) {
+ private void checkRowCounts(int[] rowCounts, PreparedStatement ps) throws SQLException, HibernateException {
int numberOfRowCounts = rowCounts.length;
- if ( numberOfRowCounts != expectations.size() ) {
+ if ( numberOfRowCounts != batchPosition ) {
log.warn( "JDBC driver did not return the expected number of row counts" );
}
- try {
- for ( int i = 0; i < numberOfRowCounts; i++ ) {
- expectations.get( i ).verifyOutcome( rowCounts[i], ps, i );
- }
- }
- catch ( SQLException e ) {
- log.error( "sqlexception escaped proxy", e );
- throw getSqlExceptionHelper()
- .convert( e, "row count verification failed for statement: ", sql );
+ for ( int i = 0; i < numberOfRowCounts; i++ ) {
+ getKey().getExpectation().verifyOutcome( rowCounts[i], ps, i );
}
}
- public void release() {
- expectationsBySql.clear();
- maxBatchPosition = 0;
- }
}
\ No newline at end of file
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/NonBatchingBatch.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/NonBatchingBatch.java
index 64eb6b116a..9b2e280096 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/NonBatchingBatch.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/NonBatchingBatch.java
@@ -23,48 +23,52 @@
*/
package org.hibernate.engine.jdbc.batch.internal;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-
+import org.hibernate.engine.jdbc.batch.spi.BatchKey;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
-import org.hibernate.engine.jdbc.spi.SQLStatementLogger;
-import org.hibernate.jdbc.Expectation;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Map;
/**
- * An implementation of {@link org.hibernate.engine.jdbc.batch.spi.Batch} which does not perform batching. It simply executes each statement as it is
- * encountered.
+ * An implementation of {@link org.hibernate.engine.jdbc.batch.spi.Batch} which does not perform batching. It simply
+ * executes each statement as it is encountered.
*
* @author Steve Ebersole
*/
public class NonBatchingBatch extends AbstractBatchImpl {
private static final Logger log = LoggerFactory.getLogger( NonBatchingBatch.class );
- protected NonBatchingBatch(Object key,
- SQLStatementLogger statementLogger,
- SQLExceptionHelper exceptionHelper) {
- super( key, statementLogger, exceptionHelper );
+ protected NonBatchingBatch(BatchKey key, JdbcCoordinator jdbcCoordinator) {
+ super( key, jdbcCoordinator );
}
- public void addToBatch(Object key, String sql, Expectation expectation) {
- checkConsistentBatchKey( key );
- if ( sql == null ) {
- throw new IllegalArgumentException( "sql must be non-null." );
- }
+ @Override
+ public void addToBatch() {
notifyObserversImplicitExecution();
- try {
- final PreparedStatement statement = getStatements().get( sql );
- final int rowCount = statement.executeUpdate();
- expectation.verifyOutcome( rowCount, statement, 0 );
- }
- catch ( SQLException e ) {
- log.error( "sqlexception escaped proxy", e );
- throw getSqlExceptionHelper().convert( e, "could not execute batch statement", sql );
+ for ( Map.Entry entry : getStatements().entrySet() ) {
+ try {
+ final PreparedStatement statement = entry.getValue();
+ final int rowCount = statement.executeUpdate();
+ getKey().getExpectation().verifyOutcome( rowCount, statement, 0 );
+ try {
+ statement.close();
+ }
+ catch (SQLException e) {
+ log.debug( "Unable to close non-batched batch statement", e );
+ }
+ }
+ catch ( SQLException e ) {
+ log.debug( "sqlexception escaped proxy", e );
+ throw sqlExceptionHelper().convert( e, "could not execute batch statement", entry.getKey() );
+ }
}
+ getStatements().clear();
}
+ @Override
protected void doExecuteBatch() {
// nothing to do
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/spi/Batch.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/spi/Batch.java
index 7c99332100..3a3ee658bb 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/spi/Batch.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/spi/Batch.java
@@ -42,7 +42,7 @@ public interface Batch {
*
* @return The batch key.
*/
- public Object getKey();
+ public BatchKey getKey();
/**
* Adds an observer to this batch.
@@ -52,30 +52,19 @@ public interface Batch {
public void addObserver(BatchObserver observer);
/**
- * Get a statement which is part of the batch.
+ * Get a statement which is part of the batch, creating if necessary (and storing for next time).
*
* @param sql The SQL statement.
- * @return the prepared statement representing the SQL statement, if the batch contained it;
- * null, otherwise.
- */
- public PreparedStatement getBatchStatement(Object key, String sql);
-
- /**
- * Add a prepared statement to the batch.
+ * @param callable Is the SQL statement callable?
*
- * @param sql The SQL statement.
+ * @return The prepared statement instance, representing the SQL statement.
*/
- public void addBatchStatement(Object key, String sql, PreparedStatement preparedStatement);
-
+ public PreparedStatement getBatchStatement(String sql, boolean callable);
/**
* Indicates completion of the current part of the batch.
- *
- * @param key
- * @param sql
- * @param expectation The expectation for the part's result.
*/
- public void addToBatch(Object key, String sql, Expectation expectation);
+ public void addToBatch();
/**
* Execute this batch.
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/spi/BatchBuilder.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/spi/BatchBuilder.java
new file mode 100644
index 0000000000..4715c13faa
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/spi/BatchBuilder.java
@@ -0,0 +1,45 @@
+/*
+ * 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.jdbc.batch.spi;
+
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.service.spi.Manageable;
+import org.hibernate.service.spi.Service;
+
+/**
+ * A builder for {@link Batch} instances
+ *
+ * @author Steve Ebersole
+ */
+public interface BatchBuilder extends Service, Manageable {
+ /**
+ * Build a batch.
+ *
+ * @param key Value to uniquely identify a batch
+ * @param jdbcCoordinator The JDBC coordinator with which to coordinate efforts
+ *
+ * @return The built batch
+ */
+ public Batch buildBatch(BatchKey key, JdbcCoordinator jdbcCoordinator);
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/ResinTransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/spi/BatchKey.java
similarity index 59%
rename from hibernate-core/src/main/java/org/hibernate/transaction/ResinTransactionManagerLookup.java
rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/spi/BatchKey.java
index c1c157c761..86e8338cc0 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/ResinTransactionManagerLookup.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/spi/BatchKey.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * 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 Middleware LLC.
+ * 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
@@ -20,29 +20,30 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
-package org.hibernate.transaction;
+package org.hibernate.engine.jdbc.batch.spi;
+
+import org.hibernate.jdbc.Expectation;
/**
- * {@link TransactionManagerLookup} strategy for Resin
+ * Unique key for batch identification.
*
- * @author Aapo Laakkonen
+ * @author Steve Ebersole
*/
-public class ResinTransactionManagerLookup extends JNDITransactionManagerLookup {
+public interface BatchKey {
+ /**
+ * How many statements will be in this batch?
+ *
+ * Note that this is distinctly different than the size of the batch.
+ *
+ * @return The number of statements.
+ */
+ public int getBatchedStatementCount();
/**
- * {@inheritDoc}
+ * Get the expectation pertaining to the outcome of the {@link Batch} associated with this key.
+ *
+ * @return The expectations
*/
- protected String getName() {
- return "java:comp/TransactionManager";
- }
-
- /**
- * {@inheritDoc}
- */
- public String getUserTransactionName() {
- return "java:comp/UserTransaction";
- }
-
+ public Expectation getExpectation();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/ConnectionManagerImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/ConnectionManagerImpl.java
deleted file mode 100644
index dddaa20eca..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/ConnectionManagerImpl.java
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.CallableStatement;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.AssertionFailure;
-import org.hibernate.ConnectionReleaseMode;
-import org.hibernate.HibernateException;
-import org.hibernate.Interceptor;
-import org.hibernate.ScrollMode;
-import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.engine.jdbc.batch.internal.BatchBuilder;
-import org.hibernate.engine.jdbc.batch.spi.Batch;
-import org.hibernate.engine.jdbc.spi.ConnectionManager;
-import org.hibernate.engine.jdbc.spi.ConnectionObserver;
-import org.hibernate.jdbc.Expectation;
-
-/**
- * Encapsulates JDBC Connection management logic needed by Hibernate.
- *
- * The lifecycle is intended to span a logical series of interactions with the
- * database. Internally, this means the the lifecycle of the Session.
- *
- * @author Steve Ebersole
- */
-public class ConnectionManagerImpl implements ConnectionManager {
-
- private static final Logger log = LoggerFactory.getLogger( ConnectionManagerImpl.class );
-
- public static interface Callback extends ConnectionObserver {
- public boolean isTransactionInProgress();
- }
-
- // TODO: check if it's ok to change the method names in Callback
-
- private transient Interceptor interceptor;
-
- private final Callback callback;
- private transient LogicalConnectionImpl logicalConnection;
- private transient StatementPreparer statementPreparer;
- private final transient BatchBuilder batchBuilder;
- private Batch batch;
-
- /**
- * Constructs a ConnectionManager.
- *
- * This is the form used internally.
- *
- * @param callback An observer for internal state change.
- * @param releaseMode The mode by which to release JDBC connections.
- * @param suppliedConnection An externally supplied connection.
- */
- public ConnectionManagerImpl(
- SessionFactoryImplementor factory,
- Callback callback,
- ConnectionReleaseMode releaseMode,
- Connection suppliedConnection,
- Interceptor interceptor) {
- this( factory,
- callback,
- interceptor,
- new LogicalConnectionImpl(
- suppliedConnection,
- releaseMode,
- factory.getJdbcServices(),
- factory.getStatistics() != null ? factory.getStatisticsImplementor() : null
- )
- );
- }
-
- /**
- * Private constructor used exclusively from custom serialization
- */
- private ConnectionManagerImpl(
- SessionFactoryImplementor factory,
- Callback callback,
- Interceptor interceptor,
- LogicalConnectionImpl logicalConnection
- ) {
- this.callback = callback;
- this.interceptor = interceptor;
- this.logicalConnection = logicalConnection;
- this.logicalConnection.addObserver( callback );
- this.statementPreparer = new StatementPreparer( logicalConnection, factory.getSettings() );
- this.batchBuilder = factory.getSettings().getBatchBuilder();
- }
-
- /**
- * Retrieves the connection currently managed by this ConnectionManager.
- *
- * Note, that we may need to obtain a connection to return here if a
- * connection has either not yet been obtained (non-UserSuppliedConnectionProvider)
- * or has previously been aggressively released (if supported in this environment).
- *
- * @return The current Connection.
- *
- * @throws HibernateException Indicates a connection is currently not
- * available (we are currently manually disconnected).
- */
- @Override
- public Connection getConnection() throws HibernateException {
- return logicalConnection.getConnection();
- }
-
- @Override
- public boolean hasBorrowedConnection() {
- // used from testsuite
- return logicalConnection.hasBorrowedConnection();
- }
-
- public Connection borrowConnection() {
- return logicalConnection.borrowConnection();
- }
-
- @Override
- public void releaseBorrowedConnection() {
- logicalConnection.releaseBorrowedConnection();
- }
-
- /**
- * Is the connection considered "auto-commit"?
- *
- * @return True if we either do not have a connection, or the connection
- * really is in auto-commit mode.
- *
- * @throws SQLException Can be thrown by the Connection.isAutoCommit() check.
- */
- public boolean isAutoCommit() throws SQLException {
- return logicalConnection == null ||
- ! logicalConnection.isOpen() ||
- ! logicalConnection.isPhysicallyConnected() ||
- logicalConnection.getConnection().getAutoCommit();
- }
-
- /**
- * Will connections be released after each statement execution?
- *
- * Connections will be released after each statement if either:
- * - the defined release-mode is {@link ConnectionReleaseMode#AFTER_STATEMENT}; or
- *
- the defined release-mode is {@link ConnectionReleaseMode#AFTER_TRANSACTION} but
- * we are in auto-commit mode.
- *
- * release-mode = {@link ConnectionReleaseMode#ON_CLOSE} should [b]never[/b] release
- * a connection.
- *
- * @return True if the connections will be released after each statement; false otherwise.
- */
- public boolean isAggressiveRelease() {
- if ( logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_STATEMENT ) {
- return true;
- }
- else if ( logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION ) {
- boolean inAutoCommitState;
- try {
- inAutoCommitState = isAutoCommit() && ! callback.isTransactionInProgress();
- }
- catch( SQLException e ) {
- // assume we are in an auto-commit state
- inAutoCommitState = true;
- }
- return inAutoCommitState;
- }
- return false;
- }
-
- /**
- * Modified version of {@link #isAggressiveRelease} which does not force a
- * transaction check. This is solely used from our {@link #afterTransaction}
- * callback, so no need to do the check; plus it seems to cause problems on
- * websphere (god i love websphere ;)
- *
- * It uses this information to decide if an aggressive release was skipped
- * do to open resources, and if so forces a release.
- *
- * @return True if the connections will be released after each statement; false otherwise.
- */
- private boolean isAggressiveReleaseNoTransactionCheck() {
- if ( logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_STATEMENT ) {
- return true;
- }
- else {
- boolean inAutoCommitState;
- try {
- inAutoCommitState = isAutoCommit();
- }
- catch( SQLException e ) {
- // assume we are in an auto-commit state
- inAutoCommitState = true;
- }
- return logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION && inAutoCommitState;
- }
- }
-
- /**
- * Is this ConnectionManager instance "logically" connected. Meaning
- * do we either have a cached connection available or do we have the
- * ability to obtain a connection on demand.
- *
- * @return True if logically connected; false otherwise.
- */
- @Override
- public boolean isCurrentlyConnected() {
- return logicalConnection != null && logicalConnection.isLogicallyConnected();
- }
-
- /**
- * To be called after execution of each JDBC statement. Used to
- * conditionally release the JDBC connection aggressively if
- * the configured release mode indicates.
- */
- @Override
- public void afterStatement() {
- if ( isAggressiveRelease() ) {
- logicalConnection.afterStatementExecution();
- }
- }
-
- /**
- * To be called after local transaction completion. Used to conditionally
- * release the JDBC connection aggressively if the configured release mode
- * indicates.
- */
- public void afterTransaction() {
- if ( logicalConnection != null ) {
- if ( isAfterTransactionRelease() || isAggressiveReleaseNoTransactionCheck() ) {
- logicalConnection.afterTransaction();
- }
- else if ( isOnCloseRelease() ) {
- // log a message about potential connection leaks
- log.debug( "transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!" );
- }
- }
- if ( statementPreparer != null ) {
- statementPreparer.unsetTransactionTimeout();
- }
- }
-
- private boolean isAfterTransactionRelease() {
- return logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION;
- }
-
- private boolean isOnCloseRelease() {
- return logicalConnection.getConnectionReleaseMode() == ConnectionReleaseMode.ON_CLOSE;
- }
-
- private boolean isLogicallyConnected() {
- return logicalConnection != null && logicalConnection.isOpen();
- }
-
- @Override
- public void setTransactionTimeout(int seconds) {
- statementPreparer.setTransactionTimeout( seconds );
- }
-
- /**
- * To be called after Session completion. Used to release the JDBC
- * connection.
- *
- * @return The connection mantained here at time of close. Null if
- * there was no connection cached internally.
- */
- @Override
- public Connection close() {
- return cleanup();
- }
-
- /**
- * Manually disconnect the underlying JDBC Connection. The assumption here
- * is that the manager will be reconnected at a later point in time.
- *
- * @return The connection mantained here at time of disconnect. Null if
- * there was no connection cached internally.
- */
- @Override
- public Connection manualDisconnect() {
- if ( ! isLogicallyConnected() ) {
- throw new IllegalStateException( "cannot manually disconnect because not logically connected." );
- }
- releaseBatch();
- return logicalConnection.manualDisconnect();
- }
-
- /**
- * Manually reconnect the underlying JDBC Connection. Should be called at
- * some point after manualDisconnect().
- *
- * This form is used for ConnectionProvider-supplied connections.
- */
- @Override
- public void manualReconnect() {
- manualReconnect( null );
- }
-
- /**
- * Manually reconnect the underlying JDBC Connection. Should be called at
- * some point after manualDisconnect().
- *
- * This form is used for user-supplied connections.
- */
- @Override
- public void manualReconnect(Connection suppliedConnection) {
- if ( ! isLogicallyConnected() ) {
- throw new IllegalStateException( "cannot manually disconnect because not logically connected." );
- }
- logicalConnection.reconnect( suppliedConnection );
- }
-
- /**
- * Releases the Connection and cleans up any resources associated with
- * that Connection. This is intended for use:
- * 1) at the end of the session
- * 2) on a manual disconnect of the session
- * 3) from afterTransaction(), in the case of skipped aggressive releasing
- *
- * @return The released connection.
- * @throws HibernateException
- */
- private Connection cleanup() throws HibernateException {
- if ( logicalConnection == null ) {
- log.trace( "connection already null in cleanup : no action");
- return null;
- }
- try {
- log.trace( "performing cleanup" );
- releaseBatch();
- statementPreparer.close();
- Connection c = logicalConnection.close();
- return c;
- }
- finally {
- batch = null;
- statementPreparer = null;
- logicalConnection = null;
- }
- }
-
- /**
- * Callback to let us know that a flush is beginning. We use this fact
- * to temporarily circumvent aggressive connection releasing until after
- * the flush cycle is complete {@link #flushEnding()}
- */
- @Override
- public void flushBeginning() {
- log.trace( "registering flush begin" );
- logicalConnection.disableReleases();
- }
-
- /**
- * Callback to let us know that a flush is ending. We use this fact to
- * stop circumventing aggressive releasing connections.
- */
- @Override
- public void flushEnding() {
- log.trace( "registering flush end" );
- logicalConnection.enableReleases();
- afterStatement();
- }
-
- /**
- * Get a non-batchable prepared statement to use for inserting / deleting / updating,
- * using JDBC3 getGeneratedKeys ({@link java.sql.Connection#prepareStatement(String, int)}).
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()}, it will be
- * released when the session is closed or disconnected.
- */
- @Override
- public PreparedStatement prepareStatement(String sql, final int autoGeneratedKeys)
- throws HibernateException {
- executeBatch();
- return statementPreparer.prepareStatement( getSQL( sql ), autoGeneratedKeys );
- }
-
- /**
- * Get a non-batchable prepared statement to use for inserting / deleting / updating.
- * using JDBC3 getGeneratedKeys ({@link java.sql.Connection#prepareStatement(String, String[])}).
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()}, it will be
- * released when the session is closed or disconnected.
- */
- @Override
- public PreparedStatement prepareStatement(String sql, final String[] columnNames) {
- executeBatch();
- return statementPreparer.prepareStatement( getSQL( sql ), columnNames );
- }
-
- /**
- * Get a non-batchable prepared statement to use for selecting. Does not
- * result in execution of the current batch.
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()},
- * it will be released when the session is closed or disconnected.
- */
- @Override
- public PreparedStatement prepareSelectStatement(String sql) {
- return statementPreparer.prepareStatement( getSQL( sql ), false );
- }
-
- /**
- * Get a non-batchable prepared statement to use for inserting / deleting / updating.
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()}, it will be
- * released when the session is closed or disconnected.
- */
- @Override
- public PreparedStatement prepareStatement(String sql, final boolean isCallable) {
- executeBatch();
- return statementPreparer.prepareStatement( getSQL( sql ), isCallable );
- }
-
- /**
- * Get a non-batchable callable statement to use for inserting / deleting / updating.
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()}, it will be
- * released when the session is closed or disconnected.
- */
- @Override
- public CallableStatement prepareCallableStatement(String sql) {
- executeBatch();
- log.trace("preparing callable statement");
- return CallableStatement.class.cast( statementPreparer.prepareStatement( getSQL( sql ), true ) );
- }
-
- /**
- * Get a batchable prepared statement to use for inserting / deleting / updating
- * (might be called many times before a single call to executeBatch()).
- * After setting parameters, call addToBatch - do not execute the
- * statement explicitly.
- * @see org.hibernate.engine.jdbc.batch.spi.Batch#addToBatch
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()}, it will be
- * released when the session is closed or disconnected.
- */
- @Override
- public PreparedStatement prepareBatchStatement(Object key, String sql, boolean isCallable) {
- if ( key == null ) {
- throw new IllegalArgumentException( "batch key must be non-null." );
- }
- String actualSQL = getSQL( sql );
- PreparedStatement batchUpdate = null;
- if ( batch != null ) {
- if ( key.equals( batch.getKey() ) ) {
- batchUpdate = batch.getBatchStatement( key, actualSQL );
- }
- else {
- batch.execute();
- batch = null;
- }
- }
- if ( batch == null ) {
- batch = batchBuilder.buildBatch(
- key,
- logicalConnection.getJdbcServices().getSqlStatementLogger(),
- logicalConnection.getJdbcServices().getSqlExceptionHelper()
- );
- }
- if ( batchUpdate == null ) {
- batchUpdate = statementPreparer.prepareStatement( actualSQL, isCallable );
- batch.addBatchStatement( key, actualSQL, batchUpdate );
- }
- return batchUpdate;
- }
-
- /**
- * Get a prepared statement for use in loading / querying. Does not
- * result in execution of the current batch.
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()},
- * it will be released when the session is closed or disconnected.
- */
- @Override
- public PreparedStatement prepareQueryStatement(
- String sql,
- final boolean isScrollable,
- final ScrollMode scrollMode,
- final boolean isCallable) {
- PreparedStatement ps = (
- isScrollable ?
- statementPreparer.prepareScrollableQueryStatement(
- getSQL( sql ), scrollMode, isCallable
- ) :
- statementPreparer.prepareQueryStatement(
- getSQL( sql ), isCallable
- )
- );
- logicalConnection.getResourceRegistry().registerLastQuery( ps );
- return ps;
- }
-
- /**
- * Cancel the current query statement
- */
- @Override
- public void cancelLastQuery() throws HibernateException {
- logicalConnection.getResourceRegistry().cancelLastQuery();
- }
-
- @Override
- public void addToBatch(Object batchKey, String sql, Expectation expectation) {
- batch.addToBatch( batchKey, sql, expectation );
- }
-
- @Override
- public void executeBatch() throws HibernateException {
- if ( batch != null ) {
- batch.execute();
- batch.release(); // needed?
- }
- }
-
- @Override
- public void abortBatch() {
- releaseBatch();
- }
-
- private void releaseBatch() {
- if ( batch != null ) {
- batch.release();
- }
- }
-
- private String getSQL(String sql) {
- sql = interceptor.onPrepareStatement( sql );
- if ( sql==null || sql.length() == 0 ) {
- throw new AssertionFailure( "Interceptor.onPrepareStatement() returned null or empty string." );
- }
- return sql;
- }
-
- public boolean isReadyForSerialization() {
- return logicalConnection == null ? true : logicalConnection.isReadyForSerialization();
- }
-
- /**
- * Used during serialization.
- *
- * @param oos The stream to which we are being written.
- * @throws IOException Indicates an I/O error writing to the stream
- */
- private void writeObject(ObjectOutputStream oos) throws IOException {
- if ( !isReadyForSerialization() ) {
- throw new IllegalStateException( "Cannot serialize a ConnectionManager while connected" );
- }
- oos.defaultWriteObject();
- }
-
- /**
- * Used during deserialization.
- *
- * @param ois The stream from which we are being read.
- * @throws IOException Indicates an I/O error reading the stream
- * @throws ClassNotFoundException Indicates resource class resolution.
- */
- private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
- ois.defaultReadObject();
- }
-
- public void serialize(ObjectOutputStream oos) throws IOException {
- logicalConnection.serialize( oos );
- }
-
- public static ConnectionManagerImpl deserialize(
- ObjectInputStream ois,
- SessionFactoryImplementor factory,
- Interceptor interceptor,
- ConnectionReleaseMode connectionReleaseMode,
- Callback callback) throws IOException {
- return new ConnectionManagerImpl(
- factory,
- callback,
- interceptor,
- LogicalConnectionImpl.deserialize(
- ois,
- factory.getJdbcServices(),
- factory.getStatistics() != null ? factory.getStatisticsImplementor() : null,
- connectionReleaseMode
- )
- );
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JDBCContextImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JDBCContextImpl.java
deleted file mode 100644
index bc3e7fb75a..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JDBCContextImpl.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.ObjectOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.sql.Connection;
-import java.sql.SQLException;
-
-import javax.transaction.TransactionManager;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.hibernate.ConnectionReleaseMode;
-import org.hibernate.HibernateException;
-import org.hibernate.Interceptor;
-import org.hibernate.SessionException;
-import org.hibernate.Transaction;
-import org.hibernate.TransactionException;
-import org.hibernate.engine.jdbc.spi.ConnectionManager;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-import org.hibernate.transaction.synchronization.CallbackCoordinator;
-import org.hibernate.transaction.synchronization.HibernateSynchronizationImpl;
-import org.hibernate.util.JTAHelper;
-import org.hibernate.engine.SessionFactoryImplementor;
-
-/**
- * Acts as the mediary between "entity-mode related" sessions in terms of
- * their interaction with the JDBC data store.
- *
- * @author Steve Ebersole
- */
-public class JDBCContextImpl implements ConnectionManagerImpl.Callback, JDBCContext {
-
- // TODO : make this the factory for "entity mode related" sessions;
- // also means making this the target of transaction-synch and the
- // thing that knows how to cascade things between related sessions
- //
- // At that point, perhaps this thing is a "SessionContext", and
- // ConnectionManager is a "JDBCContext"? A "SessionContext" should
- // live in the impl package...
-
- private static final Logger log = LoggerFactory.getLogger( JDBCContextImpl.class );
-
- private Context owner;
- private ConnectionManagerImpl connectionManager;
- private transient boolean isTransactionCallbackRegistered;
- private transient Transaction hibernateTransaction;
-
- private CallbackCoordinator jtaSynchronizationCallbackCoordinator;
-
- public JDBCContextImpl(Context owner, Connection connection, Interceptor interceptor) {
- this.owner = owner;
- this.connectionManager = new ConnectionManagerImpl(
- owner.getFactory(),
- this,
- owner.getConnectionReleaseMode(),
- connection,
- interceptor
- );
-
- final boolean registerSynchronization = owner.isAutoCloseSessionEnabled()
- || owner.isFlushBeforeCompletionEnabled()
- || owner.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION;
- if ( registerSynchronization ) {
- registerSynchronizationIfPossible();
- }
- }
-
- /**
- * Private constructor used exclusively for custom serialization...
- *
- */
- private JDBCContextImpl() {
- }
-
- @Override
- public CallbackCoordinator getJtaSynchronizationCallbackCoordinator() {
- return jtaSynchronizationCallbackCoordinator;
- }
-
- private CallbackCoordinator getJtaSynchronizationCallbackCoordinator(javax.transaction.Transaction jtaTransaction) {
- jtaSynchronizationCallbackCoordinator = new CallbackCoordinator( owner, this, jtaTransaction, hibernateTransaction );
- return jtaSynchronizationCallbackCoordinator;
- }
-
- @Override
- public void cleanUpJtaSynchronizationCallbackCoordinator() {
- jtaSynchronizationCallbackCoordinator = null;
- }
-
-
- // ConnectionManager.Callback implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- @Override
- public void physicalConnectionObtained(Connection connection) {
- if ( owner.getFactory().getStatistics().isStatisticsEnabled() ) {
- owner.getFactory().getStatisticsImplementor().connect();
- }
- }
-
- @Override
- public void physicalConnectionReleased() {
- if ( !isTransactionCallbackRegistered ) {
- afterTransactionCompletion( false, null );
- // Note : success = false, because we don't know the outcome of the transaction
- }
- }
-
- @Override
- public void logicalConnectionClosed() {
- // TODO: anything need to be done?
- }
-
- @Override
- public SessionFactoryImplementor getFactory() {
- return owner.getFactory();
- }
-
- @Override
- public ConnectionManager getConnectionManager() {
- return connectionManager;
- }
-
- public Connection borrowConnection() {
- return connectionManager.borrowConnection();
- }
-
- @Override
- public Connection connection() throws HibernateException {
- if ( owner.isClosed() ) {
- throw new SessionException( "Session is closed" );
- }
-
- return connectionManager.getConnection();
- }
-
- @Override
- public boolean registerCallbackIfNecessary() {
- if ( isTransactionCallbackRegistered ) {
- return false;
- }
- else {
- isTransactionCallbackRegistered = true;
- return true;
- }
-
- }
-
- @Override
- public boolean registerSynchronizationIfPossible() {
- if ( isTransactionCallbackRegistered ) {
- // we already have a callback registered; either a local
- // (org.hibernate.Transaction) transaction has accepted
- // callback responsibilities, or we have previously
- // registered a transaction synch.
- return true;
- }
- boolean localCallbacksOnly = owner.getFactory().getSettings()
- .getTransactionFactory()
- .areCallbacksLocalToHibernateTransactions();
- if ( localCallbacksOnly ) {
- // the configured transaction-factory says it only supports
- // local callback mode, so no sense attempting to register a
- // JTA Synchronization
- return false;
- }
- TransactionManager tm = owner.getFactory().getTransactionManager();
- if ( tm == null ) {
- // if there is no TM configured, we will not be able to access
- // the javax.transaction.Transaction object in order to
- // register a synch anyway.
- return false;
- }
- else {
- try {
- if ( !isTransactionInProgress() ) {
- log.trace( "TransactionFactory reported no active transaction; Synchronization not registered" );
- return false;
- }
- else {
- javax.transaction.Transaction tx = tm.getTransaction();
- if ( JTAHelper.isMarkedForRollback( tx ) ) {
- // transactions marked for rollback-only cause some TM impls to throw exceptions
- log.debug( "Transaction is marked for rollback; skipping Synchronization registration" );
- return false;
- }
- else {
- if ( hibernateTransaction == null ) {
- hibernateTransaction = owner.getFactory().getSettings().getTransactionFactory().createTransaction( this, owner );
- }
- tx.registerSynchronization(
- new HibernateSynchronizationImpl( getJtaSynchronizationCallbackCoordinator( tx ) )
- );
-// tx.registerSynchronization( new CacheSynchronization(owner, this, tx, hibernateTransaction) );
- isTransactionCallbackRegistered = true;
- log.debug("successfully registered Synchronization");
- return true;
- }
- }
- }
- catch( HibernateException e ) {
- throw e;
- }
- catch (Exception e) {
- throw new TransactionException( "could not register synchronization with JTA TransactionManager", e );
- }
- }
- }
-
- @Override
- public boolean isTransactionInProgress() {
- return owner.getFactory().getSettings().getTransactionFactory()
- .isTransactionInProgress( this, owner, hibernateTransaction );
- }
-
- @Override
- public Transaction getTransaction() throws HibernateException {
- if (hibernateTransaction==null) {
- hibernateTransaction = owner.getFactory().getSettings()
- .getTransactionFactory()
- .createTransaction( this, owner );
- }
- return hibernateTransaction;
- }
-
- @Override
- public void beforeTransactionCompletion(Transaction tx) {
- log.trace( "before transaction completion" );
- owner.beforeTransactionCompletion(tx);
- }
-
- /**
- * We cannot rely upon this method being called! It is only
- * called if we are using Hibernate Transaction API.
- */
- @Override
- public void afterTransactionBegin(Transaction tx) {
- log.trace( "after transaction begin" );
- owner.afterTransactionBegin(tx);
- }
-
- @Override
- public void afterTransactionCompletion(boolean success, Transaction tx) {
- log.trace( "after transaction completion" );
-
- if ( getFactory().getStatistics().isStatisticsEnabled() ) {
- getFactory().getStatisticsImplementor().endTransaction(success);
- }
-
- connectionManager.afterTransaction();
-
- isTransactionCallbackRegistered = false;
- hibernateTransaction = null;
- owner.afterTransactionCompletion(success, tx);
- }
-
- /**
- * Called after executing a query outside the scope of
- * a Hibernate or JTA transaction
- */
- @Override
- public void afterNontransactionalQuery(boolean success) {
- log.trace( "after autocommit" );
- try {
- // 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 = connectionManager.isAutoCommit();
-
- connectionManager.afterTransaction();
-
- if ( isAutocommit ) {
- owner.afterTransactionCompletion(success, null);
- }
- }
- catch (SQLException sqle) {
- throw owner.getFactory().getSQLExceptionHelper().convert(
- sqle,
- "could not inspect JDBC autocommit mode"
- );
- }
- }
-
-
- // serialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- public boolean isReadyForSerialization() {
- return connectionManager.isReadyForSerialization();
- }
-
- private void writeObject(ObjectOutputStream oos) throws IOException {
- // isTransactionCallbackRegistered denotes whether any Hibernate
- // Transaction has registered as a callback against this
- // JDBCContext; only one such callback is allowed. Directly
- // serializing this value causes problems with JDBCTransaction,
- // or really any Transaction impl where the callback is local
- // to the Transaction instance itself, since that Transaction
- // is not serialized along with the JDBCContext. Thus we
- // handle that fact here explicitly...
- oos.defaultWriteObject();
- boolean deserHasCallbackRegistered = isTransactionCallbackRegistered
- && ! owner.getFactory().getSettings().getTransactionFactory()
- .areCallbacksLocalToHibernateTransactions();
- oos.writeBoolean( deserHasCallbackRegistered );
- }
-
- private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
- ois.defaultReadObject();
- isTransactionCallbackRegistered = ois.readBoolean();
- }
-
- /**
- * Custom serialization routine used during serialization of a
- * Session/PersistenceContext for increased performance.
- *
- * @param oos The stream to which we should write the serial data.
- * @throws IOException
- */
- public void serialize(ObjectOutputStream oos) throws IOException {
- connectionManager.serialize( oos );
- }
-
- /**
- * Custom deserialization routine used during deserialization of a
- * Session/PersistenceContext for increased performance.
- *
- * @param ois The stream from which to read the entry.
- * @throws IOException
- */
- public static JDBCContextImpl deserialize(
- ObjectInputStream ois,
- Context context,
- Interceptor interceptor) throws IOException, ClassNotFoundException {
- JDBCContextImpl jdbcContext = new JDBCContextImpl();
- jdbcContext.owner = context;
- jdbcContext.connectionManager = ConnectionManagerImpl.deserialize(
- ois,
- context.getFactory(),
- interceptor,
- context.getConnectionReleaseMode(),
- jdbcContext
- );
- return jdbcContext;
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java
new file mode 100644
index 0000000000..241530c1a6
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java
@@ -0,0 +1,236 @@
+/*
+ * 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.jdbc.internal;
+
+import org.hibernate.HibernateException;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.jdbc.batch.spi.Batch;
+import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
+import org.hibernate.engine.jdbc.batch.spi.BatchKey;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
+import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
+import org.hibernate.engine.jdbc.spi.StatementPreparer;
+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.jdbc.Work;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Standard Hibernate implementation of {@link JdbcCoordinator}
+ *
+ * IMPL NOTE : Custom serialization handling!
+ *
+ * @author Steve Ebersole
+ */
+public class JdbcCoordinatorImpl implements JdbcCoordinator {
+ private static final Logger log = LoggerFactory.getLogger( JdbcCoordinatorImpl.class );
+
+ private transient TransactionCoordinatorImpl transactionCoordinator;
+
+ private final transient LogicalConnectionImpl logicalConnection;
+
+ private transient Batch currentBatch;
+
+ public JdbcCoordinatorImpl(
+ Connection userSuppliedConnection,
+ TransactionCoordinatorImpl transactionCoordinator) {
+ this.transactionCoordinator = transactionCoordinator;
+ this.logicalConnection = new LogicalConnectionImpl(
+ userSuppliedConnection,
+ transactionCoordinator.getTransactionContext().getConnectionReleaseMode(),
+ transactionCoordinator.getTransactionContext().getTransactionEnvironment().getJdbcServices()
+ );
+ }
+
+ private JdbcCoordinatorImpl(LogicalConnectionImpl logicalConnection) {
+ this.logicalConnection = logicalConnection;
+ }
+
+ @Override
+ public TransactionCoordinator getTransactionCoordinator() {
+ return transactionCoordinator;
+ }
+
+ @Override
+ public LogicalConnectionImplementor getLogicalConnection() {
+ return logicalConnection;
+ }
+
+ protected TransactionEnvironment transactionEnvironment() {
+ return getTransactionCoordinator().getTransactionContext().getTransactionEnvironment();
+ }
+
+ protected SessionFactoryImplementor sessionFactory() {
+ return transactionEnvironment().getSessionFactory();
+ }
+
+ protected BatchBuilder batchBuilder() {
+ return sessionFactory().getServiceRegistry().getService( BatchBuilder.class );
+ }
+
+ private SQLExceptionHelper sqlExceptionHelper() {
+ return transactionEnvironment().getJdbcServices().getSqlExceptionHelper();
+ }
+
+
+ private int flushDepth = 0;
+
+ @Override
+ public void flushBeginning() {
+ if ( flushDepth == 0 ) {
+ logicalConnection.disableReleases();
+ }
+ flushDepth++;
+ }
+
+ @Override
+ public void flushEnding() {
+ flushDepth--;
+ if ( flushDepth < 0 ) {
+ throw new HibernateException( "Mismatched flush handling" );
+ }
+ if ( flushDepth == 0 ) {
+ logicalConnection.enableReleases();
+ }
+ }
+
+ @Override
+ public Connection close() {
+ if ( currentBatch != null ) {
+ log.warn( "Closing un-released batch" );
+ currentBatch.release();
+ }
+ return logicalConnection.close();
+ }
+
+ @Override
+ public Batch getBatch(BatchKey key) {
+ if ( currentBatch != null ) {
+ if ( currentBatch.getKey().equals( key ) ) {
+ return currentBatch;
+ }
+ else {
+ currentBatch.execute();
+ currentBatch.release();
+ }
+ }
+ currentBatch = batchBuilder().buildBatch( key, this );
+ return currentBatch;
+ }
+
+ @Override
+ public void abortBatch() {
+ if ( currentBatch != null ) {
+ currentBatch.release();
+ }
+ }
+
+ private transient StatementPreparer statementPreparer;
+
+ @Override
+ public StatementPreparer getStatementPreparer() {
+ if ( statementPreparer == null ) {
+ statementPreparer = new StatementPreparerImpl( this );
+ }
+ return statementPreparer;
+ }
+
+ @Override
+ public void setTransactionTimeOut(int timeOut) {
+ getStatementPreparer().setTransactionTimeOut( timeOut );
+ }
+
+ /**
+ * To be called after local transaction completion. Used to conditionally
+ * release the JDBC connection aggressively if the configured release mode
+ * indicates.
+ */
+ public void afterTransaction() {
+ logicalConnection.afterTransaction();
+ if ( statementPreparer != null ) {
+ statementPreparer.unsetTransactionTimeOut();
+ }
+ }
+
+ public void coordinateWork(Work work) {
+ Connection connection = getLogicalConnection().getDistinctConnectionProxy();
+ try {
+ work.execute( connection );
+ getLogicalConnection().afterStatementExecution();
+ }
+ catch ( SQLException e ) {
+ throw sqlExceptionHelper().convert( e, "error executing work" );
+ }
+ finally {
+ try {
+ if ( ! connection.isClosed() ) {
+ connection.close();
+ }
+ }
+ catch (SQLException e) {
+ log.debug( "Error closing connection proxy", e );
+ }
+ }
+ }
+
+ public void executeBatch() {
+ if ( currentBatch != null ) {
+ currentBatch.execute();
+ currentBatch.release(); // needed?
+ }
+ }
+
+ @Override
+ public void cancelLastQuery() {
+ logicalConnection.getResourceRegistry().cancelLastQuery();
+ }
+
+
+ public void serialize(ObjectOutputStream oos) throws IOException {
+ if ( ! logicalConnection.isReadyForSerialization() ) {
+ throw new HibernateException( "Cannot serialize Session while connected" );
+ }
+ logicalConnection.serialize( oos );
+ }
+
+ public static JdbcCoordinatorImpl deserialize(
+ ObjectInputStream ois,
+ TransactionContext transactionContext) throws IOException, ClassNotFoundException {
+ return new JdbcCoordinatorImpl( LogicalConnectionImpl.deserialize( ois, transactionContext ) );
+ }
+
+ public void afterDeserialize(TransactionCoordinatorImpl transactionCoordinator) {
+ this.transactionCoordinator = transactionCoordinator;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/LogicalConnectionImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/LogicalConnectionImpl.java
index 8191d94162..25a5c208f2 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/LogicalConnectionImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/LogicalConnectionImpl.java
@@ -23,43 +23,46 @@
*/
package org.hibernate.engine.jdbc.internal;
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.HibernateException;
+import org.hibernate.JDBCException;
+import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
+import org.hibernate.engine.jdbc.spi.ConnectionObserver;
+import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
+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.util.CollectionHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
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.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.ConnectionReleaseMode;
-import org.hibernate.HibernateException;
-import org.hibernate.JDBCException;
-import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
-import org.hibernate.engine.jdbc.spi.JdbcServices;
-import org.hibernate.engine.jdbc.spi.ConnectionObserver;
-import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
-import org.hibernate.jdbc.BorrowedConnectionProxy;
-import org.hibernate.stat.StatisticsImplementor;
-
/**
- * LogicalConnectionImpl implementation
+ * Standard Hibernate {@link org.hibernate.engine.jdbc.spi.LogicalConnection} implementation
+ *
+ * IMPL NOTE : Custom serialization handling!
*
* @author Steve Ebersole
*/
public class LogicalConnectionImpl implements LogicalConnectionImplementor {
private static final Logger log = LoggerFactory.getLogger( LogicalConnectionImpl.class );
- private Connection physicalConnection;
- private Connection borrowedConnection;
+ private transient Connection physicalConnection;
+ private transient Connection shareableConnectionProxy;
- private final ConnectionReleaseMode connectionReleaseMode;
- private final JdbcServices jdbcServices;
- private final StatisticsImplementor statisticsImplementor;
- private final JdbcResourceRegistry jdbcResourceRegistry;
- private final List observers = new ArrayList();
+ private final transient ConnectionReleaseMode connectionReleaseMode;
+ private final transient JdbcServices jdbcServices;
+ private final transient JdbcResourceRegistry jdbcResourceRegistry;
+ private final transient List observers;
private boolean releasesEnabled = true;
@@ -67,40 +70,41 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
private boolean isClosed;
- public LogicalConnectionImpl(Connection userSuppliedConnection,
- ConnectionReleaseMode connectionReleaseMode,
- JdbcServices jdbcServices,
- StatisticsImplementor statisticsImplementor
- ) {
- this( connectionReleaseMode,
+ public LogicalConnectionImpl(
+ Connection userSuppliedConnection,
+ ConnectionReleaseMode connectionReleaseMode,
+ JdbcServices jdbcServices) {
+ this(
+ connectionReleaseMode,
jdbcServices,
- statisticsImplementor,
- userSuppliedConnection != null,
- false
+ (userSuppliedConnection != null),
+ false,
+ new ArrayList()
);
this.physicalConnection = userSuppliedConnection;
}
- private LogicalConnectionImpl(ConnectionReleaseMode connectionReleaseMode,
- JdbcServices jdbcServices,
- StatisticsImplementor statisticsImplementor,
- boolean isUserSuppliedConnection,
- boolean isClosed) {
+ private LogicalConnectionImpl(
+ ConnectionReleaseMode connectionReleaseMode,
+ JdbcServices jdbcServices,
+ boolean isUserSuppliedConnection,
+ boolean isClosed,
+ List observers) {
this.connectionReleaseMode = determineConnectionReleaseMode(
jdbcServices, isUserSuppliedConnection, connectionReleaseMode
);
this.jdbcServices = jdbcServices;
- this.statisticsImplementor = statisticsImplementor;
- this.jdbcResourceRegistry =
- new JdbcResourceRegistryImpl( getJdbcServices().getSqlExceptionHelper() );
+ this.jdbcResourceRegistry = new JdbcResourceRegistryImpl( getJdbcServices().getSqlExceptionHelper() );
+ this.observers = observers;
this.isUserSuppliedConnection = isUserSuppliedConnection;
this.isClosed = isClosed;
}
- private static ConnectionReleaseMode determineConnectionReleaseMode(JdbcServices jdbcServices,
- boolean isUserSuppliedConnection,
- ConnectionReleaseMode connectionReleaseMode) {
+ private static ConnectionReleaseMode determineConnectionReleaseMode(
+ JdbcServices jdbcServices,
+ boolean isUserSuppliedConnection,
+ ConnectionReleaseMode connectionReleaseMode) {
if ( isUserSuppliedConnection ) {
return ConnectionReleaseMode.ON_CLOSE;
}
@@ -114,60 +118,37 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
}
}
- /**
- * {@inheritDoc}
- */
+ @Override
public JdbcServices getJdbcServices() {
return jdbcServices;
}
- /**
- * {@inheritDoc}
- */
- public StatisticsImplementor getStatisticsImplementor() {
- return statisticsImplementor;
- }
-
- /**
- * {@inheritDoc}
- */
+ @Override
public JdbcResourceRegistry getResourceRegistry() {
return jdbcResourceRegistry;
}
- /**
- * {@inheritDoc}
- */
+ @Override
public void addObserver(ConnectionObserver observer) {
observers.add( observer );
}
- /**
- * {@inheritDoc}
- */
+ @Override
+ public void removeObserver(ConnectionObserver connectionObserver) {
+ observers.remove( connectionObserver );
+ }
+
+ @Override
public boolean isOpen() {
return !isClosed;
}
- /**
- * {@inheritDoc}
- */
- public boolean isLogicallyConnected() {
- return isUserSuppliedConnection ?
- isPhysicallyConnected() :
- isOpen();
- }
-
- /**
- * {@inheritDoc}
- */
+ @Override
public boolean isPhysicallyConnected() {
return physicalConnection != null;
}
- /**
- * {@inheritDoc}
- */
+ @Override
public Connection getConnection() throws HibernateException {
if ( isClosed ) {
throw new HibernateException( "Logical connection is closed" );
@@ -182,16 +163,33 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
return physicalConnection;
}
+ @Override
+ public Connection getShareableConnectionProxy() {
+ if ( shareableConnectionProxy == null ) {
+ shareableConnectionProxy = buildConnectionProxy();
+ }
+ return shareableConnectionProxy;
+ }
+
+ private Connection buildConnectionProxy() {
+ return ProxyBuilder.buildConnection( this );
+ }
+
+ @Override
+ public Connection getDistinctConnectionProxy() {
+ return buildConnectionProxy();
+ }
+
/**
* {@inheritDoc}
*/
public Connection close() {
- Connection c = physicalConnection;
+ log.trace( "closing logical connection" );
+ Connection c = isUserSuppliedConnection ? physicalConnection : null;
try {
- releaseBorrowedConnection();
- log.trace( "closing logical connection" );
+ releaseProxies();
+ jdbcResourceRegistry.close();
if ( !isUserSuppliedConnection && physicalConnection != null ) {
- jdbcResourceRegistry.close();
releaseConnection();
}
return c;
@@ -204,46 +202,28 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
for ( ConnectionObserver observer : observers ) {
observer.logicalConnectionClosed();
}
+ observers.clear();
}
}
- /**
- * {@inheritDoc}
- */
+ private void releaseProxies() {
+ if ( shareableConnectionProxy != null ) {
+ try {
+ shareableConnectionProxy.close();
+ }
+ catch (SQLException e) {
+ log.debug( "Error releasing shared connection proxy", e );
+ }
+ }
+ shareableConnectionProxy = null;
+ }
+
+ @Override
public ConnectionReleaseMode getConnectionReleaseMode() {
return connectionReleaseMode;
}
- public boolean hasBorrowedConnection() {
- return borrowedConnection != null;
- }
-
- public Connection borrowConnection() {
- if ( isClosed ) {
- throw new HibernateException( "connection has been closed" );
- }
- if ( isUserSuppliedConnection ) {
- return physicalConnection;
- }
- else {
- if ( borrowedConnection == null ) {
- borrowedConnection = BorrowedConnectionProxy.generateProxy( this );
- }
- return borrowedConnection;
- }
- }
-
- public void releaseBorrowedConnection() {
- if ( borrowedConnection != null ) {
- try {
- BorrowedConnectionProxy.renderUnuseable( borrowedConnection );
- }
- finally {
- borrowedConnection = null;
- }
- }
- }
-
+ @Override
public void afterStatementExecution() {
log.trace( "starting after statement execution processing [{}]", connectionReleaseMode );
if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT ) {
@@ -255,13 +235,11 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
log.debug( "skipping aggressive release due to registered resources" );
return;
}
- else if ( borrowedConnection != null ) {
- log.debug( "skipping aggresive-release due to borrowed connection" );
- }
releaseConnection();
}
}
+ @Override
public void afterTransaction() {
if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT ||
connectionReleaseMode == ConnectionReleaseMode.AFTER_TRANSACTION ) {
@@ -273,20 +251,21 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
}
}
+ @Override
public void disableReleases() {
log.trace( "disabling releases" );
releasesEnabled = false;
}
+ @Override
public void enableReleases() {
log.trace( "(re)enabling releases" );
releasesEnabled = true;
- //FIXME: uncomment after new batch stuff is integrated!!!
- //afterStatementExecution();
+ afterStatementExecution();
}
/**
- * Force aggresive release of the underlying connection.
+ * Force aggressive release of the underlying connection.
*/
public void aggressiveRelease() {
if ( isUserSuppliedConnection ) {
@@ -302,7 +281,7 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
/**
- * Pysically opens a JDBC Connection.
+ * Physically opens a JDBC Connection.
*
* @throws org.hibernate.JDBCException Indicates problem opening a connection
*/
@@ -349,32 +328,32 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
for ( ConnectionObserver observer : observers ) {
observer.physicalConnectionReleased();
}
+ releaseNonDurableObservers();
}
- /**
- * Manually disconnect the underlying JDBC Connection. The assumption here
- * is that the manager will be reconnected at a later point in time.
- *
- * @return The connection mantained here at time of disconnect. Null if
- * there was no connection cached internally.
- */
+ @Override
public Connection manualDisconnect() {
if ( isClosed ) {
throw new IllegalStateException( "cannot manually disconnect because logical connection is already closed" );
}
+ releaseProxies();
Connection c = physicalConnection;
jdbcResourceRegistry.releaseResources();
releaseConnection();
return c;
}
- /**
- * Manually reconnect the underlying JDBC Connection. Should be called at
- * some point after manualDisconnect().
- *
- * This form is used for user-supplied connections.
- */
- public void reconnect(Connection suppliedConnection) {
+ private void releaseNonDurableObservers() {
+ Iterator observers = this.observers.iterator();
+ while ( observers.hasNext() ) {
+ if ( NonDurableConnectionObserver.class.isInstance( observers.next() ) ) {
+ observers.remove();
+ }
+ }
+ }
+
+ @Override
+ public void manualReconnect(Connection suppliedConnection) {
if ( isClosed ) {
throw new IllegalStateException( "cannot manually reconnect because logical connection is already closed" );
}
@@ -401,29 +380,65 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
}
}
+ @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 void notifyObserversStatementPrepared() {
+ for ( ConnectionObserver observer : observers ) {
+ observer.statementPrepared();
+ }
+ }
+
+ @Override
public boolean isReadyForSerialization() {
- return isUserSuppliedConnection ?
- ! isPhysicallyConnected() :
- ! getResourceRegistry().hasRegisteredResources()
- ;
+ return isUserSuppliedConnection
+ ? ! isPhysicallyConnected()
+ : ! getResourceRegistry().hasRegisteredResources();
}
public void serialize(ObjectOutputStream oos) throws IOException {
oos.writeBoolean( isUserSuppliedConnection );
oos.writeBoolean( isClosed );
+ List durableConnectionObservers = new ArrayList();
+ for ( ConnectionObserver observer : observers ) {
+ if ( ! NonDurableConnectionObserver.class.isInstance( observer ) ) {
+ durableConnectionObservers.add( observer );
+ }
+ }
+ oos.writeInt( durableConnectionObservers.size() );
+ for ( ConnectionObserver observer : durableConnectionObservers ) {
+ oos.writeObject( observer );
+ }
}
- public static LogicalConnectionImpl deserialize(ObjectInputStream ois,
- JdbcServices jdbcServices,
- StatisticsImplementor statisticsImplementor,
- ConnectionReleaseMode connectionReleaseMode
- ) throws IOException {
+ public static LogicalConnectionImpl deserialize(
+ ObjectInputStream ois,
+ TransactionContext transactionContext) throws IOException, ClassNotFoundException {
+ boolean isUserSuppliedConnection = ois.readBoolean();
+ boolean isClosed = ois.readBoolean();
+ int observerCount = ois.readInt();
+ List observers = CollectionHelper.arrayList( observerCount );
+ for ( int i = 0; i < observerCount; i++ ) {
+ observers.add( (ConnectionObserver) ois.readObject() );
+ }
return new LogicalConnectionImpl(
- connectionReleaseMode,
- jdbcServices,
- statisticsImplementor,
- ois.readBoolean(),
- ois.readBoolean()
+ transactionContext.getConnectionReleaseMode(),
+ transactionContext.getTransactionEnvironment().getJdbcServices(),
+ isUserSuppliedConnection,
+ isClosed,
+ observers
);
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/StatementPreparer.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/StatementPreparer.java
deleted file mode 100644
index 2500f328f9..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/StatementPreparer.java
+++ /dev/null
@@ -1,276 +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.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.AssertionFailure;
-import org.hibernate.HibernateException;
-import org.hibernate.ScrollMode;
-import org.hibernate.TransactionException;
-import org.hibernate.cfg.Settings;
-import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
-import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
-import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
-
-/**
- * Prepares statements.
- *
- * @author Gail Badner
- */
-public class StatementPreparer {
-
- private static final Logger log = LoggerFactory.getLogger( StatementPreparer.class );
-
- // TODO: Move JDBC settings into a different object...
- private final Settings settings;
- private final Connection proxiedConnection;
- private final SQLExceptionHelper sqlExceptionHelper;
-
- private long transactionTimeout = -1;
- boolean isTransactionTimeoutSet;
-
- /**
- * Constructs a StatementPreparer object
- * @param logicalConnection - the logical connection
- * @param settings - contains settings configured for preparing statements
- */
- public StatementPreparer(LogicalConnectionImplementor logicalConnection, Settings settings) {
- this.settings = settings;
- proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
- sqlExceptionHelper = logicalConnection.getJdbcServices().getSqlExceptionHelper();
- }
-
- private abstract class StatementPreparation {
- private final String sql;
- protected abstract PreparedStatement doPrepare() throws SQLException;
- public StatementPreparation(String sql) {
- this.sql = sql;
- }
- public String getSql() {
- return sql;
- }
- public void postProcess(PreparedStatement preparedStatement) throws SQLException {
- setStatementTimeout( preparedStatement );
- }
- public PreparedStatement prepareAndPostProcess() {
- try {
- PreparedStatement ps = doPrepare();
- postProcess( ps );
- return ps;
- }
- catch ( SQLException sqle ) {
- log.error( "sqlexception escaped proxy", sqle );
- throw sqlExceptionHelper.convert(
- sqle, "could not prepare statement", sql
- );
- }
- }
- }
-
- private abstract class QueryStatementPreparation extends StatementPreparation {
- QueryStatementPreparation(String sql) {
- super( sql );
- }
- public void postProcess(PreparedStatement preparedStatement) throws SQLException {
- super.postProcess( preparedStatement );
- setStatementFetchSize( preparedStatement );
- }
- }
-
- public void close() {
- try {
- proxiedConnection.close();
- }
- catch (SQLException sqle) {
- log.error( "sqlexception escaped proxy", sqle );
- throw sqlExceptionHelper.convert( sqle, "could not close connection proxy" );
- }
- }
-
- /**
- * Prepare a statement. If configured, the query timeout is set.
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()},
- * it will be released when the session is closed or disconnected.
- *
- * @param sql - the SQL for the statement to be prepared
- * @param isCallable - true, if a callable statement is to be prepared
- * @return the prepared statement
- */
- public PreparedStatement prepareStatement(String sql, final boolean isCallable) {
- StatementPreparation statementPreparation = new StatementPreparation( sql ) {
- public PreparedStatement doPrepare() throws SQLException {
- return isCallable ?
- proxiedConnection.prepareCall( getSql() ) :
- proxiedConnection.prepareStatement( getSql() );
- }
- };
- return statementPreparation.prepareAndPostProcess();
- }
-
- /**
- * Get a prepared statement to use for inserting / deleting / updating,
- * using JDBC3 getGeneratedKeys ({@link java.sql.Connection#prepareStatement(String, int)}).
- * If configured, the query timeout is set.
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()},
- * it will be released when the session is closed or disconnected.
-
- * @param sql - the SQL for the statement to be prepared
- * @param autoGeneratedKeys - a flag indicating whether auto-generated
- * keys should be returned; one of
- *
PreparedStatement.RETURN_GENERATED_KEYS
or
- * Statement.NO_GENERATED_KEYS
- * @return the prepared statement
- */
- public PreparedStatement prepareStatement(String sql, final int autoGeneratedKeys)
- throws HibernateException {
- if ( autoGeneratedKeys == PreparedStatement.RETURN_GENERATED_KEYS ) {
- checkAutoGeneratedKeysSupportEnabled();
- }
- StatementPreparation statementPreparation = new StatementPreparation( sql ) {
- public PreparedStatement doPrepare() throws SQLException {
- return proxiedConnection.prepareStatement( getSql(), autoGeneratedKeys );
- }
- };
- return statementPreparation.prepareAndPostProcess();
- }
-
- /**
- * Get a prepared statement to use for inserting / deleting / updating.
- * using JDBC3 getGeneratedKeys ({@link java.sql.Connection#prepareStatement(String, String[])}).
- * If configured, the query timeout is set.
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()},
- * it will be released when the session is closed or disconnected.
- */
- public PreparedStatement prepareStatement(String sql, final String[] columnNames) {
- checkAutoGeneratedKeysSupportEnabled();
- StatementPreparation preparation = new StatementPreparation( sql ) {
- public PreparedStatement doPrepare() throws SQLException {
- return proxiedConnection.prepareStatement( getSql(), columnNames );
- }
- };
- return preparation.prepareAndPostProcess();
- }
-
- private void checkAutoGeneratedKeysSupportEnabled() {
- if ( ! settings.isGetGeneratedKeysEnabled() ) {
- throw new AssertionFailure("getGeneratedKeys() support is not enabled");
- }
- }
-
- /**
- * Get a prepared statement for use in loading / querying.
- * If configured, the query timeout and statement fetch size are set.
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()},
- * it will be released when the session is closed or disconnected.
- */
- public PreparedStatement prepareQueryStatement(
- String sql,
- final boolean isCallable
- ) {
- StatementPreparation prep = new QueryStatementPreparation( sql ) {
- public PreparedStatement doPrepare() throws SQLException {
- return isCallable ?
- proxiedConnection.prepareCall( getSql() ) :
- proxiedConnection.prepareStatement( getSql() );
- }
- };
- return prep.prepareAndPostProcess();
- }
-
- /**
- * Get a scrollable prepared statement for use in loading / querying.
- * If configured, the query timeout and statement fetch size are set.
- *
- * If not explicitly closed via {@link java.sql.PreparedStatement#close()},
- * it will be released when the session is closed or disconnected.
- */
- public PreparedStatement prepareScrollableQueryStatement(
- String sql,
- final ScrollMode scrollMode,
- final boolean isCallable
- ) {
- if ( ! settings.isScrollableResultSetsEnabled() ) {
- throw new AssertionFailure("scrollable result sets are not enabled");
- }
- StatementPreparation prep = new QueryStatementPreparation( sql ) {
- public PreparedStatement doPrepare() throws SQLException {
- return isCallable ?
- proxiedConnection.prepareCall(
- getSql(), scrollMode.toResultSetType(), ResultSet.CONCUR_READ_ONLY
- ) :
- proxiedConnection.prepareStatement(
- getSql(), scrollMode.toResultSetType(), ResultSet.CONCUR_READ_ONLY
- );
- }
- };
- return prep.prepareAndPostProcess();
- }
-
- /**
- * Sets the transaction timeout.
- * @param seconds - number of seconds until the the transaction times out.
- */
- public void setTransactionTimeout(int seconds) {
- isTransactionTimeoutSet = true;
- transactionTimeout = System.currentTimeMillis() / 1000 + seconds;
- }
-
- /**
- * Unset the transaction timeout, called after the end of a
- * transaction.
- */
- public void unsetTransactionTimeout() {
- isTransactionTimeoutSet = false;
- }
-
- private void setStatementTimeout(PreparedStatement preparedStatement) throws SQLException {
- if ( isTransactionTimeoutSet ) {
- int timeout = (int) ( transactionTimeout - ( System.currentTimeMillis() / 1000 ) );
- if ( timeout <= 0) {
- throw new TransactionException("transaction timeout expired");
- }
- else {
- preparedStatement.setQueryTimeout(timeout);
- }
- }
- }
-
- private void setStatementFetchSize(PreparedStatement statement) throws SQLException {
- if ( settings.getJdbcFetchSize() != null ) {
- statement.setFetchSize( settings.getJdbcFetchSize() );
- }
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/StatementPreparerImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/StatementPreparerImpl.java
new file mode 100644
index 0000000000..ed4fa259b0
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/StatementPreparerImpl.java
@@ -0,0 +1,223 @@
+/*
+ * 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.jdbc.internal;
+
+import org.hibernate.AssertionFailure;
+import org.hibernate.ScrollMode;
+import org.hibernate.TransactionException;
+import org.hibernate.cfg.Settings;
+import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
+import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
+import org.hibernate.engine.jdbc.spi.StatementPreparer;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+* @author Steve Ebersole
+*/
+class StatementPreparerImpl implements StatementPreparer {
+ private long transactionTimeOut = -1;
+ private JdbcCoordinatorImpl jdbcCoordinator;
+
+ StatementPreparerImpl(JdbcCoordinatorImpl jdbcCoordinator) {
+ this.jdbcCoordinator = jdbcCoordinator;
+ }
+
+ protected final Settings settings() {
+ return jdbcCoordinator.sessionFactory().getSettings();
+ }
+
+ protected final Connection connectionProxy() {
+ return logicalConnection().getShareableConnectionProxy();
+ }
+
+ protected final LogicalConnectionImplementor logicalConnection() {
+ return jdbcCoordinator.getLogicalConnection();
+ }
+
+ protected final SQLExceptionHelper sqlExceptionHelper() {
+ return jdbcCoordinator.getTransactionCoordinator()
+ .getTransactionContext()
+ .getTransactionEnvironment()
+ .getJdbcServices()
+ .getSqlExceptionHelper();
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql) {
+ return buildPreparedStatementPreparationTemplate( sql, false ).prepareStatement();
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, final boolean isCallable) {
+ jdbcCoordinator.executeBatch();
+ return buildPreparedStatementPreparationTemplate( sql, isCallable ).prepareStatement();
+ }
+
+ private StatementPreparationTemplate buildPreparedStatementPreparationTemplate(String sql, final boolean isCallable) {
+ return new StatementPreparationTemplate( sql ) {
+ @Override
+ protected PreparedStatement doPrepare() throws SQLException {
+ return isCallable
+ ? connectionProxy().prepareCall( sql )
+ : connectionProxy().prepareStatement( sql );
+ }
+ };
+ }
+
+ private void checkAutoGeneratedKeysSupportEnabled() {
+ if ( ! settings().isGetGeneratedKeysEnabled() ) {
+ throw new AssertionFailure( "getGeneratedKeys() support is not enabled" );
+ }
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, final int autoGeneratedKeys) {
+ if ( autoGeneratedKeys == PreparedStatement.RETURN_GENERATED_KEYS ) {
+ checkAutoGeneratedKeysSupportEnabled();
+ }
+ jdbcCoordinator.executeBatch();
+ return new StatementPreparationTemplate( sql ) {
+ public PreparedStatement doPrepare() throws SQLException {
+ return connectionProxy().prepareStatement( sql, autoGeneratedKeys );
+ }
+ }.prepareStatement();
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, final String[] columnNames) {
+ checkAutoGeneratedKeysSupportEnabled();
+ jdbcCoordinator.executeBatch();
+ return new StatementPreparationTemplate( sql ) {
+ public PreparedStatement doPrepare() throws SQLException {
+ return connectionProxy().prepareStatement( sql, columnNames );
+ }
+ }.prepareStatement();
+ }
+
+ @Override
+ public PreparedStatement prepareQueryStatement(
+ String sql,
+ final boolean isCallable,
+ final ScrollMode scrollMode) {
+ if ( scrollMode != null && !scrollMode.equals( ScrollMode.FORWARD_ONLY ) ) {
+ if ( ! settings().isScrollableResultSetsEnabled() ) {
+ throw new AssertionFailure("scrollable result sets are not enabled");
+ }
+ PreparedStatement ps = new QueryStatementPreparationTemplate( sql ) {
+ public PreparedStatement doPrepare() throws SQLException {
+ return isCallable
+ ? connectionProxy().prepareCall(
+ sql, scrollMode.toResultSetType(), ResultSet.CONCUR_READ_ONLY
+ )
+ : connectionProxy().prepareStatement(
+ sql, scrollMode.toResultSetType(), ResultSet.CONCUR_READ_ONLY
+ );
+ }
+ }.prepareStatement();
+ logicalConnection().getResourceRegistry().registerLastQuery( ps );
+ return ps;
+ }
+ else {
+ PreparedStatement ps = new QueryStatementPreparationTemplate( sql ) {
+ public PreparedStatement doPrepare() throws SQLException {
+ return isCallable
+ ? connectionProxy().prepareCall( sql )
+ : connectionProxy().prepareStatement( sql );
+ }
+ }.prepareStatement();
+ logicalConnection().getResourceRegistry().registerLastQuery( ps );
+ return ps;
+ }
+ }
+
+ @Override
+ public void setTransactionTimeOut(int timeOut) {
+ transactionTimeOut = timeOut;
+ }
+
+ @Override
+ public void unsetTransactionTimeOut() {
+ transactionTimeOut = -1;
+ }
+
+ private abstract class StatementPreparationTemplate {
+ protected final String sql;
+
+ protected StatementPreparationTemplate(String sql) {
+ this.sql = sql;
+ }
+
+ public PreparedStatement prepareStatement() {
+ try {
+ PreparedStatement preparedStatement = doPrepare();
+ setStatementTimeout( preparedStatement );
+ postProcess( preparedStatement );
+ return preparedStatement;
+ }
+ catch ( SQLException e ) {
+ throw sqlExceptionHelper().convert( e, "could not prepare statement", sql );
+ }
+ }
+
+ protected abstract PreparedStatement doPrepare() throws SQLException;
+
+ public void postProcess(PreparedStatement preparedStatement) throws SQLException {
+ }
+
+ private void setStatementTimeout(PreparedStatement preparedStatement) throws SQLException {
+ if ( transactionTimeOut > 0 ) {
+ int timeout = (int) ( transactionTimeOut - ( System.currentTimeMillis() / 1000 ) );
+ if ( timeout <= 0 ) {
+ throw new TransactionException( "transaction timeout expired" );
+ }
+ else {
+ preparedStatement.setQueryTimeout( timeout );
+ }
+ }
+ }
+
+ }
+
+ private abstract class QueryStatementPreparationTemplate extends StatementPreparationTemplate {
+ protected QueryStatementPreparationTemplate(String sql) {
+ super( sql );
+ }
+
+ public void postProcess(PreparedStatement preparedStatement) throws SQLException {
+ super.postProcess( preparedStatement );
+ setStatementFetchSize( preparedStatement );
+ }
+ }
+
+ private void setStatementFetchSize(PreparedStatement statement) throws SQLException {
+ if ( settings().getJdbcFetchSize() != null ) {
+ statement.setFetchSize( settings().getJdbcFetchSize() );
+ }
+ }
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/ConnectionProxyHandler.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/ConnectionProxyHandler.java
index ef5e0fcf47..206ae0b2e7 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/ConnectionProxyHandler.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/ConnectionProxyHandler.java
@@ -36,19 +36,19 @@ import java.sql.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.hibernate.TransactionException;
import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
import org.hibernate.engine.jdbc.spi.JdbcServices;
-import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
-import org.hibernate.stat.StatisticsImplementor;
+import org.hibernate.engine.jdbc.spi.NonDurableConnectionObserver;
/**
* The {@link InvocationHandler} for intercepting messages to {@link java.sql.Connection} proxies.
*
* @author Steve Ebersole
*/
-public class ConnectionProxyHandler extends AbstractProxyHandler implements InvocationHandler, ConnectionObserver {
+public class ConnectionProxyHandler
+ extends AbstractProxyHandler
+ implements InvocationHandler, NonDurableConnectionObserver {
private static final Logger log = LoggerFactory.getLogger( ConnectionProxyHandler.class );
private LogicalConnectionImplementor logicalConnection;
@@ -112,6 +112,10 @@ public class ConnectionProxyHandler extends AbstractProxyHandler implements Invo
return null;
}
+ if ( "isClosed".equals( methodName ) ) {
+ return ! isValid();
+ }
+
errorIfInvalid();
// handle the JDBC 4 Wrapper#isWrapperFor and Wrapper#unwrap calls
@@ -185,9 +189,7 @@ public class ConnectionProxyHandler extends AbstractProxyHandler implements Invo
}
private void postProcessPreparedStatement(Statement statement) throws SQLException {
- if ( getStatisticsImplementorOrNull() != null ) {
- getStatisticsImplementorOrNull().prepareStatement();
- }
+ logicalConnection.notifyObserversStatementPrepared();
postProcessStatement( statement );
}
@@ -203,29 +205,25 @@ public class ConnectionProxyHandler extends AbstractProxyHandler implements Invo
invalidate();
}
- /**
- * {@inheritDoc}
- */
+ // ConnectionObserver ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ @Override
public void physicalConnectionObtained(Connection connection) {
}
- /**
- * {@inheritDoc}
- */
+ @Override
public void physicalConnectionReleased() {
log.info( "logical connection releasing its physical connection");
}
- /**
- * {@inheritDoc}
- */
+ @Override
public void logicalConnectionClosed() {
log.info( "*** logical connection closed ***" );
invalidateHandle();
}
- /* package-protected */
- StatisticsImplementor getStatisticsImplementorOrNull() {
- return getLogicalConnection().getStatisticsImplementor();
+ @Override
+ public void statementPrepared() {
+ // N/A
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ConnectionObserver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ConnectionObserver.java
index 20abcbf038..27072979d7 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ConnectionObserver.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ConnectionObserver.java
@@ -47,4 +47,9 @@ public interface ConnectionObserver {
* The logical connection was closed.
*/
public void logicalConnectionClosed();
+
+ /**
+ * Notification of a statement being prepared
+ */
+ public void statementPrepared();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/jdbc/ConnectionWrapper.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ConnectionObserverAdapter.java
similarity index 66%
rename from hibernate-core/src/main/java/org/hibernate/jdbc/ConnectionWrapper.java
rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ConnectionObserverAdapter.java
index 1515245d79..32408525b2 100644
--- a/hibernate-core/src/main/java/org/hibernate/jdbc/ConnectionWrapper.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ConnectionObserverAdapter.java
@@ -1,42 +1,47 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.jdbc;
-
-import java.sql.Connection;
-
-/**
- * Interface implemented by JDBC connection wrappers in order to give
- * access to the underlying wrapped connection.
- *
- * @author Steve Ebersole
- */
-public interface ConnectionWrapper {
- /**
- * Get a reference to the wrapped connection.
- *
- * @return The wrapped connection.
- */
- public Connection getWrappedConnection();
-}
+/*
+ * 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.jdbc.spi;
+
+import java.sql.Connection;
+
+/**
+ * @author Steve Ebersole
+ */
+public class ConnectionObserverAdapter implements ConnectionObserver {
+ @Override
+ public void physicalConnectionObtained(Connection connection) {
+ }
+
+ @Override
+ public void physicalConnectionReleased() {
+ }
+
+ @Override
+ public void logicalConnectionClosed() {
+ }
+
+ @Override
+ public void statementPrepared() {
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JDBCContext.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JDBCContext.java
deleted file mode 100644
index 4e177d44a0..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JDBCContext.java
+++ /dev/null
@@ -1,83 +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;
-
-import org.hibernate.ConnectionReleaseMode;
-import org.hibernate.HibernateException;
-import org.hibernate.Transaction;
-import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.transaction.TransactionFactory;
-import org.hibernate.transaction.synchronization.CallbackCoordinator;
-
-/**
- * Acts as the SPI for the mediary between "entity-mode related" sessions in terms of
- * their interaction with the JDBC data store.
- *
- * @author Gail Badner
- */
-public interface JDBCContext extends Serializable {
-
- // TODO: Document these methods...
-
- CallbackCoordinator getJtaSynchronizationCallbackCoordinator();
-
- void cleanUpJtaSynchronizationCallbackCoordinator();
-
- SessionFactoryImplementor getFactory();
-
- ConnectionManager getConnectionManager();
-
- Connection connection() throws HibernateException;
-
- boolean registerCallbackIfNecessary();
-
- boolean registerSynchronizationIfPossible();
-
- boolean isTransactionInProgress();
-
- Transaction getTransaction() throws HibernateException;
-
- void beforeTransactionCompletion(Transaction tx);
-
- void afterTransactionBegin(Transaction tx);
-
- void afterTransactionCompletion(boolean success, Transaction tx);
-
- void afterNontransactionalQuery(boolean success);
-
- public static interface Context extends TransactionFactory.Context {
- /**
- * We cannot rely upon this method being called! It is only
- * called if we are using Hibernate Transaction API.
- */
- public void afterTransactionBegin(Transaction tx);
- public void beforeTransactionCompletion(Transaction tx);
- public void afterTransactionCompletion(boolean success, Transaction tx);
- public ConnectionReleaseMode getConnectionReleaseMode();
- public boolean isAutoCloseSessionEnabled();
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/OrionTransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcContext.java
similarity index 55%
rename from hibernate-core/src/main/java/org/hibernate/transaction/OrionTransactionManagerLookup.java
rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcContext.java
index 6960405c77..a3c8ad8998 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/OrionTransactionManagerLookup.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcContext.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * 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 Middleware LLC.
+ * 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
@@ -20,35 +20,32 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
-package org.hibernate.transaction;
+package org.hibernate.engine.jdbc.spi;
+
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.io.Serializable;
/**
- * {@link TransactionManagerLookup} strategy for Orion
+ * Access to services needed in the context of processing JDBC requests.
*
- * @author Gavin King
+ * @author Steve Ebersole
*/
-public class OrionTransactionManagerLookup extends JNDITransactionManagerLookup {
+public interface JdbcContext extends Serializable {
+ public SessionFactoryImplementor getSessionFactory();
+ public ConnectionReleaseMode getConnectionReleaseMode();
- /**
- * {@inheritDoc}
- */
- protected String getName() {
- return "java:comp/UserTransaction";
- }
+ public boolean isClosed();
- /**
- * {@inheritDoc}
- */
- public String getUserTransactionName() {
- return "java:comp/UserTransaction";
- }
+ public boolean isFlushModeNever();
+ public boolean isFlushBeforeCompletionEnabled();
+
+ public void managedFlush();
+
+ public boolean shouldAutoClose();
+
+ public void managedClose();
}
-
-
-
-
-
-
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcCoordinator.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcCoordinator.java
new file mode 100644
index 0000000000..d1d9a143de
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcCoordinator.java
@@ -0,0 +1,96 @@
+/*
+ * 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.jdbc.spi;
+
+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.Work;
+
+import java.io.Serializable;
+import java.sql.Connection;
+
+/**
+ * Coordinates JDBC-related activities.
+ *
+ * @author Steve Ebersole
+ */
+public interface JdbcCoordinator extends Serializable {
+ /**
+ * 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.
+ *
+ * @return The logical connection
+ */
+ public LogicalConnectionImplementor getLogicalConnection();
+
+ /**
+ * Get a batch instance.
+ *
+ * @param key The unique batch key.
+ *
+ * @return The batch
+ */
+ public Batch getBatch(BatchKey key);
+
+ public void abortBatch();
+
+ /**
+ * Obtain the statement preparer associated with this JDBC coordinator.
+ *
+ * @return This coordinator's statement preparer
+ */
+ public StatementPreparer getStatementPreparer();
+
+ /**
+ * Callback to let us know that a flush is beginning. We use this fact
+ * to temporarily circumvent aggressive connection releasing until after
+ * the flush cycle is complete {@link #flushEnding()}
+ */
+ public void flushBeginning();
+
+ /**
+ * Callback to let us know that a flush is ending. We use this fact to
+ * stop circumventing aggressive releasing connections.
+ */
+ public void flushEnding();
+
+ public Connection close();
+
+ public void afterTransaction();
+
+ public void coordinateWork(Work work);
+
+ public void executeBatch();
+
+ public void cancelLastQuery();
+
+ public void setTransactionTimeOut(int timeout);
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcResourceRegistry.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcResourceRegistry.java
index 078c6d48ec..4ec5c57ee3 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcResourceRegistry.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcResourceRegistry.java
@@ -23,6 +23,7 @@
*/
package org.hibernate.engine.jdbc.spi;
+import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.Statement;
@@ -31,7 +32,7 @@ import java.sql.Statement;
*
* @author Steve Ebersole
*/
-public interface JdbcResourceRegistry {
+public interface JdbcResourceRegistry extends Serializable {
/**
* Register a JDBC statement.
*
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/LogicalConnection.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/LogicalConnection.java
index 1c54e3f6aa..0a237d0860 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/LogicalConnection.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/LogicalConnection.java
@@ -31,7 +31,7 @@ import java.sql.Connection;
*
* @author Steve Ebersole
*/
-public interface LogicalConnection {
+public interface LogicalConnection extends Serializable {
/**
* Is this logical connection open? Another phraseology sometimes used is: "are we
* logically connected"?
@@ -55,10 +55,27 @@ public interface LogicalConnection {
* connection has either not yet been obtained (non-UserSuppliedConnectionProvider)
* or has previously been aggressively released.
*
+ * @todo ?? Move this to {@link LogicalConnectionImplementor} in lieu of {@link #getShareableConnectionProxy} and {@link #getDistinctConnectionProxy} ??
+ *
* @return The current Connection.
*/
public Connection getConnection();
+ /**
+ * Retrieves the shareable connection proxy (see {@link org.hibernate.engine.jdbc.internal.proxy} for details).
+ *
+ * @return The shareable connection proxy.
+ */
+ public Connection getShareableConnectionProxy();
+
+ /**
+ * Retrieves a distinct connection proxy (see {@link org.hibernate.engine.jdbc.internal.proxy} for details). It
+ * is distinct in that it is not shared with others unless the caller explicitly shares it.
+ *
+ * @return The distinct connection proxy.
+ */
+ public Connection getDistinctConnectionProxy();
+
/**
* Release the underlying connection and clean up any other resources associated
* with this logical connection.
@@ -68,4 +85,6 @@ public interface LogicalConnection {
* @return The physical connection which was being used.
*/
public Connection close();
+
+ public void afterTransaction();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/LogicalConnectionImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/LogicalConnectionImplementor.java
index 288554ff35..4c505836bd 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/LogicalConnectionImplementor.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/LogicalConnectionImplementor.java
@@ -24,8 +24,11 @@
package org.hibernate.engine.jdbc.spi;
import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler;
import org.hibernate.stat.StatisticsImplementor;
+import java.sql.Connection;
+
/**
* The "internal" contract for LogicalConnection
*
@@ -39,13 +42,6 @@ public interface LogicalConnectionImplementor extends LogicalConnection {
*/
public JdbcServices getJdbcServices();
- /**
- * Obtains the statistics implementor.
- *
- * @return the statistics implementor
- */
- public StatisticsImplementor getStatisticsImplementor();
-
/**
* Obtains the JDBC resource registry associated with this logical connection.
*
@@ -60,6 +56,13 @@ public interface LogicalConnectionImplementor extends LogicalConnection {
*/
public void addObserver(ConnectionObserver observer);
+ /**
+ * Remove an observer
+ *
+ * @param connectionObserver The observer to remove.
+ */
+ public void removeObserver(ConnectionObserver connectionObserver);
+
/**
* The release mode under which this logical connection is operating.
*
@@ -91,5 +94,26 @@ public interface LogicalConnectionImplementor extends LogicalConnection {
*/
public void enableReleases();
+ /**
+ * 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
+ * there was no connection cached internally.
+ */
+ public Connection manualDisconnect();
+ /**
+ * Manually reconnect the underlying JDBC Connection. Should be called at some point after manualDisconnect().
+ *
+ * @param suppliedConnection For user supplied connection strategy the user needs to hand us the connection
+ * with which to reconnect. It is an error to pass a connection in the other strategies.
+ */
+ public void manualReconnect(Connection suppliedConnection);
+
+ public boolean isAutoCommit();
+
+ public boolean isReadyForSerialization();
+
+ public void notifyObserversStatementPrepared();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/JBossTransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/NonDurableConnectionObserver.java
similarity index 65%
rename from hibernate-core/src/main/java/org/hibernate/transaction/JBossTransactionManagerLookup.java
rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/NonDurableConnectionObserver.java
index cdfd63390a..7a84ded4f9 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/JBossTransactionManagerLookup.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/NonDurableConnectionObserver.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * 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 Middleware LLC.
+ * 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
@@ -20,23 +20,14 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
-package org.hibernate.transaction;
+package org.hibernate.engine.jdbc.spi;
/**
- * A {@link TransactionManagerLookup} lookup strategy for JBoss AS.
+ * Additional optional contract for connection observers to indicate that they should be released when the physical
+ * connection is released.
*
- * @author Gavin King
+ * @author Steve Ebersole
*/
-public final class JBossTransactionManagerLookup extends JNDITransactionManagerLookup {
-
- protected String getName() {
- return "java:/TransactionManager";
- }
-
- public String getUserTransactionName() {
- return "UserTransaction";
- }
-
+public interface NonDurableConnectionObserver extends ConnectionObserver {
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SQLExceptionHelper.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SQLExceptionHelper.java
index bb70a938cf..0db12c826b 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SQLExceptionHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SQLExceptionHelper.java
@@ -23,6 +23,7 @@
*/
package org.hibernate.engine.jdbc.spi;
+import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLWarning;
@@ -41,7 +42,7 @@ import org.hibernate.util.StringHelper;
*
* @author Steve Ebersole
*/
-public class SQLExceptionHelper {
+public class SQLExceptionHelper implements Serializable {
private static final Logger log = LoggerFactory.getLogger( SQLExceptionHelper.class );
public static final String DEFAULT_EXCEPTION_MSG = "SQL Exception";
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/StatementPreparer.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/StatementPreparer.java
new file mode 100644
index 0000000000..56c02e6653
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/StatementPreparer.java
@@ -0,0 +1,97 @@
+/*
+ * 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.jdbc.spi;
+
+import org.hibernate.ScrollMode;
+
+import java.sql.PreparedStatement;
+
+/**
+ * @author Steve Ebersole
+ */
+public interface StatementPreparer {
+ /**
+ * Prepare a statement.
+ *
+ * @param sql The SQL the statement to be prepared
+ *
+ * @return the prepared statement
+ */
+ public PreparedStatement prepareStatement(String sql);
+
+ /**
+ * Prepare a statement.
+ *
+ * @param sql The SQL the statement to be prepared
+ * @param isCallable Whether to prepare as a callable statement.
+ *
+ * @return the prepared statement
+ */
+ public PreparedStatement prepareStatement(String sql, boolean isCallable);
+
+ /**
+ * Get a prepared statement to use for inserting using JDBC3
+ * {@link java.sql.PreparedStatement#getGeneratedKeys getGeneratedKeys} processing.
+ *
+ * @param sql - the SQL for the statement to be prepared
+ * @param autoGeneratedKeys - a flag indicating whether auto-generated keys should be returned; one of
+ * - {@link PreparedStatement#RETURN_GENERATED_KEYS}
+ * - {@link PreparedStatement#NO_GENERATED_KEYS}
+ *
+ *
+ * @return the prepared statement
+ *
+ * @see java.sql.Connection#prepareStatement(String, int)
+ */
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys);
+
+
+ /**
+ * Get a prepared statement to use for inserting using JDBC3
+ * {@link java.sql.PreparedStatement#getGeneratedKeys getGeneratedKeys} processing.
+ *
+ * @param sql - the SQL for the statement to be prepared
+ * @param columnNames The name of the columns to be returned in the generated keys result set.
+ *
+ * @return the prepared statement
+ *
+ * @see java.sql.Connection#prepareStatement(String, String[])
+ */
+ public PreparedStatement prepareStatement(String sql, String[] columnNames);
+
+ /**
+ * Get a prepared statement for use in loading / querying.
+ *
+ * @param sql The SQL the statement to be prepared
+ * @param isCallable Whether to prepare as a callable statement.
+ * @param scrollMode (optional) scroll mode to be applied to the resulting result set; may be null to indicate
+ * no scrolling should be applied.
+ *
+ * @return the prepared statement
+ */
+ public PreparedStatement prepareQueryStatement(String sql, boolean isCallable, ScrollMode scrollMode);
+
+ public void setTransactionTimeOut(int timeout);
+ public void unsetTransactionTimeOut();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/NativeSQLQueryPlan.java b/hibernate-core/src/main/java/org/hibernate/engine/query/NativeSQLQueryPlan.java
index e930ef4ff4..dfa7d3c94f 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/query/NativeSQLQueryPlan.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/query/NativeSQLQueryPlan.java
@@ -198,7 +198,7 @@ public class NativeSQLQueryPlan implements Serializable {
session );
String sql = queryParameters.getFilteredSQL();
- ps = session.getJDBCContext().getConnectionManager().prepareStatement( sql, false );
+ ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
try {
int col = 1;
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/Isolater.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/Isolater.java
deleted file mode 100644
index ba2c75f799..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/engine/transaction/Isolater.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import javax.transaction.SystemException;
-import javax.transaction.NotSupportedException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.hibernate.HibernateException;
-import org.hibernate.engine.SessionImplementor;
-import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
-import org.hibernate.exception.JDBCExceptionHelper;
-import org.hibernate.exception.SQLExceptionConverter;
-
-/**
- * Class which provides the isolation semantics required by
- * an {@link IsolatedWork}. Processing comes in two flavors:
- * - {@link #doIsolatedWork} : makes sure the work to be done is
- * performed in a seperate, distinct transaction
- * - {@link #doNonTransactedWork} : makes sure the work to be
- * done is performed outside the scope of any transaction
- *
- *
- * @author Steve Ebersole
- */
-public class Isolater {
-
- private static final Logger log = LoggerFactory.getLogger( Isolater.class );
-
- /**
- * Ensures that all processing actually performed by the given work will
- * occur on a seperate transaction.
- *
- * @param work The work to be performed.
- * @param session The session from which this request is originating.
- * @throws HibernateException
- */
- public static void doIsolatedWork(IsolatedWork work, SessionImplementor session) throws HibernateException {
- boolean isJta = session.getFactory().getTransactionManager() != null;
- if ( isJta ) {
- new JtaDelegate( session ).delegateWork( work, true );
- }
- else {
- new JdbcDelegate( session ).delegateWork( work, true );
- }
- }
-
- /**
- * Ensures that all processing actually performed by the given work will
- * occur outside of a transaction.
- *
- * @param work The work to be performed.
- * @param session The session from which this request is originating.
- * @throws HibernateException
- */
- public static void doNonTransactedWork(IsolatedWork work, SessionImplementor session) throws HibernateException {
- boolean isJta = session.getFactory().getTransactionManager() != null;
- if ( isJta ) {
- new JtaDelegate( session ).delegateWork( work, false );
- }
- else {
- new JdbcDelegate( session ).delegateWork( work, false );
- }
- }
-
- // should be ok performance-wise to generate new delegate instances for each
- // request since these are locally stack-scoped. Besides, it makes the code
- // much easier to read than the old TransactionHelper stuff...
-
- private static interface Delegate {
- public void delegateWork(IsolatedWork work, boolean transacted) throws HibernateException;
- }
-
- /**
- * An isolation delegate for JTA-based transactions. Essentially susepnds
- * any current transaction, does the work in a new transaction, and then
- * resumes the initial transaction (if there was one).
- */
- public static class JtaDelegate implements Delegate {
- private final SessionImplementor session;
-
- public JtaDelegate(SessionImplementor session) {
- this.session = session;
- }
-
- public void delegateWork(IsolatedWork work, boolean transacted) throws HibernateException {
- TransactionManager transactionManager = session.getFactory().getTransactionManager();
-
- try {
- // First we suspend any current JTA transaction
- Transaction surroundingTransaction = transactionManager.suspend();
- if ( log.isDebugEnabled() ) {
- log.debug( "surrounding JTA transaction suspended [" + surroundingTransaction + "]" );
- }
-
- boolean hadProblems = false;
- try {
- // then peform the requested work
- if ( transacted ) {
- doTheWorkInNewTransaction( work, transactionManager );
- }
- else {
- doTheWorkInNoTransaction( work );
- }
- }
- catch ( HibernateException e ) {
- hadProblems = true;
- throw e;
- }
- finally {
- try {
- transactionManager.resume( surroundingTransaction );
- if ( log.isDebugEnabled() ) {
- log.debug( "surrounding JTA transaction resumed [" + surroundingTransaction + "]" );
- }
- }
- catch( Throwable t ) {
- // if the actually work had an error use that, otherwise error based on t
- if ( !hadProblems ) {
- //noinspection ThrowFromFinallyBlock
- throw new HibernateException( "Unable to resume previously suspended transaction", t );
- }
- }
- }
- }
- catch ( SystemException e ) {
- throw new HibernateException( "Unable to suspend current JTA transaction", e );
- }
- }
-
- private void doTheWorkInNewTransaction(IsolatedWork work, TransactionManager transactionManager) {
- try {
- // start the new isolated transaction
- transactionManager.begin();
-
- try {
- doTheWork( work );
- // if everythign went ok, commit the isolated transaction
- transactionManager.commit();
- }
- catch ( Exception e ) {
- try {
- transactionManager.rollback();
- }
- catch ( Exception ignore ) {
- log.info( "Unable to rollback isolated transaction on error [" + e + "] : [" + ignore + "]" );
- }
- }
- }
- catch ( SystemException e ) {
- throw new HibernateException( "Unable to start isolated transaction", e );
- }
- catch ( NotSupportedException e ) {
- throw new HibernateException( "Unable to start isolated transaction", e );
- }
- }
-
- private void doTheWorkInNoTransaction(IsolatedWork work) {
- doTheWork( work );
- }
-
- private void doTheWork(IsolatedWork work) {
- try {
- // obtain our isolated connection
- Connection connection = session.getFactory().getConnectionProvider().getConnection();
- try {
- // do the actual work
- work.doWork( connection );
- }
- catch ( HibernateException e ) {
- throw e;
- }
- catch ( Exception e ) {
- throw new HibernateException( "Unable to perform isolated work", e );
- }
- finally {
- try {
- // no matter what, release the connection (handle)
- session.getFactory().getConnectionProvider().closeConnection( connection );
- }
- catch ( Throwable ignore ) {
- log.info( "Unable to release isolated connection [" + ignore + "]" );
- }
- }
- }
- catch ( SQLException sqle ) {
- throw sqlExceptionHelper().convert(
- sqle,
- "unable to obtain isolated JDBC connection"
- );
- }
- }
-
- private SQLExceptionHelper sqlExceptionHelper() {
- return session.getFactory().getSQLExceptionHelper();
- }
- }
-
- /**
- * An isolation delegate for JDBC-based transactions. Basically just
- * grabs a new connection and does the work on that.
- */
- public static class JdbcDelegate implements Delegate {
- private final SessionImplementor session;
-
- public JdbcDelegate(SessionImplementor session) {
- this.session = session;
- }
-
- public void delegateWork(IsolatedWork work, boolean transacted) throws HibernateException {
- boolean wasAutoCommit = false;
- try {
- Connection connection = session.getFactory().getConnectionProvider().getConnection();
- try {
- if ( transacted ) {
- if ( connection.getAutoCommit() ) {
- wasAutoCommit = true;
- connection.setAutoCommit( false );
- }
- }
-
- work.doWork( connection );
-
- if ( transacted ) {
- connection.commit();
- }
- }
- catch( Exception e ) {
- try {
- if ( transacted && !connection.isClosed() ) {
- connection.rollback();
- }
- }
- catch( Exception ignore ) {
- log.info( "unable to rollback connection on exception [" + ignore + "]" );
- }
-
- if ( e instanceof HibernateException ) {
- throw ( HibernateException ) e;
- }
- else if ( e instanceof SQLException ) {
- throw sqlExceptionHelper().convert(
- ( SQLException ) e,
- "error performing isolated work"
- );
- }
- else {
- throw new HibernateException( "error performing isolated work", e );
- }
- }
- finally {
- if ( transacted && wasAutoCommit ) {
- try {
- connection.setAutoCommit( true );
- }
- catch( Exception ignore ) {
- log.trace( "was unable to reset connection back to auto-commit" );
- }
- }
- try {
- session.getFactory().getConnectionProvider().closeConnection( connection );
- }
- catch ( Exception ignore ) {
- log.info( "Unable to release isolated connection [" + ignore + "]" );
- }
- }
- }
- catch ( SQLException sqle ) {
- throw sqlExceptionHelper().convert(
- sqle,
- "unable to obtain isolated JDBC connection"
- );
- }
- }
-
- private SQLExceptionHelper sqlExceptionHelper() {
- return session.getFactory().getSQLExceptionHelper();
- }
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/NullSynchronizationException.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/NullSynchronizationException.java
similarity index 89%
rename from hibernate-core/src/main/java/org/hibernate/engine/transaction/NullSynchronizationException.java
rename to hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/NullSynchronizationException.java
index 083ba68072..e4080b7b62 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/transaction/NullSynchronizationException.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/NullSynchronizationException.java
@@ -21,12 +21,12 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.engine.transaction;
+package org.hibernate.engine.transaction.internal;
import org.hibernate.HibernateException;
/**
- * TODO : javadoc
+ * Indicates an attempt to register a null synchronization. Basically a glorified {@link NullPointerException}
*
* @author Steve Ebersole
*/
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/SynchronizationRegistry.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/SynchronizationRegistryImpl.java
similarity index 75%
rename from hibernate-core/src/main/java/org/hibernate/engine/transaction/SynchronizationRegistry.java
rename to hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/SynchronizationRegistryImpl.java
index c0a3ad9e68..ca504aac1b 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/transaction/SynchronizationRegistry.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/SynchronizationRegistryImpl.java
@@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * 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.
@@ -21,7 +21,9 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.engine.transaction;
+package org.hibernate.engine.transaction.internal;
+
+import org.hibernate.engine.transaction.spi.SynchronizationRegistry;
import java.util.LinkedHashSet;
import javax.transaction.Synchronization;
@@ -29,25 +31,17 @@ import javax.transaction.Synchronization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.hibernate.HibernateException;
-
/**
* Manages a registry of {@link Synchronization Synchronizations}.
*
* @author Steve Ebersole
*/
-public class SynchronizationRegistry {
- private static final Logger log = LoggerFactory.getLogger( SynchronizationRegistry.class );
+public class SynchronizationRegistryImpl implements SynchronizationRegistry {
+ private static final Logger log = LoggerFactory.getLogger( SynchronizationRegistryImpl.class );
private LinkedHashSet synchronizations;
- /**
- * Register a user {@link Synchronization} callback for this transaction.
- *
- * @param synchronization The synchronization callback to register.
- *
- * @throws HibernateException
- */
+ @Override
public void registerSynchronization(Synchronization synchronization) {
if ( synchronization == null ) {
throw new NullSynchronizationException();
@@ -63,10 +57,7 @@ public class SynchronizationRegistry {
}
}
- /**
- * Delegate {@link Synchronization#beforeCompletion} calls to {@link #registerSynchronization registered}
- * {@link Synchronization Synchronizations}
- */
+ @Override
public void notifySynchronizationsBeforeTransactionCompletion() {
if ( synchronizations != null ) {
for ( Synchronization synchronization : synchronizations ) {
@@ -80,12 +71,7 @@ public class SynchronizationRegistry {
}
}
- /**
- * Delegate {@link Synchronization#afterCompletion} calls to {@link #registerSynchronization registered}
- * {@link Synchronization Synchronizations}
- *
- * @param status The transaction status (if known) per {@link javax.transaction.Status}
- */
+ @Override
public void notifySynchronizationsAfterTransactionCompletion(int status) {
if ( synchronizations != null ) {
for ( Synchronization synchronization : synchronizations ) {
@@ -98,4 +84,14 @@ public class SynchronizationRegistry {
}
}
}
+
+ /**
+ * Package-protected access to clear registered synchronizations.
+ */
+ void clearSynchronizations() {
+ if ( synchronizations != null ) {
+ synchronizations.clear();
+ synchronizations = null;
+ }
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java
new file mode 100644
index 0000000000..b9d4fc59ff
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java
@@ -0,0 +1,348 @@
+/*
+ * 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 org.hibernate.ConnectionReleaseMode;
+import org.hibernate.ResourceClosedException;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
+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.SynchronizationCallbackCoordinatorImpl;
+import org.hibernate.engine.transaction.synchronization.spi.SynchronizationCallbackCoordinator;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.util.CollectionHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Standard implementation of the Hibernate {@link TransactionCoordinator}
+ *
+ * IMPL NOTE : Custom serialization handling!
+ *
+ * @author Steve Ebersole
+ */
+public class TransactionCoordinatorImpl implements TransactionCoordinator {
+ private static final Logger log = LoggerFactory.getLogger( TransactionCoordinatorImpl.class );
+
+ private final transient TransactionContext transactionContext;
+ private final transient JdbcCoordinatorImpl jdbcCoordinator;
+
+ private final transient List observers;
+ private final transient SynchronizationRegistryImpl synchronizationRegistry;
+
+ private transient TransactionImplementor currentHibernateTransaction;
+
+ private transient SynchronizationCallbackCoordinatorImpl callbackCoordinator;
+
+ private transient boolean open = true;
+ private transient boolean synchronizationRegistered;
+ private transient boolean ownershipTaken;
+
+ public TransactionCoordinatorImpl(
+ Connection userSuppliedConnection,
+ TransactionContext transactionContext) {
+ this.transactionContext = transactionContext;
+ this.jdbcCoordinator = new JdbcCoordinatorImpl( userSuppliedConnection, this );
+ this.observers = new ArrayList();
+ 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 observers) {
+ this.transactionContext = transactionContext;
+ this.jdbcCoordinator = jdbcCoordinator;
+ 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 );
+
+ // IMPL NOTE : reset clears synchronizations (following jta spec), but not observers!
+ synchronizationRegistry.clearSynchronizations();
+ }
+
+ public void afterTransaction(TransactionImplementor hibernateTransaction, int status) {
+ log.trace( "after transaction completion" );
+
+ final boolean success = JtaStatusHelper.isCommitted( status );
+
+ // todo : handle stats as observer?
+ // as is this messes up unit tests which do not build a sf
+// if ( sessionFactory().getStatistics().isStatisticsEnabled() ) {
+// sessionFactory().getStatisticsImplementor().endTransaction( success );
+// }
+
+ getJdbcCoordinator().afterTransaction();
+
+ getTransactionContext().afterTransactionCompletion( hibernateTransaction, success );
+ sendAfterTransactionCompletionNotifications( hibernateTransaction, status );
+ reset();
+ }
+
+ private SessionFactoryImplementor sessionFactory() {
+ return transactionContext.getTransactionEnvironment().getSessionFactory();
+ }
+
+ public boolean isSynchronizationRegistered() {
+ return synchronizationRegistered;
+ }
+
+ @Override
+ @SuppressWarnings( {"unchecked"})
+ public boolean isTransactionInProgress() {
+ return getTransaction().isActive() &&
+ transactionFactory().getJoinStatus( this, getTransaction() ) == JoinStatus.JOINED;
+ }
+
+ @Override
+ public TransactionContext getTransactionContext() {
+ return transactionContext;
+ }
+
+ @Override
+ public JdbcCoordinator getJdbcCoordinator() {
+ return jdbcCoordinator;
+ }
+
+ private TransactionFactory transactionFactory() {
+ return getTransactionEnvironment().getTransactionFactory();
+ }
+
+ private TransactionEnvironment getTransactionEnvironment() {
+ return getTransactionContext().getTransactionEnvironment();
+ }
+
+ @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().getLogicalConnection().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;
+ }
+
+ // Has the local transaction (Hibernate facade) taken on the responsibility of driving the transaction inflow?
+ if ( currentHibernateTransaction.isInitiator() ) {
+ 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
+
+ JtaPlatform jtaPlatform = getTransactionEnvironment().getJtaPlatform();
+ if ( jtaPlatform == null ) {
+ // if no jta platform was registered we wont be able to register a jta synchronization
+ return;
+ }
+
+ // Can we resister a synchronization
+ if ( ! jtaPlatform.canRegisterSynchronization() ) {
+ log.trace( "registered JTA platform says we cannot currently resister synchronization; skipping" );
+ return;
+ }
+
+ // Should we resister a synchronization
+ if ( ! transactionFactory().isJoinableJtaTransaction( this, currentHibernateTransaction ) ) {
+ log.trace( "TransactionFactory reported no JTA transaction to join; skipping Synchronization registration" );
+ return;
+ }
+
+ jtaPlatform.registerSynchronization( new RegisteredSynchronization( getSynchronizationCallbackCoordinator() ) );
+ synchronizationRegistered = true;
+ log.debug( "successfully registered Synchronization" );
+ }
+
+ @Override
+ public SynchronizationCallbackCoordinator getSynchronizationCallbackCoordinator() {
+ if ( callbackCoordinator == null ) {
+ callbackCoordinator = new SynchronizationCallbackCoordinatorImpl( this );
+ }
+ return callbackCoordinator;
+ }
+
+ public void pulse() {
+ log.trace( "Starting transaction coordinator 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
+ @SuppressWarnings( {"unchecked"})
+ public boolean isTransactionJoinable() {
+ return transactionFactory().isJoinableJtaTransaction( this, currentHibernateTransaction );
+ }
+
+ @Override
+ @SuppressWarnings( {"unchecked"})
+ public boolean isTransactionJoined() {
+ return transactionFactory().getJoinStatus( this, currentHibernateTransaction ) == 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 : observers ) {
+ observer.afterCompletion( successful, hibernateTransaction );
+ }
+ synchronizationRegistry.notifySynchronizationsAfterTransactionCompletion( status );
+ }
+
+
+ // 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 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;
+ }
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionFactoryInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionFactoryInitiator.java
new file mode 100644
index 0000000000..a72526ff98
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionFactoryInitiator.java
@@ -0,0 +1,96 @@
+/*
+ * 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.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.HibernateException;
+import org.hibernate.cfg.Environment;
+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.spi.TransactionFactory;
+import org.hibernate.service.classloading.spi.ClassLoaderService;
+import org.hibernate.service.spi.ServiceInitiator;
+import org.hibernate.service.spi.ServiceRegistry;
+
+/**
+ * Standard instantiator for the standard {@link TransactionFactory} service.
+ *
+ * @author Steve Ebersole
+ */
+public class TransactionFactoryInitiator implements ServiceInitiator {
+ private static final Logger log = LoggerFactory.getLogger( TransactionFactoryInitiator.class );
+
+ public static final TransactionFactoryInitiator INSTANCE = new TransactionFactoryInitiator();
+
+ @Override
+ public Class getServiceInitiated() {
+ return TransactionFactory.class;
+ }
+
+ @Override
+ public TransactionFactory initiateService(Map configVales, ServiceRegistry registry) {
+ final Object strategy = configVales.get( Environment.TRANSACTION_STRATEGY );
+ if ( TransactionFactory.class.isInstance( strategy ) ) {
+ return (TransactionFactory) strategy;
+ }
+
+ if ( strategy == null ) {
+ log.info( "Using default transaction strategy (direct JDBC transactions)" );
+ return new JdbcTransactionFactory();
+ }
+
+ final String strategyClassName = mapLegacyNames( strategy.toString() );
+ log.info( "Transaction strategy: " + strategyClassName );
+
+ ClassLoaderService classLoaderService = registry.getService( ClassLoaderService.class );
+ try {
+ return (TransactionFactory) classLoaderService.classForName( strategyClassName ).newInstance();
+ }
+ catch ( Exception e ) {
+ throw new HibernateException( "Unable to instantiate specified TransactionFactory class [" + strategyClassName + "]", e );
+ }
+ }
+
+ private String mapLegacyNames(String name) {
+ if ( "org.hibernate.transaction.JDBCTransactionFactory".equals( name ) ) {
+ return JdbcTransactionFactory.class.getName();
+ }
+
+ if ( "org.hibernate.transaction.JTATransactionFactory".equals( name ) ) {
+ return JtaTransactionFactory.class.getName();
+ }
+
+ if ( "org.hibernate.transaction.CMTTransactionFactory".equals( name ) ) {
+ return CMTTransactionFactory.class.getName();
+ }
+
+ return name;
+ }
+}
+
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jdbc/JdbcIsolationDelegate.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jdbc/JdbcIsolationDelegate.java
new file mode 100644
index 0000000000..01a4e611d2
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jdbc/JdbcIsolationDelegate.java
@@ -0,0 +1,123 @@
+/*
+ * 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.jdbc;
+
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.HibernateException;
+import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
+import org.hibernate.engine.transaction.spi.IsolationDelegate;
+import org.hibernate.engine.transaction.spi.TransactionCoordinator;
+import org.hibernate.jdbc.Work;
+import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+
+/**
+ * The isolation delegate for JDBC {@link Connection} based transactions
+ *
+ * @author Steve Ebersole
+ */
+public class JdbcIsolationDelegate implements IsolationDelegate {
+ private static final Logger log = LoggerFactory.getLogger( JdbcIsolationDelegate.class );
+
+ private final TransactionCoordinator transactionCoordinator;
+
+ public JdbcIsolationDelegate(TransactionCoordinator transactionCoordinator) {
+ this.transactionCoordinator = transactionCoordinator;
+ }
+
+ protected ConnectionProvider connectionProvider() {
+ return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getJdbcServices().getConnectionProvider();
+ }
+
+ protected SQLExceptionHelper sqlExceptionHelper() {
+ return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getJdbcServices().getSqlExceptionHelper();
+ }
+
+ @Override
+ public void delegateWork(Work work, boolean transacted) throws HibernateException {
+ boolean wasAutoCommit = false;
+ try {
+ // todo : should we use a connection proxy here?
+ Connection connection = connectionProvider().getConnection();
+ try {
+ if ( transacted ) {
+ if ( connection.getAutoCommit() ) {
+ wasAutoCommit = true;
+ connection.setAutoCommit( false );
+ }
+ }
+
+ work.execute( connection );
+
+ if ( transacted ) {
+ connection.commit();
+ }
+ }
+ catch ( Exception e ) {
+ try {
+ if ( transacted && !connection.isClosed() ) {
+ connection.rollback();
+ }
+ }
+ catch ( Exception ignore ) {
+ log.info( "unable to rollback connection on exception [" + ignore + "]" );
+ }
+
+ if ( e instanceof HibernateException ) {
+ throw (HibernateException) e;
+ }
+ else if ( e instanceof SQLException ) {
+ throw sqlExceptionHelper().convert( (SQLException) e, "error performing isolated work" );
+ }
+ else {
+ throw new HibernateException( "error performing isolated work", e );
+ }
+ }
+ finally {
+ if ( transacted && wasAutoCommit ) {
+ try {
+ connection.setAutoCommit( true );
+ }
+ catch ( Exception ignore ) {
+ log.trace( "was unable to reset connection back to auto-commit" );
+ }
+ }
+ try {
+ connectionProvider().closeConnection( connection );
+ }
+ catch ( Exception ignore ) {
+ log.info( "Unable to release isolated connection [" + ignore + "]" );
+ }
+ }
+ }
+ catch ( SQLException sqle ) {
+ throw sqlExceptionHelper().convert( sqle, "unable to obtain isolated JDBC connection" );
+ }
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jdbc/JdbcTransaction.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jdbc/JdbcTransaction.java
new file mode 100644
index 0000000000..9896ffe917
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jdbc/JdbcTransaction.java
@@ -0,0 +1,208 @@
+/*
+ * 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.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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * {@link org.hibernate.Transaction} implementation based on transaction management through a JDBC {@link java.sql.Connection}.
+ *
+ * This the default transaction strategy.
+ *
+ * @author Anton van Straaten
+ * @author Gavin King
+ * @author Steve Ebersole
+ */
+public class JdbcTransaction extends AbstractTransactionImpl {
+ private static final Logger log = LoggerFactory.getLogger( JdbcTransaction.class );
+
+ 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();
+ if ( log.isDebugEnabled() ) {
+ log.debug( "initial autocommit status: " + 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.info( "Could not close session; swallowing exception as transaction completed", 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;
+ }
+}
\ No newline at end of file
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jdbc/JdbcTransactionFactory.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jdbc/JdbcTransactionFactory.java
new file mode 100644
index 0000000000..494d886dcf
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jdbc/JdbcTransactionFactory.java
@@ -0,0 +1,71 @@
+/*
+ * 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.JoinStatus;
+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 {
+ @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;
+ }
+
+ @Override
+ public JoinStatus getJoinStatus(TransactionCoordinator transactionCoordinator, JdbcTransaction transaction) {
+ return transaction.getJoinStatus();
+ }
+}
\ No newline at end of file
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/CMTTransaction.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/CMTTransaction.java
new file mode 100644
index 0000000000..1600f20930
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/CMTTransaction.java
@@ -0,0 +1,154 @@
+/*
+ * 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 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;
+
+import javax.transaction.SystemException;
+import javax.transaction.TransactionManager;
+
+/**
+ * Implements a transaction strategy for Container Managed Transaction (CMT) scenarios. All work is done in
+ * the context of the container managed transaction.
+ *
+ * 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.
+ *
+ * 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 {
+ 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 join() {
+ // todo : implement method body
+ }
+
+ @Override
+ public void resetJoinStatus() {
+ // todo : implement method body
+ }
+
+ boolean isJoinable() {
+ return JtaStatusHelper.isActive( transactionManager() );
+ }
+
+ @Override
+ public JoinStatus getJoinStatus() {
+ return isJoinable() ? JoinStatus.JOINED : JoinStatus.NOT_JOINED;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/CMTTransactionFactory.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/CMTTransactionFactory.java
old mode 100755
new mode 100644
similarity index 50%
rename from hibernate-core/src/main/java/org/hibernate/transaction/CMTTransactionFactory.java
rename to hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/CMTTransactionFactory.java
index fac6e191d1..42a79256ce
--- a/hibernate-core/src/main/java/org/hibernate/transaction/CMTTransactionFactory.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/CMTTransactionFactory.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * 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 Middleware LLC.
+ * 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
@@ -20,60 +20,64 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
-package org.hibernate.transaction;
-
-import java.util.Properties;
+package org.hibernate.engine.transaction.internal.jta;
import org.hibernate.ConnectionReleaseMode;
-import org.hibernate.HibernateException;
-import org.hibernate.Transaction;
import org.hibernate.TransactionException;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-import org.hibernate.util.JTAHelper;
+import org.hibernate.engine.transaction.spi.JoinStatus;
+import org.hibernate.engine.transaction.spi.TransactionCoordinator;
+import org.hibernate.engine.transaction.spi.TransactionFactory;
import javax.transaction.SystemException;
/**
- * Factory for {@link CMTTransaction} instances.
+ * Factory for Container Managed Transaction (CMT) based transaction facades.
*
+ * @author Steve Ebersole
* @author Gavin King
*/
-public class CMTTransactionFactory implements TransactionFactory {
+public class CMTTransactionFactory implements TransactionFactory {
+ @Override
+ public CMTTransaction createTransaction(TransactionCoordinator transactionCoordinator) {
+ return new CMTTransaction( transactionCoordinator );
+ }
+ @Override
+ public boolean canBeDriver() {
+ return false;
+ }
+
+ @Override
public ConnectionReleaseMode getDefaultReleaseMode() {
return ConnectionReleaseMode.AFTER_STATEMENT;
}
- public void configure(Properties props) throws HibernateException {}
-
- public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)
- throws HibernateException {
- return new CMTTransaction(jdbcContext, transactionContext);
- }
-
- public boolean isTransactionManagerRequired() {
+ @Override
+ public boolean compatibleWithJtaSynchronization() {
return true;
}
- public boolean areCallbacksLocalToHibernateTransactions() {
- return false;
- }
-
- public boolean isTransactionInProgress(
- JDBCContext jdbcContext,
- Context transactionContext,
- Transaction transaction) {
+ @Override
+ public boolean isJoinableJtaTransaction(TransactionCoordinator transactionCoordinator, CMTTransaction transaction) {
try {
- return JTAHelper.isTransactionInProgress(
- transactionContext.getFactory().getTransactionManager().getTransaction()
- );
+ final int status = transactionCoordinator
+ .getTransactionContext()
+ .getTransactionEnvironment()
+ .getJtaPlatform()
+ .retrieveTransactionManager()
+ .getStatus();
+ return JtaStatusHelper.isActive( status );
}
catch( SystemException se ) {
throw new TransactionException( "Unable to check transaction status", se );
}
+ }
+
+ @Override
+ public JoinStatus getJoinStatus(TransactionCoordinator transactionCoordinator, CMTTransaction transaction) {
+ return null; // todo : implement method body
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaIsolationDelegate.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaIsolationDelegate.java
new file mode 100644
index 0000000000..7e071428fe
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaIsolationDelegate.java
@@ -0,0 +1,185 @@
+/*
+ * 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.jta;
+
+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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.HibernateException;
+import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
+import org.hibernate.engine.transaction.spi.IsolationDelegate;
+import org.hibernate.engine.transaction.spi.TransactionCoordinator;
+import org.hibernate.jdbc.Work;
+import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+
+/**
+ * An isolation delegate for JTA environments.
+ *
+ * @author Steve Ebersole
+ */
+public class JtaIsolationDelegate implements IsolationDelegate {
+ private static final Logger log = LoggerFactory.getLogger( JtaIsolationDelegate.class );
+
+ private final TransactionCoordinator transactionCoordinator;
+
+ public JtaIsolationDelegate(TransactionCoordinator transactionCoordinator) {
+ this.transactionCoordinator = transactionCoordinator;
+ }
+
+ protected TransactionManager transactionManager() {
+ return transactionCoordinator.getTransactionContext()
+ .getTransactionEnvironment()
+ .getJtaPlatform()
+ .retrieveTransactionManager();
+ }
+
+ protected ConnectionProvider connectionProvider() {
+ return transactionCoordinator.getTransactionContext()
+ .getTransactionEnvironment()
+ .getJdbcServices()
+ .getConnectionProvider();
+ }
+
+ protected SQLExceptionHelper sqlExceptionHelper() {
+ return transactionCoordinator.getTransactionContext()
+ .getTransactionEnvironment()
+ .getJdbcServices()
+ .getSqlExceptionHelper();
+ }
+
+ @Override
+ public void delegateWork(Work work, boolean transacted) throws HibernateException {
+ TransactionManager transactionManager = transactionManager();
+
+ try {
+ // First we suspend any current JTA transaction
+ Transaction surroundingTransaction = transactionManager.suspend();
+ if ( log.isDebugEnabled() ) {
+ log.debug( "surrounding JTA transaction suspended [" + surroundingTransaction + "]" );
+ }
+
+ boolean hadProblems = false;
+ try {
+ // then perform the requested work
+ if ( transacted ) {
+ doTheWorkInNewTransaction( work, transactionManager );
+ }
+ else {
+ doTheWorkInNoTransaction( work );
+ }
+ }
+ catch ( HibernateException e ) {
+ hadProblems = true;
+ throw e;
+ }
+ finally {
+ try {
+ transactionManager.resume( surroundingTransaction );
+ if ( log.isDebugEnabled() ) {
+ log.debug( "surrounding JTA transaction resumed [" + surroundingTransaction + "]" );
+ }
+ }
+ catch( Throwable t ) {
+ // if the actually work had an error use that, otherwise error based on t
+ if ( !hadProblems ) {
+ //noinspection ThrowFromFinallyBlock
+ throw new HibernateException( "Unable to resume previously suspended transaction", t );
+ }
+ }
+ }
+ }
+ catch ( SystemException e ) {
+ throw new HibernateException( "Unable to suspend current JTA transaction", e );
+ }
+ }
+
+ private void doTheWorkInNewTransaction(Work work, TransactionManager transactionManager) {
+ try {
+ // start the new isolated transaction
+ transactionManager.begin();
+
+ try {
+ doTheWork( work );
+ // if everythign went ok, commit the isolated transaction
+ transactionManager.commit();
+ }
+ catch ( Exception e ) {
+ try {
+ transactionManager.rollback();
+ }
+ catch ( Exception ignore ) {
+ log.info( "Unable to rollback isolated transaction on error [" + e + "] : [" + ignore + "]" );
+ }
+ }
+ }
+ catch ( SystemException e ) {
+ throw new HibernateException( "Unable to start isolated transaction", e );
+ }
+ catch ( NotSupportedException e ) {
+ throw new HibernateException( "Unable to start isolated transaction", e );
+ }
+ }
+
+ private void doTheWorkInNoTransaction(Work work) {
+ doTheWork( work );
+ }
+
+ private void doTheWork(Work work) {
+ try {
+ // obtain our isolated connection
+ Connection connection = connectionProvider().getConnection();
+ try {
+ // do the actual work
+ work.execute( connection );
+ }
+ catch ( HibernateException e ) {
+ throw e;
+ }
+ catch ( Exception e ) {
+ throw new HibernateException( "Unable to perform isolated work", e );
+ }
+ finally {
+ try {
+ // no matter what, release the connection (handle)
+ connectionProvider().closeConnection( connection );
+ }
+ catch ( Throwable ignore ) {
+ log.info( "Unable to release isolated connection [" + ignore + "]" );
+ }
+ }
+ }
+ catch ( SQLException sqle ) {
+ throw sqlExceptionHelper().convert( sqle, "unable to obtain isolated JDBC connection" );
+ }
+ }
+
+}
+
diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/jta/JtaStatusHelper.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaStatusHelper.java
similarity index 89%
rename from hibernate-core/src/main/java/org/hibernate/internal/util/jta/JtaStatusHelper.java
rename to hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaStatusHelper.java
index d9c2c05e45..639dea75c7 100644
--- a/hibernate-core/src/main/java/org/hibernate/internal/util/jta/JtaStatusHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaStatusHelper.java
@@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * 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.
@@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.internal.util.jta;
+package org.hibernate.engine.transaction.internal.jta;
import javax.transaction.Status;
import javax.transaction.SystemException;
@@ -31,7 +31,7 @@ import javax.transaction.UserTransaction;
import org.hibernate.TransactionException;
/**
- * Utility for dealing with JTA statses.
+ * Utility for dealing with JTA statuses.
*
* @author Steve Ebersole
*/
@@ -49,7 +49,7 @@ public class JtaStatusHelper {
try {
final int status = userTransaction.getStatus();
if ( status == Status.STATUS_UNKNOWN ) {
- throw new TransactionException( "UserTransaction reported transaction status as unknwon" );
+ throw new TransactionException( "UserTransaction reported transaction status as unknown" );
}
return status;
}
@@ -97,7 +97,7 @@ public class JtaStatusHelper {
*
* @param userTransaction The {@link UserTransaction} whose status is to be checked
*
- * @return True if the transactiion is active; false otherwise.
+ * @return True if the transaction is active; false otherwise.
*/
public static boolean isActive(UserTransaction userTransaction) {
final int status = getStatus( userTransaction );
@@ -109,7 +109,7 @@ public class JtaStatusHelper {
*
* @param transactionManager The {@link TransactionManager} whose status is to be checked
*
- * @return True if the transactiion is active; false otherwise.
+ * @return True if the transaction is active; false otherwise.
*/
public static boolean isActive(TransactionManager transactionManager) {
return isActive( getStatus( transactionManager ) );
@@ -133,7 +133,7 @@ public class JtaStatusHelper {
*
* @param userTransaction The {@link UserTransaction} whose status is to be checked
*
- * @return True if the transactiion indicates roll back; false otherwise.
+ * @return True if the transaction indicates roll back; false otherwise.
*/
public static boolean isRollback(UserTransaction userTransaction) {
return isRollback( getStatus( userTransaction ) );
@@ -144,7 +144,7 @@ public class JtaStatusHelper {
*
* @param transactionManager The {@link TransactionManager} whose status is to be checked
*
- * @return True if the transactiion indicates roll back; false otherwise.
+ * @return True if the transaction indicates roll back; false otherwise.
*/
public static boolean isRollback(TransactionManager transactionManager) {
return isRollback( getStatus( transactionManager ) );
@@ -158,9 +158,7 @@ public class JtaStatusHelper {
* @return True if the code indicates a roll back; false otherwise.
*/
public static boolean isCommitted(int status) {
- return status == Status.STATUS_MARKED_ROLLBACK ||
- status == Status.STATUS_ROLLING_BACK ||
- status == Status.STATUS_ROLLEDBACK;
+ return status == Status.STATUS_COMMITTED;
}
/**
@@ -168,7 +166,7 @@ public class JtaStatusHelper {
*
* @param userTransaction The {@link UserTransaction} whose status is to be checked
*
- * @return True if the transactiion indicates commit; false otherwise.
+ * @return True if the transaction indicates commit; false otherwise.
*/
public static boolean isCommitted(UserTransaction userTransaction) {
return isCommitted( getStatus( userTransaction ) );
@@ -179,7 +177,7 @@ public class JtaStatusHelper {
*
* @param transactionManager The {@link TransactionManager} whose status is to be checked
*
- * @return True if the transactiion indicates commit; false otherwise.
+ * @return True if the transaction indicates commit; false otherwise.
*/
public static boolean isCommitted(TransactionManager transactionManager) {
return isCommitted( getStatus( transactionManager ) );
@@ -192,6 +190,7 @@ public class JtaStatusHelper {
*
* @return True if the code indicates a roll back; false otherwise.
*/
+ @SuppressWarnings( {"UnusedDeclaration"})
public static boolean isMarkedForRollback(int status) {
return status == Status.STATUS_MARKED_ROLLBACK;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaTransaction.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaTransaction.java
new file mode 100644
index 0000000000..1c06032bf5
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaTransaction.java
@@ -0,0 +1,276 @@
+/*
+ * 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 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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * 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 Logger log = LoggerFactory.getLogger( 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 = jtaPlatform().retrieveUserTransaction();
+ if ( userTransaction == null ) {
+ throw new TransactionException( "Unable to locate JTA UserTransaction" );
+ }
+
+ 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 );
+ }
+
+ }
+
+ @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 );
+ }
+ finally {
+ isInitiator = false;
+ }
+ }
+
+ @Override
+ protected void afterTransactionCompletion(int status) {
+ // nothing to do
+ }
+
+ @Override
+ protected void afterAfterCompletion() {
+ // this method is a noop if there is a Synchronization!
+ if ( isDriver ) {
+ if ( !isInitiator ) {
+ log.warn( "You should set hibernate.transaction.manager_lookup_class if cache is enabled" );
+ }
+ try {
+ transactionCoordinator().afterTransaction( this, userTransaction.getStatus() );
+ }
+ catch (SystemException e) {
+ throw new TransactionException( "Unable to determine UserTransaction status", e );
+ }
+ }
+ }
+
+ @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 {
+ 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;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaTransactionFactory.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaTransactionFactory.java
new file mode 100644
index 0000000000..3c258bdcbd
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/jta/JtaTransactionFactory.java
@@ -0,0 +1,109 @@
+/*
+ * 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 org.hibernate.ConnectionReleaseMode;
+import org.hibernate.TransactionException;
+import org.hibernate.engine.transaction.spi.JoinStatus;
+import org.hibernate.engine.transaction.spi.TransactionCoordinator;
+import org.hibernate.engine.transaction.spi.TransactionFactory;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.util.JTAHelper;
+
+import javax.transaction.SystemException;
+import javax.transaction.UserTransaction;
+
+/**
+ * Factory for {@link JtaTransaction} instances.
+ *
+ * @author Gavin King
+ * @author Steve Ebersole
+ * @author Les Hazlewood
+ */
+public class JtaTransactionFactory implements TransactionFactory {
+ @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 JTAHelper.isInProgress( ut.getStatus() );
+ }
+ }
+
+ 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 && JTAHelper.isInProgress( ut.getStatus() );
+ }
+ }
+ catch ( SystemException se ) {
+ throw new TransactionException( "Unable to check transaction status", se );
+ }
+ }
+
+ @Override
+ public JoinStatus getJoinStatus(TransactionCoordinator transactionCoordinator, JtaTransaction transaction) {
+ return null; // todo : implement method body
+ }
+
+}
\ No newline at end of file
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/AbstractTransactionImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/AbstractTransactionImpl.java
new file mode 100644
index 0000000000..e8b41ae045
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/AbstractTransactionImpl.java
@@ -0,0 +1,237 @@
+/*
+ * 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.HibernateException;
+import org.hibernate.TransactionException;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+
+/**
+ * Abstract support for creating {@link TransactionImplementor transaction} implementations
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractTransactionImpl implements TransactionImplementor {
+ private static final Logger log = LoggerFactory.getLogger( 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.service.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 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 resetJoinStatus() {
+ // generally speaking this is no-op
+ }
+
+ @Override
+ public void join() {
+ // generally speaking this is no-op
+ }
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/IsolationDelegate.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/IsolationDelegate.java
new file mode 100644
index 0000000000..68935e95f4
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/IsolationDelegate.java
@@ -0,0 +1,44 @@
+/*
+ * 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.HibernateException;
+import org.hibernate.jdbc.Work;
+
+/**
+ * Contract for performing work in a manner that isolates it from any current transaction.
+ *
+ * @author Steve Ebersole
+ */
+public interface IsolationDelegate {
+ /**
+ * Perform the given work in isolation from current transaction.
+ *
+ * @param work The work to be performed.
+ * @param transacted Should the work itself be done in a (isolated) transaction?
+ *
+ * @throws HibernateException Indicates a problem performing the work.
+ */
+ public void delegateWork(Work work, boolean transacted) throws HibernateException;
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/synchronization/AfterCompletionAction.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/JoinStatus.java
similarity index 77%
rename from hibernate-core/src/main/java/org/hibernate/transaction/synchronization/AfterCompletionAction.java
rename to hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/JoinStatus.java
index 29a6d14ffb..f81c71d4ab 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/synchronization/AfterCompletionAction.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/JoinStatus.java
@@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * 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.
@@ -21,15 +21,16 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.transaction.synchronization;
-
-import org.hibernate.transaction.TransactionFactory;
+package org.hibernate.engine.transaction.spi;
/**
- * TODO : javadoc
+ * See the JPA notion of joining a transaction for details.
*
+ * @author Emmanuel Bernard
* @author Steve Ebersole
*/
-public interface AfterCompletionAction {
- public void doAction(TransactionFactory.Context ctx, int status);
+public enum JoinStatus {
+ NOT_JOINED,
+ MARKED_FOR_JOINED,
+ JOINED
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/LocalStatus.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/LocalStatus.java
new file mode 100644
index 0000000000..ef9343c825
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/LocalStatus.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+/**
+ * Enumeration of statuses in which a local transaction facade ({@link org.hibernate.Transaction}) might be.
+ *
+ * @author Steve Ebersole
+ */
+public enum LocalStatus {
+ /**
+ * The local transaction has not yet been begun
+ */
+ NOT_ACTIVE,
+ /**
+ * The local transaction has been begun, but not yet completed.
+ */
+ ACTIVE,
+ /**
+ * The local transaction has been competed successfully.
+ */
+ COMMITTED,
+ /**
+ * The local transaction has been rolled back.
+ */
+ ROLLED_BACK,
+ /**
+ * The local transaction attempted to commit, but failed.
+ */
+ FAILED_COMMIT
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/SynchronizationRegistry.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/SynchronizationRegistry.java
new file mode 100644
index 0000000000..bad7582a6f
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/SynchronizationRegistry.java
@@ -0,0 +1,57 @@
+/*
+ * 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.Synchronization;
+import java.io.Serializable;
+
+/**
+ * Manages a registry of {@link Synchronization Synchronizations}.
+ *
+ * @author Steve Ebersole
+ */
+public interface SynchronizationRegistry extends Serializable {
+ /**
+ * Register a user {@link Synchronization} callback for this transaction.
+ *
+ * @param synchronization The synchronization callback to register.
+ *
+ * @throws org.hibernate.HibernateException
+ */
+ public void registerSynchronization(Synchronization synchronization);
+
+ /**
+ * Delegate {@link Synchronization#beforeCompletion} calls to the {@link #registerSynchronization registered}
+ * {@link Synchronization Synchronizations}
+ */
+ void notifySynchronizationsBeforeTransactionCompletion();
+
+ /**
+ * Delegate {@link Synchronization#afterCompletion} calls to {@link #registerSynchronization registered}
+ * {@link Synchronization Synchronizations}
+ *
+ * @param status The transaction status (if known) per {@link javax.transaction.Status}
+ */
+ void notifySynchronizationsAfterTransactionCompletion(int status);
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionContext.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionContext.java
new file mode 100644
index 0000000000..7737980758
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionContext.java
@@ -0,0 +1,105 @@
+/*
+ * 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 java.io.Serializable;
+
+/**
+ * Access to services needed in the context of processing transaction requests.
+ *
+ * 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 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);
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionCoordinator.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionCoordinator.java
new file mode 100644
index 0000000000..05ad71ab67
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionCoordinator.java
@@ -0,0 +1,139 @@
+/*
+ * 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.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.engine.transaction.synchronization.spi.SynchronizationCallbackCoordinator;
+
+import java.io.Serializable;
+import java.sql.Connection;
+
+/**
+ * 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.
+ *
+ * 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);
+
+ /**
+ * 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.
+ *
+ * @see TransactionFactory#getJoinStatus(TransactionCoordinator, TransactionImplementor)
+ */
+ 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);
+
+}
\ No newline at end of file
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionEnvironment.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionEnvironment.java
new file mode 100644
index 0000000000..b916a41b99
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionEnvironment.java
@@ -0,0 +1,63 @@
+/*
+ * 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.engine.SessionFactoryImplementor;
+import org.hibernate.engine.jdbc.spi.JdbcServices;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+
+/**
+ * Provides access to transactional services.
+ *
+ * @author Steve Ebersole
+ */
+public interface TransactionEnvironment {
+ /**
+ * 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();
+
+ /**
+ * 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();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionFactory.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionFactory.java
new file mode 100644
index 0000000000..3688dd8fe3
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionFactory.java
@@ -0,0 +1,93 @@
+/*
+ * 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.spi.Service;
+
+/**
+ * Contract for transaction creation, as well as providing metadata and contextual information about that creation.
+ *
+ * @author Steve Ebersole
+ */
+public interface TransactionFactory 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}.
+ *
+ * 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);
+
+ /**
+ * Retrieve the current join status of the Hibernate transaction
+ *
+ * @param transactionCoordinator The transaction coordinator
+ * @param transaction The current Hibernate transaction
+ *
+ * @return The join status.
+ */
+ public JoinStatus getJoinStatus(TransactionCoordinator transactionCoordinator, T transaction);
+
+ /**
+ * Get the default connection release mode.
+ *
+ * @return The default release mode associated with this strategy
+ */
+ public ConnectionReleaseMode getDefaultReleaseMode();
+
+}
+
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionImplementor.java
new file mode 100644
index 0000000000..57de1d3dfd
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionImplementor.java
@@ -0,0 +1,67 @@
+/*
+ * 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.Transaction;
+
+/**
+ * Additional contract for implementors of the Hibernate {@link Transaction} API.
+ *
+ * @author Steve Ebersole
+ */
+public interface TransactionImplementor extends Transaction {
+ /**
+ * Retrieve an isolation delegate appropriate for this transaction strategy.
+ *
+ * @return An isolation delegate.
+ */
+ public IsolationDelegate createIsolationDelegate();
+
+ /**
+ * Get the current state of this transaction's join status.
+ *
+ * @return The current join status
+ */
+ public JoinStatus getJoinStatus();
+
+ /**
+ * Perform a join to the underlying transaction
+ */
+ public void join();
+
+ /**
+ * Reset this transaction's join status.
+ */
+ public void resetJoinStatus();
+
+ /**
+ * Make a best effort to mark the underlying transaction for rollback only.
+ */
+ public void markRollbackOnly();
+
+ /**
+ * Called after completion of the underlying transaction to signify the facade is no longer valid.
+ */
+ public void invalidate();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionObserver.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionObserver.java
new file mode 100644
index 0000000000..5a3472f046
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionObserver.java
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+/**
+ * Observer of internal transaction events.
+ *
+ * @author Steve Ebersole
+ */
+public interface TransactionObserver {
+ /**
+ * Callback for processing the beginning of a transaction.
+ *
+ * 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);
+
+ /**
+ * Callback for processing the initial phase of transaction completion.
+ *
+ * @param transaction The Hibernate transaction
+ */
+ public void beforeCompletion(TransactionImplementor transaction);
+
+ /**
+ * 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);
+}
+
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/synchronization/HibernateSynchronizationImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/internal/RegisteredSynchronization.java
similarity index 60%
rename from hibernate-core/src/main/java/org/hibernate/transaction/synchronization/HibernateSynchronizationImpl.java
rename to hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/internal/RegisteredSynchronization.java
index 5cd3c5ba48..c8651d8217 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/synchronization/HibernateSynchronizationImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/internal/RegisteredSynchronization.java
@@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * 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.
@@ -21,26 +21,26 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.transaction.synchronization;
-
-import javax.transaction.Synchronization;
+package org.hibernate.engine.transaction.synchronization.internal;
+import org.hibernate.engine.transaction.synchronization.spi.SynchronizationCallbackCoordinator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.transaction.Synchronization;
+
/**
- * The {@link Synchronization} implementation Hibernate registers with the JTA {@link javax.transaction.Transaction}
+ * The JTA {@link javax.transaction.Synchronization} Hibernate registers when needed for JTA callbacks
*
- * @author Gavin King
* @author Steve Ebersole
*/
-public class HibernateSynchronizationImpl implements Synchronization {
- private static final Logger log = LoggerFactory.getLogger( HibernateSynchronizationImpl.class );
+public class RegisteredSynchronization implements Synchronization {
+ private static final Logger log = LoggerFactory.getLogger( RegisteredSynchronization.class );
- private final CallbackCoordinator coordinator;
+ private final SynchronizationCallbackCoordinator synchronizationCallbackCoordinator;
- public HibernateSynchronizationImpl(CallbackCoordinator coordinator) {
- this.coordinator = coordinator;
+ public RegisteredSynchronization(SynchronizationCallbackCoordinator synchronizationCallbackCoordinator) {
+ this.synchronizationCallbackCoordinator = synchronizationCallbackCoordinator;
}
/**
@@ -48,7 +48,7 @@ public class HibernateSynchronizationImpl implements Synchronization {
*/
public void beforeCompletion() {
log.trace( "JTA sync : beforeCompletion()" );
- coordinator.beforeCompletion();
+ synchronizationCallbackCoordinator.beforeCompletion();
}
/**
@@ -56,6 +56,6 @@ public class HibernateSynchronizationImpl implements Synchronization {
*/
public void afterCompletion(int status) {
log.trace( "JTA sync : afterCompletion({})", status );
- coordinator.afterCompletion( status );
+ synchronizationCallbackCoordinator.afterCompletion( status );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/synchronization/CallbackCoordinator.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/internal/SynchronizationCallbackCoordinatorImpl.java
similarity index 53%
rename from hibernate-core/src/main/java/org/hibernate/transaction/synchronization/CallbackCoordinator.java
rename to hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/internal/SynchronizationCallbackCoordinatorImpl.java
index 3f42cc2d8c..ff0ba26775 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/synchronization/CallbackCoordinator.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/internal/SynchronizationCallbackCoordinatorImpl.java
@@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * 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.
@@ -21,75 +21,57 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.transaction.synchronization;
-
-import javax.transaction.Status;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
+package org.hibernate.engine.transaction.synchronization.internal;
+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.SynchronizationCallbackCoordinator;
+import org.hibernate.engine.transaction.synchronization.spi.ExceptionMapper;
+import org.hibernate.engine.transaction.synchronization.spi.ManagedFlushChecker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.hibernate.TransactionException;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-import org.hibernate.transaction.TransactionFactory;
-import org.hibernate.util.JTAHelper;
+import javax.transaction.SystemException;
/**
* Manages callbacks from the {@link javax.transaction.Synchronization} registered by Hibernate.
*
* @author Steve Ebersole
*/
-public class CallbackCoordinator {
- private static final Logger log = LoggerFactory.getLogger( CallbackCoordinator.class );
+public class SynchronizationCallbackCoordinatorImpl implements SynchronizationCallbackCoordinator {
+ private static final Logger log = LoggerFactory.getLogger( SynchronizationCallbackCoordinatorImpl.class );
- private final TransactionFactory.Context ctx;
- private JDBCContext jdbcContext;
- private final Transaction jtaTransaction;
- private final org.hibernate.Transaction hibernateTransaction;
+ private final TransactionCoordinator transactionCoordinator;
- private BeforeCompletionManagedFlushChecker beforeCompletionManagedFlushChecker;
+ private ManagedFlushChecker managedFlushChecker;
private AfterCompletionAction afterCompletionAction;
private ExceptionMapper exceptionMapper;
- public CallbackCoordinator(
- TransactionFactory.Context ctx,
- JDBCContext jdbcContext,
- Transaction jtaTransaction,
- org.hibernate.Transaction hibernateTransaction) {
- this.ctx = ctx;
- this.jdbcContext = jdbcContext;
- this.jtaTransaction = jtaTransaction;
- this.hibernateTransaction = hibernateTransaction;
+ public SynchronizationCallbackCoordinatorImpl(TransactionCoordinator transactionCoordinator) {
+ this.transactionCoordinator = transactionCoordinator;
reset();
}
public void reset() {
- beforeCompletionManagedFlushChecker = STANDARD_MANAGED_FLUSH_CHECKER;
+ managedFlushChecker = STANDARD_MANAGED_FLUSH_CHECKER;
exceptionMapper = STANDARD_EXCEPTION_MAPPER;
afterCompletionAction = STANDARD_AFTER_COMPLETION_ACTION;
}
- public BeforeCompletionManagedFlushChecker getBeforeCompletionManagedFlushChecker() {
- return beforeCompletionManagedFlushChecker;
- }
-
- public void setBeforeCompletionManagedFlushChecker(BeforeCompletionManagedFlushChecker beforeCompletionManagedFlushChecker) {
- this.beforeCompletionManagedFlushChecker = beforeCompletionManagedFlushChecker;
- }
-
- public ExceptionMapper getExceptionMapper() {
- return exceptionMapper;
+ @Override
+ public void setManagedFlushChecker(ManagedFlushChecker managedFlushChecker) {
+ this.managedFlushChecker = managedFlushChecker;
}
+ @Override
public void setExceptionMapper(ExceptionMapper exceptionMapper) {
this.exceptionMapper = exceptionMapper;
}
- public AfterCompletionAction getAfterCompletionAction() {
- return afterCompletionAction;
- }
-
+ @Override
public void setAfterCompletionAction(AfterCompletionAction afterCompletionAction) {
this.afterCompletionAction = afterCompletionAction;
}
@@ -102,7 +84,12 @@ public class CallbackCoordinator {
boolean flush;
try {
- flush = beforeCompletionManagedFlushChecker.shouldDoManagedFlush( ctx, jtaTransaction );
+ final int status = transactionCoordinator
+ .getTransactionContext()
+ .getTransactionEnvironment()
+ .getJtaPlatform()
+ .getCurrentStatus();
+ flush = managedFlushChecker.shouldDoManagedFlush( transactionCoordinator, status );
}
catch ( SystemException se ) {
setRollbackOnly();
@@ -112,7 +99,7 @@ public class CallbackCoordinator {
try {
if ( flush ) {
log.trace( "automatically flushing session" );
- ctx.managedFlush();
+ transactionCoordinator.getTransactionContext().managedFlush();
}
}
catch ( RuntimeException re ) {
@@ -120,48 +107,41 @@ public class CallbackCoordinator {
throw exceptionMapper.mapManagedFlushFailure( "error during managed flush", re );
}
finally {
- jdbcContext.beforeTransactionCompletion( hibernateTransaction );
+ transactionCoordinator.sendBeforeTransactionCompletionNotifications( null );
+ transactionCoordinator.getTransactionContext().beforeTransactionCompletion( null );
}
}
private void setRollbackOnly() {
- try {
- jtaTransaction.setRollbackOnly();
- }
- catch ( SystemException se ) {
- // best effort
- log.error( "could not set transaction to rollback only", se );
- }
+ transactionCoordinator.setRollbackOnly();
}
public void afterCompletion(int status) {
log.trace( "transaction after completion callback [status={}]", status );
try {
- afterCompletionAction.doAction( ctx, status );
-
- final boolean wasSuccessful = ( status == Status.STATUS_COMMITTED );
- jdbcContext.afterTransactionCompletion( wasSuccessful, hibernateTransaction );
+ afterCompletionAction.doAction( transactionCoordinator, status );
+ transactionCoordinator.afterTransaction( null, status );
}
finally {
reset();
- jdbcContext.cleanUpJtaSynchronizationCallbackCoordinator();
- if ( ctx.shouldAutoClose() && !ctx.isClosed() ) {
+ if ( transactionContext().shouldAutoClose() && ! transactionContext().isClosed() ) {
log.trace( "automatically closing session" );
- ctx.managedClose();
+ transactionContext().managedClose();
}
}
}
- private static final BeforeCompletionManagedFlushChecker STANDARD_MANAGED_FLUSH_CHECKER = new BeforeCompletionManagedFlushChecker() {
- public boolean shouldDoManagedFlush(TransactionFactory.Context ctx, Transaction jtaTransaction)
- throws SystemException {
- return !ctx.isClosed() &&
- !ctx.isFlushModeNever() &&
- ctx.isFlushBeforeCompletionEnabled() &&
- !JTAHelper.isRollback( jtaTransaction.getStatus() );
- //actually, this last test is probably unnecessary, since
- //beforeCompletion() doesn't get called during rollback
+ private TransactionContext transactionContext() {
+ return transactionCoordinator.getTransactionContext();
+ }
+
+ private static final ManagedFlushChecker STANDARD_MANAGED_FLUSH_CHECKER = new ManagedFlushChecker() {
+ @Override
+ public boolean shouldDoManagedFlush(TransactionCoordinator coordinator, int jtaStatus) {
+ return coordinator.getTransactionContext().isFlushModeNever() &&
+ coordinator.getTransactionContext().isFlushBeforeCompletionEnabled() &&
+ !JtaStatusHelper.isRollback( jtaStatus );
}
};
@@ -178,7 +158,8 @@ public class CallbackCoordinator {
};
private static final AfterCompletionAction STANDARD_AFTER_COMPLETION_ACTION = new AfterCompletionAction() {
- public void doAction(TransactionFactory.Context ctx, int status) {
+ @Override
+ public void doAction(TransactionCoordinator transactionCoordinator, int status) {
// nothing to do by default.
}
};
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/AfterCompletionAction.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/AfterCompletionAction.java
new file mode 100644
index 0000000000..c4e0298451
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/AfterCompletionAction.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.hibernate.engine.transaction.spi.TransactionCoordinator;
+
+/**
+ * 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.
+ *
+ * @author Steve Ebersole
+ */
+public interface AfterCompletionAction {
+ public void doAction(TransactionCoordinator transactionCoordinator, int status);
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/synchronization/ExceptionMapper.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/ExceptionMapper.java
similarity index 79%
rename from hibernate-core/src/main/java/org/hibernate/transaction/synchronization/ExceptionMapper.java
rename to hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/ExceptionMapper.java
index 403c558dca..1a0182a050 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/synchronization/ExceptionMapper.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/ExceptionMapper.java
@@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * 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.
@@ -21,18 +21,20 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.transaction.synchronization;
+package org.hibernate.engine.transaction.synchronization.spi;
import javax.transaction.SystemException;
+import java.io.Serializable;
/**
- * TODO : javadoc
+ * A pluggable strategy for defining how the {@link javax.transaction.Synchronization} registered by Hibernate handles
+ * exceptions.
*
* @author Steve Ebersole
*/
-public interface ExceptionMapper {
+public interface ExceptionMapper extends Serializable {
/**
- * Map a JTA {@link SystemException} to the appropriate runtime-based exception.
+ * 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
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/synchronization/BeforeCompletionManagedFlushChecker.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/ManagedFlushChecker.java
similarity index 58%
rename from hibernate-core/src/main/java/org/hibernate/transaction/synchronization/BeforeCompletionManagedFlushChecker.java
rename to hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/ManagedFlushChecker.java
index 90994fcc41..5734b11d3d 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/synchronization/BeforeCompletionManagedFlushChecker.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/ManagedFlushChecker.java
@@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * 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.
@@ -21,31 +21,27 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.transaction.synchronization;
+package org.hibernate.engine.transaction.synchronization.spi;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
+import org.hibernate.engine.transaction.spi.TransactionCoordinator;
-import org.hibernate.transaction.TransactionFactory;
+import java.io.Serializable;
/**
- * Contract for checking whether to perform a managed flush in a
- * {@link javax.transaction.Synchronization#beforeCompletion()} callback
+ * 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}.
*
* @author Steve Ebersole
*/
-public interface BeforeCompletionManagedFlushChecker {
+public interface ManagedFlushChecker extends Serializable {
/**
* Check whether we should perform the managed flush
*
- * @param ctx The Hibernate "transaction context"
- * @param jtaTransaction The JTA transaction
+ * @param coordinator The transaction coordinator
+ * @param jtaStatus The status of the current JTA transaction.
*
* @return True to indicate to perform the managed flush; false otherwise.
- *
- * @throws SystemException Can be thrown while accessing the JTA transaction; will result in transaction being
- * marked for rollback (best effort).
*/
- public boolean shouldDoManagedFlush(TransactionFactory.Context ctx, Transaction jtaTransaction)
- throws SystemException;
+ public boolean shouldDoManagedFlush(TransactionCoordinator coordinator, int jtaStatus);
}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/SynchronizationCallbackCoordinator.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/SynchronizationCallbackCoordinator.java
new file mode 100644
index 0000000000..d96a62b0f9
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/spi/SynchronizationCallbackCoordinator.java
@@ -0,0 +1,35 @@
+/*
+ * 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 javax.transaction.Synchronization;
+
+/**
+ * @author Steve Ebersole
+ */
+public interface SynchronizationCallbackCoordinator extends Synchronization{
+ public void setManagedFlushChecker(ManagedFlushChecker managedFlushChecker);
+ public void setAfterCompletionAction(AfterCompletionAction afterCompletionAction);
+ public void setExceptionMapper(ExceptionMapper exceptionMapper);
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/event/def/AbstractFlushingEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/def/AbstractFlushingEventListener.java
index d252b091f1..15aa516d8c 100644
--- a/hibernate-core/src/main/java/org/hibernate/event/def/AbstractFlushingEventListener.java
+++ b/hibernate-core/src/main/java/org/hibernate/event/def/AbstractFlushingEventListener.java
@@ -313,7 +313,7 @@ public abstract class AbstractFlushingEventListener implements Serializable {
log.trace("executing flush");
try {
- session.getJDBCContext().getConnectionManager().flushBeginning();
+ session.getTransactionCoordinator().getJdbcCoordinator().flushBeginning();
// we need to lock the collection caches before
// executing entity inserts/updates in order to
// account for bidi associations
@@ -325,7 +325,7 @@ public abstract class AbstractFlushingEventListener implements Serializable {
throw he;
}
finally {
- session.getJDBCContext().getConnectionManager().flushEnding();
+ session.getTransactionCoordinator().getJdbcCoordinator().flushEnding();
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java
index 9bf1ad0950..7cc8bfa059 100644
--- a/hibernate-core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java
+++ b/hibernate-core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java
@@ -259,7 +259,7 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
Serializable id = key == null ? null : key.getIdentifier();
- boolean inTxn = source.getJDBCContext().isTransactionInProgress();
+ boolean inTxn = source.getTransactionCoordinator().isTransactionInProgress();
boolean shouldDelayIdentityInserts = !inTxn && !requiresImmediateIdAccess;
// Put a placeholder in entries, so we don't recurse back and try to save() the
diff --git a/hibernate-core/src/main/java/org/hibernate/exception/SQLExceptionConverter.java b/hibernate-core/src/main/java/org/hibernate/exception/SQLExceptionConverter.java
index 1a0e1df965..630db0ab6b 100644
--- a/hibernate-core/src/main/java/org/hibernate/exception/SQLExceptionConverter.java
+++ b/hibernate-core/src/main/java/org/hibernate/exception/SQLExceptionConverter.java
@@ -26,6 +26,7 @@ package org.hibernate.exception;
import org.hibernate.JDBCException;
+import java.io.Serializable;
import java.sql.SQLException;
/**
@@ -42,9 +43,9 @@ import java.sql.SQLException;
* @author Steve Ebersole
* @see SQLExceptionConverterFactory
*/
-public interface SQLExceptionConverter {
+public interface SQLExceptionConverter extends Serializable {
/**
- * Convert the given SQLException into Hibernate's JDBCException hierarchy.
+ * Convert the given SQLException into the Hibernate {@link JDBCException} hierarchy.
*
* @param sqlException The SQLException to be converted.
* @param message An optional error message.
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java b/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
index 50f486cd0d..efb94d6869 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
@@ -23,35 +23,33 @@
*/
package org.hibernate.hql.ast.exec;
-import java.sql.PreparedStatement;
-import java.sql.Connection;
-import java.sql.SQLWarning;
-import java.sql.Statement;
-import java.util.List;
-import java.util.Collections;
+import antlr.RecognitionException;
+import antlr.collections.AST;
import org.hibernate.HibernateException;
import org.hibernate.action.BulkOperationCleanupAction;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
-import org.hibernate.engine.transaction.Isolater;
-import org.hibernate.engine.transaction.IsolatedWork;
import org.hibernate.event.EventSource;
import org.hibernate.hql.ast.HqlSqlWalker;
import org.hibernate.hql.ast.SqlGenerator;
+import org.hibernate.jdbc.Work;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.InsertSelect;
import org.hibernate.sql.Select;
import org.hibernate.sql.SelectFragment;
import org.hibernate.util.JDBCExceptionReporter;
import org.hibernate.util.StringHelper;
-
-import antlr.RecognitionException;
-import antlr.collections.AST;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.util.Collections;
+import java.util.List;
+
/**
* Implementation of AbstractStatementExecutor.
*
@@ -139,42 +137,55 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
" from " + persister.getTemporaryIdTableName();
}
+ private static class TemporaryTableCreationWork implements Work {
+ private final Queryable persister;
+
+ private TemporaryTableCreationWork(Queryable persister) {
+ this.persister = persister;
+ }
+
+ @Override
+ public void execute(Connection connection) {
+ try {
+ Statement statement = connection.createStatement();
+ try {
+ statement.executeUpdate( persister.getTemporaryIdTableDDL() );
+ JDBCExceptionReporter.handleAndClearWarnings( statement, CREATION_WARNING_HANDLER );
+ }
+ finally {
+ try {
+ statement.close();
+ }
+ catch( Throwable ignore ) {
+ // ignore
+ }
+ }
+ }
+ catch( Exception e ) {
+ LOG.debug( "unable to create temporary id table [" + e.getMessage() + "]" );
+ }
+ }
+ }
protected void createTemporaryTableIfNecessary(final Queryable persister, final SessionImplementor session) {
// Don't really know all the codes required to adequately decipher returned jdbc exceptions here.
// simply allow the failure to be eaten and the subsequent insert-selects/deletes should fail
- IsolatedWork work = new IsolatedWork() {
- public void doWork(Connection connection) throws HibernateException {
- try {
- Statement statement = connection.createStatement();
- try {
- statement.executeUpdate( persister.getTemporaryIdTableDDL() );
- JDBCExceptionReporter.handleAndClearWarnings( statement, CREATION_WARNING_HANDLER );
- }
- finally {
- try {
- statement.close();
- }
- catch( Throwable ignore ) {
- // ignore
- }
- }
- }
- catch( Exception e ) {
- log.debug( "unable to create temporary id table [" + e.getMessage() + "]" );
- }
- }
- };
+ TemporaryTableCreationWork work = new TemporaryTableCreationWork( persister );
if ( shouldIsolateTemporaryTableDDL() ) {
- if ( getFactory().getSettings().isDataDefinitionInTransactionSupported() ) {
- Isolater.doIsolatedWork( work, session );
- }
- else {
- Isolater.doNonTransactedWork( work, session );
- }
+ session.getTransactionCoordinator()
+ .getTransaction()
+ .createIsolationDelegate()
+ .delegateWork( work, getFactory().getSettings().isDataDefinitionInTransactionSupported() );
}
else {
- work.doWork( session.getJDBCContext().getConnectionManager().getConnection() );
- session.getJDBCContext().getConnectionManager().afterStatement();
+ final Connection connection = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getLogicalConnection()
+ .getShareableConnectionProxy();
+ work.execute( connection );
+ session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getLogicalConnection()
+ .afterStatementExecution();
}
}
@@ -194,53 +205,67 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
}
};
- protected void dropTemporaryTableIfNecessary(final Queryable persister, final SessionImplementor session) {
- if ( getFactory().getDialect().dropTemporaryTableAfterUse() ) {
- IsolatedWork work = new IsolatedWork() {
- public void doWork(Connection connection) throws HibernateException {
- final String command = session.getFactory().getDialect().getDropTemporaryTableString()
- + ' ' + persister.getTemporaryIdTableName();
- try {
- Statement statement = connection.createStatement();
- try {
- statement = connection.createStatement();
- statement.executeUpdate( command );
- }
- finally {
- try {
- statement.close();
- }
- catch( Throwable ignore ) {
- // ignore
- }
- }
- }
- catch( Exception e ) {
- log.warn( "unable to drop temporary id table after use [" + e.getMessage() + "]" );
- }
- }
- };
+ private static class TemporaryTableDropWork implements Work {
+ private final Queryable persister;
+ private final SessionImplementor session;
- if ( shouldIsolateTemporaryTableDDL() ) {
- if ( getFactory().getSettings().isDataDefinitionInTransactionSupported() ) {
- Isolater.doIsolatedWork( work, session );
+ private TemporaryTableDropWork(Queryable persister, SessionImplementor session) {
+ this.persister = persister;
+ this.session = session;
+ }
+
+ @Override
+ public void execute(Connection connection) {
+ final String command = session.getFactory().getDialect().getDropTemporaryTableString()
+ + ' ' + persister.getTemporaryIdTableName();
+ try {
+ Statement statement = connection.createStatement();
+ try {
+ statement = connection.createStatement();
+ statement.executeUpdate( command );
}
- else {
- Isolater.doNonTransactedWork( work, session );
+ finally {
+ try {
+ statement.close();
+ }
+ catch( Throwable ignore ) {
+ // ignore
+ }
}
}
+ catch( Exception e ) {
+ LOG.warn( "unable to drop temporary id table after use [" + e.getMessage() + "]" );
+ }
+ }
+ }
+
+ protected void dropTemporaryTableIfNecessary(final Queryable persister, final SessionImplementor session) {
+ if ( getFactory().getDialect().dropTemporaryTableAfterUse() ) {
+ TemporaryTableDropWork work = new TemporaryTableDropWork( persister, session );
+ if ( shouldIsolateTemporaryTableDDL() ) {
+ session.getTransactionCoordinator()
+ .getTransaction()
+ .createIsolationDelegate()
+ .delegateWork( work, getFactory().getSettings().isDataDefinitionInTransactionSupported() );
+ }
else {
- work.doWork( session.getJDBCContext().getConnectionManager().getConnection() );
- session.getJDBCContext().getConnectionManager().afterStatement();
+ final Connection connection = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getLogicalConnection()
+ .getShareableConnectionProxy();
+ work.execute( connection );
+ session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getLogicalConnection()
+ .afterStatementExecution();
}
}
else {
// at the very least cleanup the data :)
PreparedStatement ps = null;
try {
- ps = session.getJDBCContext().getConnectionManager().prepareStatement( "delete from " + persister.getTemporaryIdTableName(),
- false
- );
+ final String sql = "delete from " + persister.getTemporaryIdTableName();
+ ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
ps.executeUpdate();
}
catch( Throwable t ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/BasicExecutor.java b/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/BasicExecutor.java
index 53c0aeee67..6aebc128dd 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/BasicExecutor.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/BasicExecutor.java
@@ -84,7 +84,7 @@ public class BasicExecutor extends AbstractStatementExecutor {
try {
try {
- st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, false );
+ st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
Iterator parameterSpecifications = this.parameterSpecifications.iterator();
int pos = 1;
while ( parameterSpecifications.hasNext() ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java b/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java
index 4290cb2ef4..4c40bc3aa5 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java
@@ -105,7 +105,7 @@ public class MultiTableDeleteExecutor extends AbstractStatementExecutor {
int resultCount = 0;
try {
try {
- ps = session.getJDBCContext().getConnectionManager().prepareStatement( idInsertSelect, false );
+ ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( idInsertSelect, false );
Iterator paramSpecifications = getIdSelectParameterSpecifications().iterator();
int pos = 1;
while ( paramSpecifications.hasNext() ) {
@@ -132,7 +132,7 @@ public class MultiTableDeleteExecutor extends AbstractStatementExecutor {
for ( int i = 0; i < deletes.length; i++ ) {
try {
try {
- ps = session.getJDBCContext().getConnectionManager().prepareStatement( deletes[i], false );
+ ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( deletes[i], false );
ps.executeUpdate();
}
finally {
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java b/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java
index 17f4cfc2a0..d183f29498 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java
@@ -129,7 +129,7 @@ public class MultiTableUpdateExecutor extends AbstractStatementExecutor {
int resultCount = 0;
try {
try {
- ps = session.getJDBCContext().getConnectionManager().prepareStatement( idInsertSelect, false );
+ ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( idInsertSelect, false );
// int parameterStart = getWalker().getNumberOfParametersInSetClause();
// List allParams = getIdSelectParameterSpecifications();
// Iterator whereParams = allParams.subList( parameterStart, allParams.size() ).iterator();
@@ -161,7 +161,7 @@ public class MultiTableUpdateExecutor extends AbstractStatementExecutor {
}
try {
try {
- ps = session.getJDBCContext().getConnectionManager().prepareStatement( updates[i], false );
+ ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( updates[i], false );
if ( hqlParameters[i] != null ) {
int position = 1; // jdbc params are 1-based
for ( int x = 0; x < hqlParameters[i].length; x++ ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/id/GUIDGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/GUIDGenerator.java
index d183b1a592..3f24e37b12 100644
--- a/hibernate-core/src/main/java/org/hibernate/id/GUIDGenerator.java
+++ b/hibernate-core/src/main/java/org/hibernate/id/GUIDGenerator.java
@@ -58,7 +58,7 @@ public class GUIDGenerator implements IdentifierGenerator {
final String sql = session.getFactory().getDialect().getSelectGUIDString();
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement(sql);
+ PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
ResultSet rs = st.executeQuery();
final String result;
diff --git a/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java
index 65aa1e4b5f..72318efff4 100644
--- a/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java
+++ b/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java
@@ -87,7 +87,10 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
}
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
- return session.getJDBCContext().getConnectionManager().prepareStatement( insertSQL, PreparedStatement.RETURN_GENERATED_KEYS );
+ return session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( insertSQL, PreparedStatement.RETURN_GENERATED_KEYS );
}
public Serializable executeAndExtract(PreparedStatement insert) throws SQLException {
@@ -131,7 +134,10 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
}
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
- return session.getJDBCContext().getConnectionManager().prepareStatement( insertSQL, PreparedStatement.NO_GENERATED_KEYS );
+ return session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( insertSQL, PreparedStatement.NO_GENERATED_KEYS );
}
public Serializable executeAndExtract(PreparedStatement insert) throws SQLException {
diff --git a/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java
index 7cdd9bf16e..45b93f297b 100644
--- a/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java
+++ b/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java
@@ -121,7 +121,7 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
log.debug( "fetching initial value: " + sql );
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
ResultSet rs = st.executeQuery();
try {
diff --git a/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java
index 87f37e08a7..d3da145438 100644
--- a/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java
+++ b/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java
@@ -106,7 +106,7 @@ public class SequenceGenerator implements PersistentIdentifierGenerator, Configu
protected IntegralDataTypeHolder generateHolder(SessionImplementor session) {
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
ResultSet rs = st.executeQuery();
try {
diff --git a/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java
index 5382fbeda2..d61e23aac0 100644
--- a/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java
+++ b/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java
@@ -96,7 +96,7 @@ public class SequenceIdentityGenerator extends SequenceGenerator
}
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
- return session.getJDBCContext().getConnectionManager().prepareStatement( insertSQL, keyColumns );
+ return session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( insertSQL, keyColumns );
}
protected Serializable executeAndExtract(PreparedStatement insert) throws SQLException {
diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java
index d946d2cf1e..5b2ac14c9c 100644
--- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java
+++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java
@@ -102,7 +102,7 @@ public class SequenceStructure implements DatabaseStructure {
public IntegralDataTypeHolder getNextValue() {
accessCounter++;
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try {
ResultSet rs = st.executeQuery();
try {
diff --git a/hibernate-core/src/main/java/org/hibernate/id/insert/AbstractSelectingDelegate.java b/hibernate-core/src/main/java/org/hibernate/id/insert/AbstractSelectingDelegate.java
index 9b93eab5d7..ca9c3a978c 100644
--- a/hibernate-core/src/main/java/org/hibernate/id/insert/AbstractSelectingDelegate.java
+++ b/hibernate-core/src/main/java/org/hibernate/id/insert/AbstractSelectingDelegate.java
@@ -50,7 +50,10 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
public final Serializable performInsert(String insertSQL, SessionImplementor session, Binder binder) {
try {
// prepare and execute the insert
- PreparedStatement insert = session.getJDBCContext().getConnectionManager().prepareStatement( insertSQL, PreparedStatement.NO_GENERATED_KEYS );
+ PreparedStatement insert = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( insertSQL, PreparedStatement.NO_GENERATED_KEYS );
try {
binder.bindValues( insert );
insert.executeUpdate();
@@ -71,7 +74,10 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
try {
//fetch the generated id in a separate query
- PreparedStatement idSelect = session.getJDBCContext().getConnectionManager().prepareStatement( selectSQL, false );
+ PreparedStatement idSelect = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( selectSQL, false );
try {
bindParameters( session, idSelect, binder.getEntity() );
ResultSet rs = idSelect.executeQuery();
diff --git a/hibernate-core/src/main/java/org/hibernate/impl/AbstractSessionImpl.java b/hibernate-core/src/main/java/org/hibernate/impl/AbstractSessionImpl.java
index ea7e1cbdbe..bc017b1a27 100755
--- a/hibernate-core/src/main/java/org/hibernate/impl/AbstractSessionImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/impl/AbstractSessionImpl.java
@@ -38,6 +38,8 @@ import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.query.HQLQueryPlan;
import org.hibernate.engine.query.NativeSQLQueryPlan;
+import org.hibernate.engine.transaction.spi.TransactionContext;
+import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import java.util.List;
@@ -46,7 +48,7 @@ import java.util.List;
*
* @author Gavin King
*/
-public abstract class AbstractSessionImpl implements SessionImplementor {
+public abstract class AbstractSessionImpl implements SessionImplementor, TransactionContext {
protected transient SessionFactoryImpl factory;
private boolean closed = false;
@@ -59,6 +61,11 @@ public abstract class AbstractSessionImpl implements SessionImplementor {
return factory;
}
+ @Override
+ public TransactionEnvironment getTransactionEnvironment() {
+ return factory.getTransactionEnvironment();
+ }
+
public boolean isClosed() {
return closed;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/impl/ConnectionObserverStatsBridge.java b/hibernate-core/src/main/java/org/hibernate/impl/ConnectionObserverStatsBridge.java
new file mode 100644
index 0000000000..cbfb318576
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/impl/ConnectionObserverStatsBridge.java
@@ -0,0 +1,59 @@
+/*
+ * 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.impl;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.jdbc.spi.ConnectionObserver;
+
+import java.io.Serializable;
+import java.sql.Connection;
+
+/**
+ * @author Steve Ebersole
+ */
+public class ConnectionObserverStatsBridge implements ConnectionObserver, Serializable {
+ private final SessionFactoryImplementor sessionFactory;
+
+ public ConnectionObserverStatsBridge(SessionFactoryImplementor sessionFactory) {
+ this.sessionFactory = sessionFactory;
+ }
+
+ @Override
+ public void physicalConnectionObtained(Connection connection) {
+ sessionFactory.getStatisticsImplementor().connect();
+ }
+
+ @Override
+ public void physicalConnectionReleased() {
+ }
+
+ @Override
+ public void logicalConnectionClosed() {
+ }
+
+ @Override
+ public void statementPrepared() {
+ sessionFactory.getStatisticsImplementor().prepareStatement();
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java
index 6a004835ca..3a7dedf62d 100644
--- a/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java
@@ -23,32 +23,6 @@
*/
package org.hibernate.impl;
-import java.io.IOException;
-import java.io.InvalidObjectException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-import java.sql.Connection;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import javax.naming.NamingException;
-import javax.naming.Reference;
-import javax.naming.StringRefAddr;
-import javax.transaction.TransactionManager;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import org.hibernate.AssertionFailure;
import org.hibernate.Cache;
import org.hibernate.ConnectionReleaseMode;
@@ -76,10 +50,6 @@ import org.hibernate.cache.impl.CacheDataDescriptionImpl;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.cfg.Settings;
-import org.hibernate.engine.jdbc.spi.JdbcServices;
-import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
-import org.hibernate.exception.SQLExceptionConverter;
-import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.context.CurrentSessionContext;
import org.hibernate.context.JTASessionContext;
import org.hibernate.context.ManagedSessionContext;
@@ -92,12 +62,16 @@ import org.hibernate.engine.NamedQueryDefinition;
import org.hibernate.engine.NamedSQLQueryDefinition;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.jdbc.spi.JdbcServices;
+import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
import org.hibernate.engine.profile.Association;
import org.hibernate.engine.profile.Fetch;
import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.engine.query.QueryPlanCache;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
+import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.event.EventListeners;
+import org.hibernate.exception.SQLExceptionConverter;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.UUIDGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
@@ -113,6 +87,8 @@ import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.EntityNotFoundDelegate;
+import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
import org.hibernate.service.spi.ServiceRegistry;
import org.hibernate.stat.ConcurrentStatisticsImpl;
import org.hibernate.stat.Statistics;
@@ -120,7 +96,6 @@ import org.hibernate.stat.StatisticsImplementor;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.hbm2ddl.SchemaUpdate;
import org.hibernate.tool.hbm2ddl.SchemaValidator;
-import org.hibernate.transaction.TransactionFactory;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.type.AssociationType;
import org.hibernate.type.Type;
@@ -128,6 +103,31 @@ import org.hibernate.type.TypeResolver;
import org.hibernate.util.CollectionHelper;
import org.hibernate.util.EmptyIterator;
import org.hibernate.util.ReflectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+import javax.transaction.TransactionManager;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
/**
@@ -153,7 +153,8 @@ import org.hibernate.util.ReflectHelper;
* @see org.hibernate.persister.collection.CollectionPersister
* @author Gavin King
*/
-public final class SessionFactoryImpl implements SessionFactory, SessionFactoryImplementor {
+public final class SessionFactoryImpl
+ implements SessionFactory, SessionFactoryImplementor {
private static final Logger log = LoggerFactory.getLogger(SessionFactoryImpl.class);
private static final IdentifierGenerator UUID_GENERATOR = UUIDGenerator.buildSessionFactoryUniqueIdentifierGenerator();
@@ -178,7 +179,6 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
private final transient Settings settings;
private final transient Properties properties;
private transient SchemaExport schemaExport;
- private final transient TransactionManager transactionManager;
private final transient QueryCache queryCache;
private final transient UpdateTimestampsCache updateTimestampsCache;
private final transient Map queryCaches;
@@ -195,6 +195,7 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
private transient boolean isClosed = false;
private final transient TypeResolver typeResolver;
private final transient TypeHelper typeHelper;
+ private final transient TransactionEnvironment transactionEnvironment;
public SessionFactoryImpl(
Configuration cfg,
@@ -386,17 +387,6 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
schemaExport = new SchemaExport( getJdbcServices(), cfg );
}
- if ( settings.getTransactionManagerLookup()!=null ) {
- log.debug("obtaining JTA TransactionManager");
- transactionManager = settings.getTransactionManagerLookup().getTransactionManager(properties);
- }
- else {
- if ( settings.getTransactionFactory().isTransactionManagerRequired() ) {
- throw new HibernateException("The chosen transaction strategy requires access to the JTA TransactionManager");
- }
- transactionManager = null;
- }
-
currentSessionContext = buildCurrentSessionContext();
if ( settings.isQueryCacheEnabled() ) {
@@ -480,9 +470,14 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
fetchProfiles.put( fetchProfile.getName(), fetchProfile );
}
+ this.transactionEnvironment = new TransactionEnvironmentImpl( this );
this.observer.sessionFactoryCreated( this );
}
+ public TransactionEnvironment getTransactionEnvironment() {
+ return transactionEnvironment;
+ }
+
public Properties getProperties() {
return properties;
}
@@ -728,14 +723,6 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
return interceptor;
}
- public TransactionFactory getTransactionFactory() {
- return settings.getTransactionFactory();
- }
-
- public TransactionManager getTransactionManager() {
- return transactionManager;
- }
-
public SQLExceptionConverter getSQLExceptionConverter() {
return getSQLExceptionHelper().getSqlExceptionConverter();
}
@@ -1229,19 +1216,34 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
return (IdentifierGenerator) identifierGenerators.get(rootEntityName);
}
+ private org.hibernate.engine.transaction.spi.TransactionFactory transactionFactory() {
+ return serviceRegistry.getService( org.hibernate.engine.transaction.spi.TransactionFactory.class );
+ }
+
+ private boolean canAccessTransactionManager() {
+ try {
+ return serviceRegistry.getService( JtaPlatform.class ).retrieveTransactionManager() != null;
+ }
+ catch (Exception e) {
+ return false;
+ }
+ }
+
private CurrentSessionContext buildCurrentSessionContext() {
String impl = properties.getProperty( Environment.CURRENT_SESSION_CONTEXT_CLASS );
- // for backward-compatability
- if ( impl == null && transactionManager != null ) {
- impl = "jta";
+ // for backward-compatibility
+ if ( impl == null ) {
+ if ( canAccessTransactionManager() ) {
+ impl = "jta";
+ }
+ else {
+ return null;
+ }
}
- if ( impl == null ) {
- return null;
- }
- else if ( "jta".equals( impl ) ) {
- if ( settings.getTransactionFactory().areCallbacksLocalToHibernateTransactions() ) {
- log.warn( "JTASessionContext being used with JDBCTransactionFactory; auto-flush will not operate correctly with getCurrentSession()" );
+ if ( "jta".equals( impl ) ) {
+ if ( ! transactionFactory().compatibleWithJtaSynchronization() ) {
+ log.warn( "JTASessionContext being used with JdbcTransactionFactory; auto-flush will not operate correctly with getCurrentSession()" );
}
return new JTASessionContext( this );
}
@@ -1256,7 +1258,7 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
Class implClass = ReflectHelper.classForName( impl );
return ( CurrentSessionContext ) implClass
.getConstructor( new Class[] { SessionFactoryImplementor.class } )
- .newInstance( new Object[] { this } );
+ .newInstance( this );
}
catch( Throwable t ) {
log.error( "Unable to construct current session context [" + impl + "]", t );
@@ -1265,11 +1267,15 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
}
}
- public EventListeners getEventListeners()
- {
+ public EventListeners getEventListeners() {
return eventListeners;
}
+ @Override
+ public ServiceRegistry getServiceRegistry() {
+ return serviceRegistry;
+ }
+
public EntityNotFoundDelegate getEntityNotFoundDelegate() {
return entityNotFoundDelegate;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/impl/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/impl/SessionImpl.java
index 25b99c52b2..32749877d2 100644
--- a/hibernate-core/src/main/java/org/hibernate/impl/SessionImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/impl/SessionImpl.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2005-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 Middleware LLC.
+ * 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
@@ -20,44 +20,21 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
package org.hibernate.impl;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Reader;
-import java.io.Serializable;
-import java.io.ByteArrayOutputStream;
-import java.io.ByteArrayInputStream;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import org.hibernate.CacheMode;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
+import org.hibernate.EntityNameResolver;
import org.hibernate.Filter;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.LobHelper;
import org.hibernate.LockMode;
+import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.ObjectDeletedException;
import org.hibernate.Query;
@@ -68,33 +45,34 @@ import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionException;
-import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.TransientObjectException;
import org.hibernate.TypeHelper;
-import org.hibernate.UnresolvableObjectException;
import org.hibernate.UnknownProfileException;
-import org.hibernate.EntityNameResolver;
-import org.hibernate.LockOptions;
+import org.hibernate.UnresolvableObjectException;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.engine.ActionQueue;
import org.hibernate.engine.CollectionEntry;
import org.hibernate.engine.EntityEntry;
import org.hibernate.engine.EntityKey;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.NonFlushedChanges;
import org.hibernate.engine.PersistenceContext;
import org.hibernate.engine.QueryParameters;
+import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.StatefulPersistenceContext;
import org.hibernate.engine.Status;
-import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
-import org.hibernate.engine.jdbc.internal.JDBCContextImpl;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.engine.query.FilterQueryPlan;
import org.hibernate.engine.query.HQLQueryPlan;
import org.hibernate.engine.query.NativeSQLQueryPlan;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
+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.TransactionImplementor;
+import org.hibernate.engine.transaction.spi.TransactionObserver;
import org.hibernate.event.AutoFlushEvent;
import org.hibernate.event.AutoFlushEventListener;
import org.hibernate.event.DeleteEvent;
@@ -136,57 +114,84 @@ import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.stat.SessionStatistics;
import org.hibernate.stat.SessionStatisticsImpl;
-import org.hibernate.type.Type;
import org.hibernate.type.SerializationException;
+import org.hibernate.type.Type;
import org.hibernate.util.ArrayHelper;
import org.hibernate.util.CollectionHelper;
import org.hibernate.util.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Reader;
+import java.io.Serializable;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
- * Concrete implementation of a Session, and also the central, organizing component
- * of Hibernate's internal implementation. As such, this class exposes two interfaces;
- * Session itself, to the application, and SessionImplementor, to other components
- * of Hibernate. This class is not threadsafe.
+ * Concrete implementation of a Session.
+ *
+ * Exposes two interfaces:
+ * - {@link Session} to the application
+ * - {@link org.hibernate.engine.SessionImplementor} to other Hibernate components (SPI)
+ *
+ *
+ * This class is not thread-safe.
*
* @author Gavin King
*/
-public final class SessionImpl extends AbstractSessionImpl
- implements EventSource, org.hibernate.classic.Session, JDBCContext.Context, LobCreationContext {
+public final class SessionImpl
+ extends AbstractSessionImpl
+ implements EventSource,
+ org.hibernate.classic.Session,
+ TransactionContext,
+ LobCreationContext {
// todo : need to find a clean way to handle the "event source" role
- // a seperate classs responsible for generating/dispatching events just duplicates most of the Session methods...
- // passing around seperate reto interceptor, factory, actionQueue, and persistentContext is not manageable...
+ // 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 Logger log = LoggerFactory.getLogger(SessionImpl.class);
- private transient EntityMode entityMode = EntityMode.POJO;
- private transient boolean autoClear; //for EJB3
-
private transient long timestamp;
- private transient FlushMode flushMode = FlushMode.AUTO;
- private transient CacheMode cacheMode = CacheMode.NORMAL;
-
- private transient Interceptor interceptor;
-
- private transient int dontFlushFromFind = 0;
private transient ActionQueue actionQueue;
private transient StatefulPersistenceContext persistenceContext;
- private transient JDBCContextImpl jdbcContext;
+ private transient TransactionCoordinatorImpl transactionCoordinator;
private transient EventListeners listeners;
+ private transient Interceptor interceptor;
+ private transient EntityNameResolver entityNameResolver = new CoordinatingEntityNameResolver();
+ private transient ConnectionReleaseMode connectionReleaseMode;
+ private transient FlushMode flushMode = FlushMode.AUTO;
+ private transient CacheMode cacheMode = CacheMode.NORMAL;
+ private transient EntityMode entityMode = EntityMode.POJO;
+ private transient boolean autoClear; //for EJB3
+
+ private transient int dontFlushFromFind = 0;
private transient boolean flushBeforeCompletionEnabled;
private transient boolean autoCloseSessionEnabled;
- private transient ConnectionReleaseMode connectionReleaseMode;
private transient LoadQueryInfluencers loadQueryInfluencers;
private transient Session rootSession;
private transient Map childSessionsByEntityMode;
- private transient EntityNameResolver entityNameResolver = new CoordinatingEntityNameResolver();
-
/**
* Constructor used in building "child sessions".
*
@@ -197,7 +202,7 @@ public final class SessionImpl extends AbstractSessionImpl
super( parent.factory );
this.rootSession = parent;
this.timestamp = parent.timestamp;
- this.jdbcContext = parent.jdbcContext;
+ this.transactionCoordinator = parent.transactionCoordinator;
this.interceptor = parent.interceptor;
this.listeners = parent.listeners;
this.actionQueue = new ActionQueue( this );
@@ -251,7 +256,11 @@ public final class SessionImpl extends AbstractSessionImpl
this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;
this.autoCloseSessionEnabled = autoCloseSessionEnabled;
this.connectionReleaseMode = connectionReleaseMode;
- this.jdbcContext = new JDBCContextImpl( this, connection, interceptor );
+
+ this.transactionCoordinator = new TransactionCoordinatorImpl( connection, this );
+ this.transactionCoordinator.getJdbcCoordinator().getLogicalConnection().addObserver(
+ new ConnectionObserverStatsBridge( factory )
+ );
loadQueryInfluencers = new LoadQueryInfluencers( factory );
@@ -330,7 +339,7 @@ public final class SessionImpl extends AbstractSessionImpl
}
if ( rootSession == null ) {
- return jdbcContext.getConnectionManager().close();
+ return transactionCoordinator.close();
}
else {
return null;
@@ -343,7 +352,6 @@ public final class SessionImpl extends AbstractSessionImpl
}
public ConnectionReleaseMode getConnectionReleaseMode() {
- checkTransactionSynchStatus();
return connectionReleaseMode;
}
@@ -523,76 +531,84 @@ public final class SessionImpl extends AbstractSessionImpl
public Connection connection() throws HibernateException {
errorIfClosed();
- return jdbcContext.borrowConnection();
+ return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getDistinctConnectionProxy();
}
public boolean isConnected() {
checkTransactionSynchStatus();
- return !isClosed() && jdbcContext.getConnectionManager().isCurrentlyConnected();
+ return !isClosed() && transactionCoordinator.getJdbcCoordinator().getLogicalConnection().isOpen();
}
-
+
public boolean isTransactionInProgress() {
checkTransactionSynchStatus();
- return !isClosed() && jdbcContext.isTransactionInProgress();
+ return !isClosed() && transactionCoordinator.isTransactionInProgress();
}
public Connection disconnect() throws HibernateException {
errorIfClosed();
log.debug( "disconnecting session" );
- return jdbcContext.getConnectionManager().manualDisconnect();
+ return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().manualDisconnect();
}
public void reconnect() throws HibernateException {
errorIfClosed();
log.debug( "reconnecting session" );
checkTransactionSynchStatus();
- jdbcContext.getConnectionManager().manualReconnect();
+ transactionCoordinator.getJdbcCoordinator().getLogicalConnection().manualReconnect( null );
}
public void reconnect(Connection conn) throws HibernateException {
errorIfClosed();
log.debug( "reconnecting session" );
checkTransactionSynchStatus();
- jdbcContext.getConnectionManager().manualReconnect( conn );
+ transactionCoordinator.getJdbcCoordinator().getLogicalConnection().manualReconnect( conn );
}
- public void beforeTransactionCompletion(Transaction tx) {
- log.trace( "before transaction completion" );
- actionQueue.beforeTransactionCompletion();
- if ( rootSession == null ) {
- try {
- interceptor.beforeTransactionCompletion(tx);
- }
- catch (Throwable t) {
- log.error("exception in interceptor beforeTransactionCompletion()", t);
- }
- }
- }
-
public void setAutoClear(boolean enabled) {
errorIfClosed();
autoClear = enabled;
}
-
+
/**
- * Check if there is a Hibernate or JTA transaction in progress and,
- * if there is not, flush if necessary, make sure the connection has
- * been committed (if it is not in autocommit mode) and run the after
+ * Check if there is a Hibernate or JTA transaction in progress and,
+ * if there is not, flush if necessary, make sure the connection has
+ * been committed (if it is not in autocommit mode) and run the after
* completion processing
*/
public void afterOperation(boolean success) {
- if ( !jdbcContext.isTransactionInProgress() ) {
- jdbcContext.afterNontransactionalQuery( success );
+ if ( ! transactionCoordinator.isTransactionInProgress() ) {
+ transactionCoordinator.afterNonTransactionalQuery( success );
}
}
- public void afterTransactionCompletion(boolean success, Transaction tx) {
+ @Override
+ public void afterTransactionBegin(TransactionImplementor hibernateTransaction) {
+ errorIfClosed();
+ interceptor.afterTransactionBegin( hibernateTransaction );
+ }
+
+ @Override
+ public void beforeTransactionCompletion(TransactionImplementor hibernateTransaction) {
+ log.trace( "before transaction completion" );
+ actionQueue.beforeTransactionCompletion();
+ if ( rootSession == null ) {
+ try {
+ interceptor.beforeTransactionCompletion( hibernateTransaction );
+ }
+ catch (Throwable t) {
+ log.error( "exception in interceptor beforeTransactionCompletion()", t );
+ }
+ }
+ }
+
+ @Override
+ public void afterTransactionCompletion(TransactionImplementor hibernateTransaction, boolean successful) {
log.trace( "after transaction completion" );
persistenceContext.afterTransactionCompletion();
- actionQueue.afterTransactionCompletion(success);
- if ( rootSession == null && tx != null ) {
+ actionQueue.afterTransactionCompletion( successful );
+ if ( rootSession == null && hibernateTransaction != null ) {
try {
- interceptor.afterTransactionCompletion(tx);
+ interceptor.afterTransactionCompletion( hibernateTransaction );
}
catch (Throwable t) {
log.error("exception in interceptor afterTransactionCompletion()", t);
@@ -660,11 +676,11 @@ public final class SessionImpl extends AbstractSessionImpl
// saveOrUpdate() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public void saveOrUpdate(Object object) throws HibernateException {
- saveOrUpdate(null, object);
+ saveOrUpdate( null, object );
}
public void saveOrUpdate(String entityName, Object obj) throws HibernateException {
- fireSaveOrUpdate( new SaveOrUpdateEvent(entityName, obj, this) );
+ fireSaveOrUpdate( new SaveOrUpdateEvent( entityName, obj, this ) );
}
private void fireSaveOrUpdate(SaveOrUpdateEvent event) {
@@ -684,15 +700,15 @@ public final class SessionImpl extends AbstractSessionImpl
}
public Serializable save(Object obj) throws HibernateException {
- return save(null, obj);
+ return save( null, obj );
}
public Serializable save(String entityName, Object object) throws HibernateException {
- return fireSave( new SaveOrUpdateEvent(entityName, object, this) );
+ return fireSave( new SaveOrUpdateEvent( entityName, object, this ) );
}
public void save(String entityName, Object object, Serializable id) throws HibernateException {
- fireSave( new SaveOrUpdateEvent(entityName, object, id, this) );
+ fireSave( new SaveOrUpdateEvent( entityName, object, id, this ) );
}
private Serializable fireSave(SaveOrUpdateEvent event) {
@@ -713,15 +729,15 @@ public final class SessionImpl extends AbstractSessionImpl
}
public void update(Object obj, Serializable id) throws HibernateException {
- update(null, obj, id);
+ update( null, obj, id );
}
public void update(String entityName, Object object) throws HibernateException {
- fireUpdate( new SaveOrUpdateEvent(entityName, object, this) );
+ fireUpdate( new SaveOrUpdateEvent( entityName, object, this ) );
}
public void update(String entityName, Object object, Serializable id) throws HibernateException {
- fireUpdate(new SaveOrUpdateEvent(entityName, object, id, this));
+ fireUpdate( new SaveOrUpdateEvent( entityName, object, id, this ) );
}
private void fireUpdate(SaveOrUpdateEvent event) {
@@ -753,7 +769,7 @@ public final class SessionImpl extends AbstractSessionImpl
}
private void fireLock( Object object, LockOptions options) {
- fireLock( new LockEvent( object, options, this) );
+ fireLock( new LockEvent( object, options, this ) );
}
private void fireLock(LockEvent lockEvent) {
@@ -769,16 +785,16 @@ public final class SessionImpl extends AbstractSessionImpl
// persist() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public void persist(String entityName, Object object) throws HibernateException {
- firePersist( new PersistEvent(entityName, object, this) );
+ firePersist( new PersistEvent( entityName, object, this ) );
}
public void persist(Object object) throws HibernateException {
- persist(null, object);
+ persist( null, object );
}
public void persist(String entityName, Object object, Map copiedAlready)
throws HibernateException {
- firePersist( copiedAlready, new PersistEvent(entityName, object, this) );
+ firePersist( copiedAlready, new PersistEvent( entityName, object, this ) );
}
private void firePersist(Map copiedAlready, PersistEvent event) {
@@ -804,16 +820,16 @@ public final class SessionImpl extends AbstractSessionImpl
public void persistOnFlush(String entityName, Object object)
throws HibernateException {
- firePersistOnFlush( new PersistEvent(entityName, object, this) );
+ firePersistOnFlush( new PersistEvent( entityName, object, this ) );
}
public void persistOnFlush(Object object) throws HibernateException {
- persist(null, object);
+ persist( null, object );
}
public void persistOnFlush(String entityName, Object object, Map copiedAlready)
throws HibernateException {
- firePersistOnFlush( copiedAlready, new PersistEvent(entityName, object, this) );
+ firePersistOnFlush( copiedAlready, new PersistEvent( entityName, object, this ) );
}
private void firePersistOnFlush(Map copiedAlready, PersistEvent event) {
@@ -838,15 +854,15 @@ public final class SessionImpl extends AbstractSessionImpl
// merge() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public Object merge(String entityName, Object object) throws HibernateException {
- return fireMerge( new MergeEvent(entityName, object, this) );
+ return fireMerge( new MergeEvent( entityName, object, this ) );
}
public Object merge(Object object) throws HibernateException {
- return merge(null, object);
+ return merge( null, object );
}
public void merge(String entityName, Object object, Map copiedAlready) throws HibernateException {
- fireMerge( copiedAlready, new MergeEvent(entityName, object, this) );
+ fireMerge( copiedAlready, new MergeEvent( entityName, object, this ) );
}
private Object fireMerge(MergeEvent event) {
@@ -873,7 +889,7 @@ public final class SessionImpl extends AbstractSessionImpl
public Object saveOrUpdateCopy(String entityName, Object object)
throws HibernateException {
- return fireSaveOrUpdateCopy( new MergeEvent(entityName, object, this) );
+ return fireSaveOrUpdateCopy( new MergeEvent( entityName, object, this ) );
}
public Object saveOrUpdateCopy(Object object) throws HibernateException {
@@ -882,7 +898,7 @@ public final class SessionImpl extends AbstractSessionImpl
public Object saveOrUpdateCopy(String entityName, Object object, Serializable id)
throws HibernateException {
- return fireSaveOrUpdateCopy( new MergeEvent(entityName, object, id, this) );
+ return fireSaveOrUpdateCopy( new MergeEvent( entityName, object, id, this ) );
}
public Object saveOrUpdateCopy(Object object, Serializable id)
@@ -1037,7 +1053,7 @@ public final class SessionImpl extends AbstractSessionImpl
}
public Object load(Class entityClass, Serializable id, LockOptions lockOptions) throws HibernateException {
- return load( entityClass.getName(), id, lockOptions);
+ return load( entityClass.getName(), id, lockOptions );
}
public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException {
@@ -1057,7 +1073,7 @@ public final class SessionImpl extends AbstractSessionImpl
}
public Object get(Class entityClass, Serializable id, LockOptions lockOptions) throws HibernateException {
- return get( entityClass.getName(), id, lockOptions);
+ return get( entityClass.getName(), id, lockOptions );
}
public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException {
@@ -1068,7 +1084,7 @@ public final class SessionImpl extends AbstractSessionImpl
public Object get(String entityName, Serializable id, LockOptions lockOptions) throws HibernateException {
LoadEvent event = new LoadEvent(id, entityName, lockOptions, this);
- fireLoad(event, LoadEventListener.GET);
+ fireLoad( event, LoadEventListener.GET );
return event.getResult();
}
@@ -1097,7 +1113,7 @@ public final class SessionImpl extends AbstractSessionImpl
}
public void refresh(Object object, Map refreshedAlready) throws HibernateException {
- fireRefresh( refreshedAlready, new RefreshEvent(object, this) );
+ fireRefresh( refreshedAlready, new RefreshEvent( object, this ) );
}
private void fireRefresh(RefreshEvent refreshEvent) {
@@ -1127,7 +1143,7 @@ public final class SessionImpl extends AbstractSessionImpl
public void replicate(String entityName, Object obj, ReplicationMode replicationMode)
throws HibernateException {
- fireReplicate( new ReplicateEvent(entityName, obj, replicationMode, this) );
+ fireReplicate( new ReplicateEvent( entityName, obj, replicationMode, this ) );
}
private void fireReplicate(ReplicateEvent event) {
@@ -1147,7 +1163,7 @@ public final class SessionImpl extends AbstractSessionImpl
* (references held by application or other persistant instances are okay)
*/
public void evict(Object object) throws HibernateException {
- fireEvict( new EvictEvent(object, this) );
+ fireEvict( new EvictEvent( object, this ) );
}
private void fireEvict(EvictEvent evictEvent) {
@@ -1289,7 +1305,7 @@ public final class SessionImpl extends AbstractSessionImpl
errorIfClosed();
checkTransactionSynchStatus();
queryParameters.validateParameters();
- NativeSQLQueryPlan plan = getNativeSQLQueryPlan(nativeQuerySpecification);
+ NativeSQLQueryPlan plan = getNativeSQLQueryPlan( nativeQuerySpecification );
autoFlushIfRequired( plan.getCustomQuery().getQuerySpaces() );
@@ -1394,11 +1410,11 @@ public final class SessionImpl extends AbstractSessionImpl
public Query getNamedQuery(String queryName) throws MappingException {
errorIfClosed();
checkTransactionSynchStatus();
- return super.getNamedQuery(queryName);
+ return super.getNamedQuery( queryName );
}
public Object instantiate(String entityName, Serializable id) throws HibernateException {
- return instantiate( factory.getEntityPersister(entityName), id );
+ return instantiate( factory.getEntityPersister( entityName ), id );
}
/**
@@ -1449,7 +1465,7 @@ public final class SessionImpl extends AbstractSessionImpl
public Transaction getTransaction() throws HibernateException {
errorIfClosed();
- return jdbcContext.getTransaction();
+ return transactionCoordinator.getTransaction();
}
public Transaction beginTransaction() throws HibernateException {
@@ -1463,11 +1479,6 @@ public final class SessionImpl extends AbstractSessionImpl
result.begin();
return result;
}
-
- public void afterTransactionBegin(Transaction tx) {
- errorIfClosed();
- interceptor.afterTransactionBegin(tx);
- }
public EntityPersister getEntityPersister(final String entityName, final Object object) {
errorIfClosed();
@@ -1522,7 +1533,7 @@ public final class SessionImpl extends AbstractSessionImpl
public Serializable getContextEntityIdentifier(Object object) {
errorIfClosed();
if ( object instanceof HibernateProxy ) {
- return getProxyIdentifier(object);
+ return getProxyIdentifier( object );
}
else {
EntityEntry entry = persistenceContext.getEntry(object);
@@ -1757,13 +1768,13 @@ public final class SessionImpl extends AbstractSessionImpl
public Query createQuery(String queryString) {
errorIfClosed();
checkTransactionSynchStatus();
- return super.createQuery(queryString);
+ return super.createQuery( queryString );
}
public SQLQuery createSQLQuery(String sql) {
errorIfClosed();
checkTransactionSynchStatus();
- return super.createSQLQuery(sql);
+ return super.createSQLQuery( sql );
}
public Query createSQLQuery(String sql, String returnAlias, Class returnClass) {
@@ -1839,11 +1850,11 @@ public final class SessionImpl extends AbstractSessionImpl
}
}
- public SessionFactory getSessionFactory() {
+ public SessionFactoryImplementor getSessionFactory() {
checkTransactionSynchStatus();
return factory;
}
-
+
public void initializeCollection(PersistentCollection collection, boolean writing)
throws HibernateException {
errorIfClosed();
@@ -1858,7 +1869,7 @@ public final class SessionImpl extends AbstractSessionImpl
if (object instanceof HibernateProxy) {
LazyInitializer initializer = ( ( HibernateProxy ) object ).getHibernateLazyInitializer();
// it is possible for this method to be called during flush processing,
- // so make certain that we do not accidently initialize an uninitialized proxy
+ // so make certain that we do not accidentally initialize an uninitialized proxy
if ( initializer.isUninitialized() ) {
return initializer.getEntityName();
}
@@ -1904,7 +1915,7 @@ public final class SessionImpl extends AbstractSessionImpl
public void cancelQuery() throws HibernateException {
errorIfClosed();
- getJDBCContext().getConnectionManager().cancelLastQuery();
+ getTransactionCoordinator().getJdbcCoordinator().cancelLastQuery();
}
public Interceptor getInterceptor() {
@@ -1983,23 +1994,17 @@ public final class SessionImpl extends AbstractSessionImpl
}
public void doWork(Work work) throws HibernateException {
- try {
- work.execute( jdbcContext.getConnectionManager().getConnection() );
- jdbcContext.getConnectionManager().afterStatement();
- }
- catch ( SQLException e ) {
- throw factory.getSQLExceptionHelper().convert( e, "error executing work" );
- }
+ transactionCoordinator.getJdbcCoordinator().coordinateWork( work );
}
public void afterScrollOperation() {
// nothing to do in a stateful session
}
- public JDBCContext getJDBCContext() {
+ @Override
+ public TransactionCoordinator getTransactionCoordinator() {
errorIfClosed();
- checkTransactionSynchStatus();
- return jdbcContext;
+ return transactionCoordinator;
}
public LoadQueryInfluencers getLoadQueryInfluencers() {
@@ -2098,8 +2103,8 @@ public final class SessionImpl extends AbstractSessionImpl
private void checkTransactionSynchStatus() {
- if ( jdbcContext != null && !isClosed() ) {
- jdbcContext.registerSynchronizationIfPossible();
+ if ( !isClosed() ) {
+ transactionCoordinator.pulse();
}
}
@@ -2131,7 +2136,7 @@ public final class SessionImpl extends AbstractSessionImpl
listeners = factory.getEventListeners();
if ( isRootSession ) {
- jdbcContext = JDBCContextImpl.deserialize( ois, this, interceptor );
+ transactionCoordinator = TransactionCoordinatorImpl.deserialize( ois, this );
}
persistenceContext = StatefulPersistenceContext.deserialize( ois, this );
@@ -2156,7 +2161,7 @@ public final class SessionImpl extends AbstractSessionImpl
while ( iter.hasNext() ) {
final SessionImpl child = ( ( SessionImpl ) iter.next() );
child.rootSession = this;
- child.jdbcContext = this.jdbcContext;
+ child.transactionCoordinator = this.transactionCoordinator;
}
}
}
@@ -2168,7 +2173,7 @@ public final class SessionImpl extends AbstractSessionImpl
* @throws IOException Indicates a general IO stream exception
*/
private void writeObject(ObjectOutputStream oos) throws IOException {
- if ( !jdbcContext.isReadyForSerialization() ) {
+ if ( ! transactionCoordinator.getJdbcCoordinator().getLogicalConnection().isReadyForSerialization() ) {
throw new IllegalStateException( "Cannot serialize a session while connected" );
}
@@ -2190,7 +2195,7 @@ public final class SessionImpl extends AbstractSessionImpl
factory.serialize( oos );
if ( rootSession == null ) {
- jdbcContext.serialize( oos );
+ transactionCoordinator.serialize( oos );
}
persistenceContext.serialize( oos );
@@ -2204,8 +2209,8 @@ public final class SessionImpl extends AbstractSessionImpl
/**
* {@inheritDoc}
*/
- public Object execute(Callback callback) {
- Connection connection = jdbcContext.getConnectionManager().getConnection();
+ public Object execute(LobCreationContext.Callback callback) {
+ Connection connection = transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnection();
try {
return callback.executeOnConnection( connection );
}
@@ -2216,7 +2221,7 @@ public final class SessionImpl extends AbstractSessionImpl
);
}
finally {
- jdbcContext.getConnectionManager().afterStatement();
+ transactionCoordinator.getJdbcCoordinator().getLogicalConnection().afterStatementExecution();
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java b/hibernate-core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java
index c18b38f2fd..a564766587 100755
--- a/hibernate-core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java
@@ -21,16 +21,6 @@
*/
package org.hibernate.impl;
-import java.io.Serializable;
-import java.sql.Connection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.hibernate.CacheMode;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.Criteria;
@@ -50,17 +40,19 @@ import org.hibernate.UnresolvableObjectException;
import org.hibernate.cache.CacheKey;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.engine.EntityKey;
+import org.hibernate.engine.LoadQueryInfluencers;
+import org.hibernate.engine.NonFlushedChanges;
import org.hibernate.engine.PersistenceContext;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.StatefulPersistenceContext;
import org.hibernate.engine.Versioning;
-import org.hibernate.engine.LoadQueryInfluencers;
-import org.hibernate.engine.NonFlushedChanges;
-import org.hibernate.engine.jdbc.internal.JDBCContextImpl;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.engine.query.HQLQueryPlan;
import org.hibernate.engine.query.NativeSQLQueryPlan;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
+import org.hibernate.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.event.EventListeners;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.loader.criteria.CriteriaLoader;
@@ -72,23 +64,42 @@ import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.type.Type;
import org.hibernate.util.CollectionHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.sql.Connection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* @author Gavin King
*/
-public class StatelessSessionImpl extends AbstractSessionImpl
- implements JDBCContext.Context, StatelessSession {
-
+public class StatelessSessionImpl extends AbstractSessionImpl implements StatelessSession {
private static final Logger log = LoggerFactory.getLogger( StatelessSessionImpl.class );
- private JDBCContextImpl jdbcContext;
+ private TransactionCoordinator transactionCoordinator;
private PersistenceContext temporaryPersistenceContext = new StatefulPersistenceContext( this );
StatelessSessionImpl(Connection connection, SessionFactoryImpl factory) {
super( factory );
- this.jdbcContext = new JDBCContextImpl( this, connection, EmptyInterceptor.INSTANCE );
+ this.transactionCoordinator = new TransactionCoordinatorImpl( connection, this );
}
+ // TransactionContext ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ @Override
+ public TransactionCoordinator getTransactionCoordinator() {
+ return transactionCoordinator;
+ }
+
+ @Override
+ public TransactionEnvironment getTransactionEnvironment() {
+ return factory.getTransactionEnvironment();
+ }
// inserts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -324,22 +335,33 @@ public class StatelessSessionImpl extends AbstractSessionImpl
if ( isClosed() ) {
throw new SessionException( "Session was already closed!" );
}
- jdbcContext.getConnectionManager().close();
+ transactionCoordinator.close();
setClosed();
}
public void managedFlush() {
errorIfClosed();
- getJDBCContext().getConnectionManager().executeBatch();
+ getTransactionCoordinator().getJdbcCoordinator().executeBatch();
}
public boolean shouldAutoClose() {
return isAutoCloseSessionEnabled() && !isClosed();
}
- public void afterTransactionCompletion(boolean successful, Transaction tx) {}
+ @Override
+ public void afterTransactionBegin(TransactionImplementor hibernateTransaction) {
+ // nothing to do here
+ }
- public void beforeTransactionCompletion(Transaction tx) {}
+ @Override
+ public void beforeTransactionCompletion(TransactionImplementor hibernateTransaction) {
+ // nothing to do here
+ }
+
+ @Override
+ public void afterTransactionCompletion(TransactionImplementor hibernateTransaction, boolean successful) {
+ // nothing to do here
+ }
public String bestGuessEntityName(Object object) {
if (object instanceof HibernateProxy) {
@@ -350,7 +372,7 @@ public class StatelessSessionImpl extends AbstractSessionImpl
public Connection connection() {
errorIfClosed();
- return jdbcContext.borrowConnection();
+ return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getDistinctConnectionProxy();
}
public int executeUpdate(String query, QueryParameters queryParameters)
@@ -444,11 +466,11 @@ public class StatelessSessionImpl extends AbstractSessionImpl
public boolean isConnected() {
- return jdbcContext.getConnectionManager().isCurrentlyConnected();
+ return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().isPhysicallyConnected();
}
public boolean isTransactionInProgress() {
- return jdbcContext.isTransactionInProgress();
+ return transactionCoordinator.isTransactionInProgress();
}
public void setAutoClear(boolean enabled) {
@@ -465,7 +487,7 @@ public class StatelessSessionImpl extends AbstractSessionImpl
public Transaction getTransaction() throws HibernateException {
errorIfClosed();
- return jdbcContext.getTransaction();
+ return transactionCoordinator.getTransaction();
}
public Transaction beginTransaction() throws HibernateException {
@@ -517,8 +539,8 @@ public class StatelessSessionImpl extends AbstractSessionImpl
}
public void afterOperation(boolean success) {
- if ( !jdbcContext.isTransactionInProgress() ) {
- jdbcContext.afterNontransactionalQuery(success);
+ if ( ! transactionCoordinator.isTransactionInProgress() ) {
+ transactionCoordinator.afterNonTransactionalQuery( success );;
}
}
@@ -619,7 +641,7 @@ public class StatelessSessionImpl extends AbstractSessionImpl
throws HibernateException {
errorIfClosed();
CustomLoader loader = new CustomLoader( customQuery, getFactory() );
- return loader.scroll(queryParameters, this);
+ return loader.scroll( queryParameters, this );
}
public ScrollableResults scroll(String query, QueryParameters queryParameters) throws HibernateException {
@@ -646,10 +668,6 @@ public class StatelessSessionImpl extends AbstractSessionImpl
return null;
}
- public JDBCContext getJDBCContext() {
- return jdbcContext;
- }
-
public LoadQueryInfluencers getLoadQueryInfluencers() {
return LoadQueryInfluencers.NONE;
}
@@ -667,8 +685,6 @@ public class StatelessSessionImpl extends AbstractSessionImpl
public void setFetchProfile(String name) {}
- public void afterTransactionBegin(Transaction tx) {}
-
protected boolean autoFlushIfRequired(Set querySpaces) throws HibernateException {
// no auto-flushing to support in stateless session
return false;
diff --git a/hibernate-core/src/main/java/org/hibernate/impl/TransactionEnvironmentImpl.java b/hibernate-core/src/main/java/org/hibernate/impl/TransactionEnvironmentImpl.java
new file mode 100644
index 0000000000..a3b67f7f5d
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/impl/TransactionEnvironmentImpl.java
@@ -0,0 +1,67 @@
+/*
+ * 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.impl;
+
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.jdbc.spi.JdbcServices;
+import org.hibernate.engine.transaction.spi.TransactionEnvironment;
+import org.hibernate.engine.transaction.spi.TransactionFactory;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.service.spi.ServiceRegistry;
+
+/**
+ * @author Steve Ebersole
+ */
+public class TransactionEnvironmentImpl implements TransactionEnvironment {
+ private final SessionFactoryImpl sessionFactory;
+
+ public TransactionEnvironmentImpl(SessionFactoryImpl sessionFactory) {
+ this.sessionFactory = sessionFactory;
+ }
+
+ @Override
+ public SessionFactoryImplementor getSessionFactory() {
+ return sessionFactory;
+ }
+
+ protected ServiceRegistry serviceRegistry() {
+ return sessionFactory.getServiceRegistry();
+ }
+
+ @Override
+ public JdbcServices getJdbcServices() {
+ return serviceRegistry().getService( JdbcServices.class );
+ }
+
+ @Override
+ public JtaPlatform getJtaPlatform() {
+ return serviceRegistry().getService( JtaPlatform.class );
+ }
+
+ @Override
+ public TransactionFactory getTransactionFactory() {
+ return serviceRegistry().getService( TransactionFactory.class );
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/jdbc/BorrowedConnectionProxy.java b/hibernate-core/src/main/java/org/hibernate/jdbc/BorrowedConnectionProxy.java
deleted file mode 100644
index 3b3ff05b5d..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/jdbc/BorrowedConnectionProxy.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.jdbc;
-
-import org.hibernate.HibernateException;
-import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.InvocationTargetException;
-import java.sql.Connection;
-
-/**
- * A proxy for borrowed connections which funnels all requests back
- * into the ConnectionManager from which it was borrowed to be properly
- * handled (in terms of connection release modes).
- *
- * Note: the term borrowed here refers to connection references obtained
- * via {@link org.hibernate.Session#connection()} for application usage.
- *
- * @author Steve Ebersole
- */
-public class BorrowedConnectionProxy implements InvocationHandler {
-
- private static final Class[] PROXY_INTERFACES = new Class[] { Connection.class, ConnectionWrapper.class };
-
- private final LogicalConnectionImpl logicalConnection;
- private boolean useable = true;
-
- public BorrowedConnectionProxy(LogicalConnectionImpl logicalConnection) {
- this.logicalConnection = logicalConnection;
- }
-
- /**
- * {@inheritDoc}
- */
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if ( "close".equals( method.getName() ) ) {
- logicalConnection.releaseBorrowedConnection();
- return null;
- }
- // should probably no-op commit/rollback here, at least in JTA scenarios
- if ( !useable ) {
- throw new HibernateException( "connnection proxy not usable after transaction completion" );
- }
-
- if ( "getWrappedConnection".equals( method.getName() ) ) {
- return logicalConnection.getConnection();
- }
-
- try {
- return method.invoke( logicalConnection.getConnection(), args );
- }
- catch( InvocationTargetException e ) {
- throw e.getTargetException();
- }
- }
-
- /**
- * Generates a Connection proxy wrapping the connection managed by the passed
- * connection manager.
- *
- * @param logicalConnection The logical connection to wrap with the
- * connection proxy.
- * @return The generated proxy.
- */
- public static Connection generateProxy(LogicalConnectionImpl logicalConnection) {
- BorrowedConnectionProxy handler = new BorrowedConnectionProxy( logicalConnection );
- return ( Connection ) Proxy.newProxyInstance(
- getProxyClassLoader(),
- PROXY_INTERFACES,
- handler
- );
- }
-
- /**
- * Marks a borrowed connection as no longer usable.
- *
- * @param connection The connection (proxy) to be marked.
- */
- public static void renderUnuseable(Connection connection) {
- if ( connection != null && Proxy.isProxyClass( connection.getClass() ) ) {
- InvocationHandler handler = Proxy.getInvocationHandler( connection );
- if ( BorrowedConnectionProxy.class.isAssignableFrom( handler.getClass() ) ) {
- ( ( BorrowedConnectionProxy ) handler ).useable = false;
- }
- }
- }
-
- /**
- * Convience method for unwrapping a connection proxy and getting a
- * handle to an underlying connection.
- *
- * @param connection The connection (proxy) to be unwrapped.
- * @return The unwrapped connection.
- */
- public static Connection getWrappedConnection(Connection connection) {
- if ( connection != null && connection instanceof ConnectionWrapper ) {
- return ( ( ConnectionWrapper ) connection ).getWrappedConnection();
- }
- else {
- return connection;
- }
- }
-
- /**
- * Determines the appropriate class loader to which the generated proxy
- * should be scoped.
- *
- * @return The class loader appropriate for proxy construction.
- */
- public static ClassLoader getProxyClassLoader() {
- return ConnectionWrapper.class.getClassLoader();
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/jmx/HibernateService.java b/hibernate-core/src/main/java/org/hibernate/jmx/HibernateService.java
index 9b3396b638..68c109f8ff 100644
--- a/hibernate-core/src/main/java/org/hibernate/jmx/HibernateService.java
+++ b/hibernate-core/src/main/java/org/hibernate/jmx/HibernateService.java
@@ -13,6 +13,7 @@ import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Environment;
import org.hibernate.service.internal.ServiceRegistryImpl;
+import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.internal.util.jndi.JndiHelper;
import org.hibernate.util.ExternalSessionFactoryConfig;
@@ -28,12 +29,12 @@ import org.hibernate.util.ExternalSessionFactoryConfig;
* @author John Urberg, Gavin King
*/
public class HibernateService extends ExternalSessionFactoryConfig implements HibernateServiceMBean {
-
- private static final Logger log = LoggerFactory.getLogger(HibernateServiceMBean.class);
+ private static final Logger log = LoggerFactory.getLogger( HibernateServiceMBean.class );
private String boundName;
private Properties properties = new Properties();
+ @Override
public void start() throws HibernateException {
boundName = getJndiName();
try {
@@ -46,6 +47,7 @@ public class HibernateService extends ExternalSessionFactoryConfig implements Hi
}
}
+ @Override
public void stop() {
log.info("stopping service");
try {
@@ -64,100 +66,126 @@ public class HibernateService extends ExternalSessionFactoryConfig implements Hi
return buildConfiguration().buildSessionFactory( new ServiceRegistryImpl( properties ) );
}
+ @Override
protected Map getExtraProperties() {
return properties;
}
+ @Override
public String getTransactionStrategy() {
return getProperty(Environment.TRANSACTION_STRATEGY);
}
+ @Override
public void setTransactionStrategy(String txnStrategy) {
setProperty(Environment.TRANSACTION_STRATEGY, txnStrategy);
}
+ @Override
public String getUserTransactionName() {
return getProperty(Environment.USER_TRANSACTION);
}
+ @Override
public void setUserTransactionName(String utName) {
setProperty(Environment.USER_TRANSACTION, utName);
}
- public String getTransactionManagerLookupStrategy() {
- return getProperty(Environment.TRANSACTION_MANAGER_STRATEGY);
+ @Override
+ public String getJtaPlatformName() {
+ return getProperty( JtaPlatformInitiator.JTA_PLATFORM );
}
- public void setTransactionManagerLookupStrategy(String lkpStrategy) {
- setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, lkpStrategy);
+ @Override
+ public void setJtaPlatformName(String name) {
+ setProperty( JtaPlatformInitiator.JTA_PLATFORM, name );
}
+ @Override
public String getPropertyList() {
return buildProperties().toString();
}
+ @Override
public String getProperty(String property) {
return properties.getProperty(property);
}
+ @Override
public void setProperty(String property, String value) {
properties.setProperty(property, value);
}
+ @Override
public void dropSchema() {
new SchemaExport( buildConfiguration() ).drop(false, true);
}
+ @Override
public void createSchema() {
new SchemaExport( buildConfiguration() ).create(false, true);
- } public String getName() {
+ }
+
+ public String getName() {
return getProperty(Environment.SESSION_FACTORY_NAME);
}
+ @Override
public String getDatasource() {
return getProperty(Environment.DATASOURCE);
}
+ @Override
public void setDatasource(String datasource) {
setProperty(Environment.DATASOURCE, datasource);
}
+ @Override
public String getJndiName() {
return getProperty(Environment.SESSION_FACTORY_NAME);
}
+ @Override
public void setJndiName(String jndiName) {
setProperty(Environment.SESSION_FACTORY_NAME, jndiName);
}
+ @Override
public String getUserName() {
return getProperty(Environment.USER);
}
+ @Override
public void setUserName(String userName) {
setProperty(Environment.USER, userName);
}
+ @Override
public String getPassword() {
return getProperty(Environment.PASS);
}
+ @Override
public void setPassword(String password) {
setProperty(Environment.PASS, password);
}
+ @Override
public void setFlushBeforeCompletionEnabled(String enabled) {
setProperty(Environment.FLUSH_BEFORE_COMPLETION, enabled);
}
+ @Override
public String getFlushBeforeCompletionEnabled() {
return getProperty(Environment.FLUSH_BEFORE_COMPLETION);
}
+ @Override
public void setAutoCloseSessionEnabled(String enabled) {
setProperty(Environment.AUTO_CLOSE_SESSION, enabled);
}
+ @Override
public String getAutoCloseSessionEnabled() {
return getProperty(Environment.AUTO_CLOSE_SESSION);
}
diff --git a/hibernate-core/src/main/java/org/hibernate/jmx/HibernateServiceMBean.java b/hibernate-core/src/main/java/org/hibernate/jmx/HibernateServiceMBean.java
index d161c7f0cf..13e768405d 100644
--- a/hibernate-core/src/main/java/org/hibernate/jmx/HibernateServiceMBean.java
+++ b/hibernate-core/src/main/java/org/hibernate/jmx/HibernateServiceMBean.java
@@ -104,44 +104,47 @@ public interface HibernateServiceMBean {
public void setJndiName(String jndiName);
/**
- * The fully qualified class name of the Hibernate TransactionFactory implementation
+ * The fully qualified class name of the Hibernate {@link org.hibernate.engine.transaction.spi.TransactionFactory}
+ * implementation to use
+ *
* @return the class name
- * @see org.hibernate.transaction.TransactionFactory
*/
public String getTransactionStrategy();
/**
- * Set the fully qualified class name of the Hibernate TransactionFactory implementation
+ * Set the fully qualified class name of the Hibernate {@link org.hibernate.engine.transaction.spi.TransactionFactory}
+ * implementation to use.
+ *
* @param txnStrategy the class name
- * @see org.hibernate.transaction.TransactionFactory
*/
public void setTransactionStrategy(String txnStrategy);
/**
- * The JNDI name of the JTA UserTransaction object (used only be JTATransaction).
+ * The JNDI name of the JTA UserTransaction object (used only be JtaTransaction).
* @return the JNDI name
- * @see org.hibernate.transaction.JTATransaction
+ * @see org.hibernate.engine.transaction.internal.jta.JtaTransaction
*/
public String getUserTransactionName();
/**
- * Set the JNDI name of the JTA UserTransaction object (used only by JTATransaction).
+ * Set the JNDI name of the JTA UserTransaction object (used only by JtaTransaction).
* @param utName the JNDI name
- * @see org.hibernate.transaction.JTATransaction
+ * @see org.hibernate.engine.transaction.internal.jta.JtaTransaction
*/
public void setUserTransactionName(String utName);
/**
- * Get the strategy for obtaining the JTA TransactionManager
- * @return the class name
- * @see org.hibernate.transaction.TransactionManagerLookup
+ * Get the name of the {@link org.hibernate.service.jta.platform.spi.JtaPlatform} implementation to use.
+ *
+ * @return The name of the {@link org.hibernate.service.jta.platform.spi.JtaPlatform} implementation to use.
*/
- public String getTransactionManagerLookupStrategy();
+ public String getJtaPlatformName();
+
/**
- * Set the strategy for obtaining the JTA TransactionManager
- * @param lkpStrategy the class name
- * @see org.hibernate.transaction.TransactionManagerLookup
+ * Sets the name of the {@link org.hibernate.service.jta.platform.spi.JtaPlatform} implementation to use.
+ *
+ * @param name The implementation class name.
*/
- public void setTransactionManagerLookupStrategy(String lkpStrategy);
+ public void setJtaPlatformName(String name);
/**
* Is SQL logging enabled?
diff --git a/hibernate-core/src/main/java/org/hibernate/loader/Loader.java b/hibernate-core/src/main/java/org/hibernate/loader/Loader.java
index b0e8d6ca91..2f67dd3e74 100644
--- a/hibernate-core/src/main/java/org/hibernate/loader/Loader.java
+++ b/hibernate-core/src/main/java/org/hibernate/loader/Loader.java
@@ -1731,11 +1731,17 @@ public abstract class Loader {
boolean hasFirstRow = getFirstRow( selection ) > 0;
boolean useOffset = hasFirstRow && useLimit && dialect.supportsLimitOffset();
boolean callable = queryParameters.isCallable();
-
- boolean useScrollableResultSetToSkip = hasFirstRow &&
+
+ final boolean canScroll = getFactory().getSettings().isScrollableResultSetsEnabled();
+ final boolean useScrollableResultSetToSkip = hasFirstRow &&
!useOffset &&
getFactory().getSettings().isScrollableResultSetsEnabled();
- ScrollMode scrollMode = scroll ? queryParameters.getScrollMode() : ScrollMode.SCROLL_INSENSITIVE;
+ final ScrollMode scrollMode =
+ canScroll
+ ? scroll || useScrollableResultSetToSkip
+ ? queryParameters.getScrollMode()
+ : ScrollMode.SCROLL_INSENSITIVE
+ : null;
if ( useLimit ) {
sql = dialect.getLimitString(
@@ -1746,14 +1752,14 @@ public abstract class Loader {
}
sql = preprocessSQL( sql, queryParameters, dialect );
-
+
PreparedStatement st = null;
- st = session.getJDBCContext().getConnectionManager().prepareQueryStatement(
+
+ st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareQueryStatement(
sql,
- scroll || useScrollableResultSetToSkip,
- scrollMode,
- callable
+ callable,
+ scrollMode
);
try {
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java
index cabd43a6bd..9136e97486 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java
@@ -23,15 +23,6 @@
*/
package org.hibernate.persister.collection;
-import java.io.Serializable;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
import org.hibernate.AssertionFailure;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
@@ -54,6 +45,7 @@ import org.hibernate.engine.PersistenceContext;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
+import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
import org.hibernate.exception.SQLExceptionConverter;
import org.hibernate.id.IdentifierGenerator;
@@ -88,6 +80,15 @@ import org.hibernate.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
/**
* Base implementation of the QueryableCollection interface.
@@ -1062,8 +1063,9 @@ public abstract class AbstractCollectionPersister
return qualifiedTableName;
}
- public void remove(Serializable id, SessionImplementor session) throws HibernateException {
+ private BasicBatchKey removeBatchKey;
+ public void remove(Serializable id, SessionImplementor session) throws HibernateException {
if ( !isInverse && isRowDeleteEnabled() ) {
if ( log.isDebugEnabled() ) {
@@ -1083,10 +1085,22 @@ public abstract class AbstractCollectionPersister
boolean useBatch = expectation.canBeBatched();
String sql = getSQLDeleteString();
if ( useBatch ) {
- st = session.getJDBCContext().getConnectionManager().prepareBatchStatement( this, sql, callable );
+ if ( removeBatchKey == null ) {
+ removeBatchKey = new BasicBatchKey(
+ getRole() + "#REMOVE",
+ expectation
+ );
+ }
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( removeBatchKey )
+ .getBatchStatement( sql, callable );
}
else {
- st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql, callable );
}
@@ -1095,7 +1109,10 @@ public abstract class AbstractCollectionPersister
writeKey( st, id, offset, session );
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().addToBatch( this, sql, expectation );
+ session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( removeBatchKey )
+ .addToBatch();
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@@ -1103,7 +1120,7 @@ public abstract class AbstractCollectionPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().abortBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
}
throw sqle;
}
@@ -1130,6 +1147,8 @@ public abstract class AbstractCollectionPersister
}
+ private BasicBatchKey recreateBatchKey;
+
public void recreate(PersistentCollection collection, Serializable id, SessionImplementor session)
throws HibernateException {
@@ -1146,6 +1165,7 @@ public abstract class AbstractCollectionPersister
//create all the new entries
Iterator entries = collection.entries(this);
if ( entries.hasNext() ) {
+ Expectation expectation = Expectations.appropriateExpectation( getInsertCheckStyle() );
collection.preInsert( this );
int i = 0;
int count = 0;
@@ -1155,18 +1175,27 @@ public abstract class AbstractCollectionPersister
if ( collection.entryExists( entry, i ) ) {
int offset = 1;
PreparedStatement st = null;
- Expectation expectation = Expectations.appropriateExpectation( getInsertCheckStyle() );
boolean callable = isInsertCallable();
boolean useBatch = expectation.canBeBatched();
String sql = getSQLInsertRowString();
if ( useBatch ) {
- st = session.getJDBCContext().getConnectionManager().prepareBatchStatement(
- this, sql, callable
- );
+ if ( recreateBatchKey == null ) {
+ recreateBatchKey = new BasicBatchKey(
+ getRole() + "#RECREATE",
+ expectation
+ );
+ }
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( recreateBatchKey )
+ .getBatchStatement( sql, callable );
}
else {
- st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql, callable );
}
@@ -1184,7 +1213,10 @@ public abstract class AbstractCollectionPersister
loc = writeElement(st, collection.getElement(entry), loc, session );
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().addToBatch( this, sql, expectation );
+ session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( recreateBatchKey )
+ .addToBatch();
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@@ -1195,7 +1227,7 @@ public abstract class AbstractCollectionPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().abortBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
}
throw sqle;
}
@@ -1235,6 +1267,8 @@ public abstract class AbstractCollectionPersister
return true;
}
+ private BasicBatchKey deleteBatchKey;
+
public void deleteRows(PersistentCollection collection, Serializable id, SessionImplementor session)
throws HibernateException {
@@ -1248,7 +1282,7 @@ public abstract class AbstractCollectionPersister
}
boolean deleteByIndex = !isOneToMany() && hasIndex && !indexContainsFormula;
-
+ final Expectation expectation = Expectations.appropriateExpectation( getDeleteCheckStyle() );
try {
//delete all the deleted entries
Iterator deletes = collection.getDeletes( this, !deleteByIndex );
@@ -1257,18 +1291,27 @@ public abstract class AbstractCollectionPersister
int count = 0;
while ( deletes.hasNext() ) {
PreparedStatement st = null;
- Expectation expectation = Expectations.appropriateExpectation( getDeleteCheckStyle() );
boolean callable = isDeleteCallable();
boolean useBatch = expectation.canBeBatched();
String sql = getSQLDeleteRowString();
if ( useBatch ) {
- st = session.getJDBCContext().getConnectionManager().prepareBatchStatement(
- this, sql, callable
- );
+ if ( deleteBatchKey == null ) {
+ deleteBatchKey = new BasicBatchKey(
+ getRole() + "#DELETE",
+ expectation
+ );
+ }
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( deleteBatchKey )
+ .getBatchStatement( sql, callable );
}
else {
- st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql, callable );
}
try {
@@ -1290,7 +1333,10 @@ public abstract class AbstractCollectionPersister
}
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().addToBatch( this, sql, expectation );
+ session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( deleteBatchKey )
+ .addToBatch();
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@@ -1299,7 +1345,7 @@ public abstract class AbstractCollectionPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().abortBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
}
throw sqle;
}
@@ -1335,6 +1381,8 @@ public abstract class AbstractCollectionPersister
return true;
}
+ private BasicBatchKey insertBatchKey;
+
public void insertRows(PersistentCollection collection, Serializable id, SessionImplementor session)
throws HibernateException {
@@ -1364,14 +1412,24 @@ public abstract class AbstractCollectionPersister
if ( collection.needsInserting( entry, i, elementType ) ) {
if ( useBatch ) {
- if ( st == null ) {
- st = session.getJDBCContext().getConnectionManager().prepareBatchStatement(
- this, sql, callable
+ if ( insertBatchKey == null ) {
+ insertBatchKey = new BasicBatchKey(
+ getRole() + "#INSERT",
+ expectation
);
}
+ if ( st == null ) {
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( insertBatchKey )
+ .getBatchStatement( sql, callable );
+ }
}
else {
- st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql, callable );
}
try {
@@ -1387,7 +1445,7 @@ public abstract class AbstractCollectionPersister
writeElement(st, collection.getElement(entry), offset, session );
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().addToBatch( this, sql, expectation );
+ session.getTransactionCoordinator().getJdbcCoordinator().getBatch( insertBatchKey ).addToBatch();
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@@ -1397,7 +1455,7 @@ public abstract class AbstractCollectionPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().abortBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
}
throw sqle;
}
@@ -1709,7 +1767,10 @@ public abstract class AbstractCollectionPersister
public int getSize(Serializable key, SessionImplementor session) {
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement(sqlSelectSizeString);
+ PreparedStatement st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sqlSelectSizeString );
try {
getKeyType().nullSafeSet(st, key, 1, session);
ResultSet rs = st.executeQuery();
@@ -1744,7 +1805,10 @@ public abstract class AbstractCollectionPersister
private boolean exists(Serializable key, Object indexOrElement, Type indexOrElementType, String sql, SessionImplementor session) {
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement(sql);
+ PreparedStatement st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql );
try {
getKeyType().nullSafeSet(st, key, 1, session);
indexOrElementType.nullSafeSet( st, indexOrElement, keyColumnNames.length + 1, session );
@@ -1775,7 +1839,10 @@ public abstract class AbstractCollectionPersister
public Object getElementByIndex(Serializable key, Object index, SessionImplementor session, Object owner) {
try {
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement(sqlSelectRowByIndexString);
+ PreparedStatement st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sqlSelectRowByIndexString );
try {
getKeyType().nullSafeSet(st, key, 1, session);
getIndexType().nullSafeSet( st, incrementIndexByBase(index), keyColumnNames.length + 1, session );
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java
index 4fa624149b..80e5c73487 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java
@@ -39,6 +39,7 @@ import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
import org.hibernate.engine.LoadQueryInfluencers;
+import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations;
import org.hibernate.loader.collection.BatchingCollectionInitializer;
@@ -190,6 +191,8 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
return elementType.isEntityType(); //instanceof AssociationType;
}
+ private BasicBatchKey updateBatchKey;
+
protected int doUpdateRows(Serializable id, PersistentCollection collection, SessionImplementor session)
throws HibernateException {
@@ -210,14 +213,22 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
int offset = 1;
if ( useBatch ) {
- if ( st == null ) {
- st = session.getJDBCContext().getConnectionManager().prepareBatchStatement(
- this, sql, callable
+ if ( updateBatchKey == null ) {
+ updateBatchKey = new BasicBatchKey(
+ getRole() + "#UPDATE",
+ expectation
);
}
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( updateBatchKey )
+ .getBatchStatement( sql, callable );
}
else {
- st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql, callable );
}
try {
@@ -237,7 +248,10 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
}
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().addToBatch( this, sql, expectation );
+ session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( updateBatchKey )
+ .addToBatch();
}
else {
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
@@ -245,7 +259,7 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
}
catch ( SQLException sqle ) {
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().abortBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
}
throw sqle;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java
index 2057a92cd6..64978a4af9 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java
@@ -24,21 +24,16 @@
*/
package org.hibernate.persister.collection;
-import java.io.Serializable;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.util.Iterator;
-
-import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cfg.Configuration;
import org.hibernate.collection.PersistentCollection;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
-import org.hibernate.engine.LoadQueryInfluencers;
+import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations;
import org.hibernate.loader.collection.BatchingCollectionInitializer;
@@ -52,6 +47,11 @@ import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.Update;
import org.hibernate.util.ArrayHelper;
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Iterator;
+
/**
* Collection persister for one-to-many associations.
*
@@ -174,8 +174,10 @@ public class OneToManyPersister extends AbstractCollectionPersister {
return false;
}
- protected int doUpdateRows(Serializable id, PersistentCollection collection, SessionImplementor session)
- throws HibernateException {
+ private BasicBatchKey deleteRowBatchKey;
+ private BasicBatchKey insertRowBatchKey;
+
+ protected int doUpdateRows(Serializable id, PersistentCollection collection, SessionImplementor session) {
// we finish all the "removes" first to take care of possible unique
// constraints and so that we can take better advantage of batching
@@ -183,53 +185,58 @@ public class OneToManyPersister extends AbstractCollectionPersister {
try {
int count = 0;
if ( isRowDeleteEnabled() ) {
- boolean useBatch = true;
+ final Expectation deleteExpectation = Expectations.appropriateExpectation( getDeleteCheckStyle() );
+ final boolean useBatch = deleteExpectation.canBeBatched();
+ if ( useBatch && deleteRowBatchKey == null ) {
+ deleteRowBatchKey = new BasicBatchKey(
+ getRole() + "#DELETEROW",
+ deleteExpectation
+ );
+ }
+ final String sql = getSQLDeleteRowString();
+
PreparedStatement st = null;
// update removed rows fks to null
try {
int i = 0;
-
Iterator entries = collection.entries( this );
int offset = 1;
- Expectation expectation = Expectations.NONE;
while ( entries.hasNext() ) {
-
Object entry = entries.next();
if ( collection.needsUpdating( entry, i, elementType ) ) { // will still be issued when it used to be null
- String sql = getSQLDeleteRowString();
- if ( st == null ) {
- if ( isDeleteCallable() ) {
- expectation = Expectations.appropriateExpectation( getDeleteCheckStyle() );
- useBatch = expectation.canBeBatched();
- st = useBatch
- ? session.getJDBCContext().getConnectionManager().prepareBatchStatement( this, sql, true )
- : session.getJDBCContext().getConnectionManager().prepareStatement( sql, true );
- offset += expectation.prepare( st );
- }
- else {
- st = session.getJDBCContext().getConnectionManager().prepareBatchStatement(
- this, sql, false
- );
- }
+ if ( useBatch ) {
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( deleteRowBatchKey )
+ .getBatchStatement( sql, isDeleteCallable() );
+ }
+ else {
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql, isDeleteCallable() );
}
int loc = writeKey( st, id, offset, session );
writeElementToWhere( st, collection.getSnapshotElement(entry, i), loc, session );
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().addToBatch( this, sql, expectation );
+ session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( deleteRowBatchKey )
+ .addToBatch();
}
else {
- expectation.verifyOutcome( st.executeUpdate(), st, -1 );
+ deleteExpectation.verifyOutcome( st.executeUpdate(), st, -1 );
}
count++;
}
i++;
}
}
- catch ( SQLException sqle ) {
+ catch ( SQLException e ) {
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().abortBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
}
- throw sqle;
+ throw e;
}
finally {
if ( !useBatch ) {
@@ -239,10 +246,17 @@ public class OneToManyPersister extends AbstractCollectionPersister {
}
if ( isRowInsertEnabled() ) {
- Expectation expectation = Expectations.appropriateExpectation( getInsertCheckStyle() );
+ final Expectation insertExpectation = Expectations.appropriateExpectation( getInsertCheckStyle() );
+ boolean useBatch = insertExpectation.canBeBatched();
boolean callable = isInsertCallable();
- boolean useBatch = expectation.canBeBatched();
- String sql = getSQLInsertRowString();
+ if ( useBatch && insertRowBatchKey == null ) {
+ insertRowBatchKey = new BasicBatchKey(
+ getRole() + "#INSERTROW",
+ insertExpectation
+ );
+ }
+ final String sql = getSQLInsertRowString();
+
PreparedStatement st = null;
// now update all changed or added rows fks
try {
@@ -253,17 +267,19 @@ public class OneToManyPersister extends AbstractCollectionPersister {
int offset = 1;
if ( collection.needsUpdating( entry, i, elementType ) ) {
if ( useBatch ) {
- if ( st == null ) {
- st = session.getJDBCContext().getConnectionManager().prepareBatchStatement(
- this, sql, callable
- );
- }
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( insertRowBatchKey )
+ .getBatchStatement( sql, callable );
}
else {
- st = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql, callable );
}
- offset += expectation.prepare( st );
+ offset += insertExpectation.prepare( st );
int loc = writeKey( st, id, offset, session );
if ( hasIndex && !indexContainsFormula ) {
@@ -273,10 +289,10 @@ public class OneToManyPersister extends AbstractCollectionPersister {
writeElementToWhere( st, collection.getElement( entry ), loc, session );
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().addToBatch( this, sql, expectation );
+ session.getTransactionCoordinator().getJdbcCoordinator().getBatch( insertRowBatchKey ).addToBatch();
}
else {
- expectation.verifyOutcome( st.executeUpdate(), st, -1 );
+ insertExpectation.verifyOutcome( st.executeUpdate(), st, -1 );
}
count++;
}
@@ -285,7 +301,7 @@ public class OneToManyPersister extends AbstractCollectionPersister {
}
catch ( SQLException sqle ) {
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().abortBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
}
throw sqle;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
index 612ed153fb..22b6f8dcab 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
@@ -23,22 +23,6 @@
*/
package org.hibernate.persister.entity;
-import java.io.Serializable;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.FetchMode;
@@ -67,6 +51,7 @@ import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.ValueInclusion;
import org.hibernate.engine.Versioning;
+import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.PostInsertIdentityPersister;
@@ -111,6 +96,21 @@ import org.hibernate.type.VersionType;
import org.hibernate.util.ArrayHelper;
import org.hibernate.util.FilterHelper;
import org.hibernate.util.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
/**
* Basic functionality for persisting an entity via JDBC
@@ -854,7 +854,10 @@ 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.getJDBCContext().getConnectionManager().prepareSelectStatement(lazySelect);
+ ps = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( lazySelect );
getIdentifierType().nullSafeSet( ps, id, 1, session );
rs = ps.executeQuery();
rs.next();
@@ -1101,7 +1104,10 @@ public abstract class AbstractEntityPersister
}
try {
- PreparedStatement ps = session.getJDBCContext().getConnectionManager().prepareSelectStatement( getSQLSnapshotSelectString() );
+ PreparedStatement ps = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( getSQLSnapshotSelectString() );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
//if ( isVersioned() ) getVersionType().nullSafeSet( ps, version, getIdentifierColumnSpan()+1, session );
@@ -1111,7 +1117,6 @@ public abstract class AbstractEntityPersister
if ( !rs.next() ) {
return null;
}
-
//otherwise return the "hydrated" state (ie. associations are not resolved)
Type[] types = getPropertyTypes();
Object[] values = new Object[types.length];
@@ -1131,13 +1136,12 @@ public abstract class AbstractEntityPersister
ps.close();
}
}
- catch ( SQLException sqle ) {
+ catch ( SQLException e ) {
throw getFactory().getSQLExceptionHelper().convert(
- sqle,
- "could not retrieve snapshot: " +
- MessageHelper.infoString( this, id, getFactory() ),
+ e,
+ "could not retrieve snapshot: " + MessageHelper.infoString( this, id, getFactory() ),
getSQLSnapshotSelectString()
- );
+ );
}
}
@@ -1315,8 +1319,11 @@ public abstract class AbstractEntityPersister
String versionIncrementString = generateVersionIncrementUpdateString();
PreparedStatement st = null;
try {
+ st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( versionIncrementString, false );
try {
- st = session.getJDBCContext().getConnectionManager().prepareStatement( versionIncrementString, false );
getVersionType().nullSafeSet( st, nextVersion, 1, session );
getIdentifierType().nullSafeSet( st, id, 2, session );
getVersionType().nullSafeSet( st, currentVersion, 2 + getIdentifierColumnSpan(), session );
@@ -1363,11 +1370,12 @@ public abstract class AbstractEntityPersister
}
try {
-
- PreparedStatement st = session.getJDBCContext().getConnectionManager().prepareSelectStatement( getVersionSelectString() );
+ PreparedStatement st = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( getVersionSelectString() );
try {
getIdentifierType().nullSafeSet( st, id, 1, session );
-
ResultSet rs = st.executeQuery();
try {
if ( !rs.next() ) {
@@ -1385,17 +1393,14 @@ public abstract class AbstractEntityPersister
finally {
st.close();
}
-
}
- catch ( SQLException sqle ) {
+ catch ( SQLException e ) {
throw getFactory().getSQLExceptionHelper().convert(
- sqle,
- "could not retrieve version: " +
- MessageHelper.infoString( this, id, getFactory() ),
+ e,
+ "could not retrieve version: " + MessageHelper.infoString( this, id, getFactory() ),
getVersionSelectString()
- );
+ );
}
-
}
protected void initLockers() {
@@ -2223,7 +2228,10 @@ 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.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ sequentialSelect = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql );
rootPersister.getIdentifierType().nullSafeSet( sequentialSelect, id, 1, session );
sequentialResultSet = sequentialSelect.executeQuery();
if ( !sequentialResultSet.next() ) {
@@ -2355,6 +2363,8 @@ public abstract class AbstractEntityPersister
.toStatementString();
}
+ private BasicBatchKey inserBatchKey;
+
/**
* Perform an SQL INSERT.
*
@@ -2387,20 +2397,33 @@ public abstract class AbstractEntityPersister
}
}
- Expectation expectation = Expectations.appropriateExpectation( insertResultCheckStyles[j] );
- boolean callable = isInsertCallable( j );
+ // TODO : shouldn't inserts be Expectations.NONE?
+ final Expectation expectation = Expectations.appropriateExpectation( insertResultCheckStyles[j] );
// we can't batch joined inserts, *especially* not if it is an identity insert;
// nor can we batch statements where the expectation is based on an output param
final boolean useBatch = j == 0 && expectation.canBeBatched();
- try {
+ if ( useBatch && inserBatchKey == null ) {
+ inserBatchKey = new BasicBatchKey(
+ getEntityName() + "#INSERT",
+ expectation
+ );
+ }
+ final boolean callable = isInsertCallable( j );
+ try {
// Render the SQL query
final PreparedStatement insert;
if ( useBatch ) {
- insert = session.getJDBCContext().getConnectionManager().prepareBatchStatement( this, sql, callable );
+ insert = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( inserBatchKey )
+ .getBatchStatement( sql, callable );
}
else {
- insert = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
+ insert = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql, callable );
}
try {
@@ -2413,19 +2436,18 @@ public abstract class AbstractEntityPersister
dehydrate( id, fields, null, notNull, propertyColumnInsertable, j, insert, session, index );
if ( useBatch ) {
- // TODO : shouldnt inserts be Expectations.NONE?
- session.getJDBCContext().getConnectionManager().addToBatch( this, sql, expectation );
+ session.getTransactionCoordinator().getJdbcCoordinator().getBatch( inserBatchKey ).addToBatch();
}
else {
expectation.verifyOutcome( insert.executeUpdate(), insert, -1 );
}
}
- catch ( SQLException sqle ) {
+ catch ( SQLException e ) {
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().abortBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
}
- throw sqle;
+ throw e;
}
finally {
if ( !useBatch ) {
@@ -2433,12 +2455,12 @@ public abstract class AbstractEntityPersister
}
}
}
- catch ( SQLException sqle ) {
+ catch ( SQLException e ) {
throw getFactory().getSQLExceptionHelper().convert(
- sqle,
+ e,
"could not insert: " + MessageHelper.infoString( this ),
sql
- );
+ );
}
}
@@ -2487,6 +2509,8 @@ public abstract class AbstractEntityPersister
}
+ private BasicBatchKey updateBatchKey;
+
protected boolean update(
final Serializable id,
final Object[] fields,
@@ -2499,10 +2523,16 @@ public abstract class AbstractEntityPersister
final String sql,
final SessionImplementor session) throws HibernateException {
- final boolean useVersion = j == 0 && isVersioned();
final Expectation expectation = Expectations.appropriateExpectation( updateResultCheckStyles[j] );
- final boolean callable = isUpdateCallable( j );
final boolean useBatch = j == 0 && expectation.canBeBatched() && isBatchable(); //note: updates to joined tables can't be batched...
+ if ( useBatch && updateBatchKey == null ) {
+ updateBatchKey = new BasicBatchKey(
+ getEntityName() + "#UPDATE",
+ expectation
+ );
+ }
+ final boolean callable = isUpdateCallable( j );
+ final boolean useVersion = j == 0 && isVersioned();
if ( log.isTraceEnabled() ) {
log.trace( "Updating entity: " + MessageHelper.infoString( this, id, getFactory() ) );
@@ -2512,18 +2542,22 @@ public abstract class AbstractEntityPersister
}
try {
-
int index = 1; // starting index
final PreparedStatement update;
if ( useBatch ) {
- update = session.getJDBCContext().getConnectionManager().prepareBatchStatement( this, sql, callable );
+ update = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( updateBatchKey )
+ .getBatchStatement( sql, callable );
}
else {
- update = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
+ update = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql, callable );
}
try {
-
index+= expectation.prepare( update );
//Now write the values of fields onto the prepared statement
@@ -2559,7 +2593,7 @@ public abstract class AbstractEntityPersister
}
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().addToBatch( this, sql, expectation );
+ session.getTransactionCoordinator().getJdbcCoordinator().getBatch( updateBatchKey ).addToBatch();
return true;
}
else {
@@ -2567,11 +2601,11 @@ public abstract class AbstractEntityPersister
}
}
- catch ( SQLException sqle ) {
+ catch ( SQLException e ) {
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().abortBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
}
- throw sqle;
+ throw e;
}
finally {
if ( !useBatch ) {
@@ -2580,15 +2614,17 @@ public abstract class AbstractEntityPersister
}
}
- catch ( SQLException sqle ) {
+ catch ( SQLException e ) {
throw getFactory().getSQLExceptionHelper().convert(
- sqle,
+ e,
"could not update: " + MessageHelper.infoString( this, id, getFactory() ),
sql
);
}
}
+ private BasicBatchKey deleteBatchKey;
+
/**
* Perform an SQL DELETE
*/
@@ -2609,6 +2645,12 @@ public abstract class AbstractEntityPersister
final boolean callable = isDeleteCallable( j );
final Expectation expectation = Expectations.appropriateExpectation( deleteResultCheckStyles[j] );
final boolean useBatch = j == 0 && isBatchable() && expectation.canBeBatched();
+ if ( useBatch && deleteBatchKey == null ) {
+ deleteBatchKey = new BasicBatchKey(
+ getEntityName() + "#DELETE",
+ expectation
+ );
+ }
if ( log.isTraceEnabled() ) {
log.trace( "Deleting entity: " + MessageHelper.infoString( this, id, getFactory() ) );
@@ -2625,15 +2667,20 @@ public abstract class AbstractEntityPersister
}
try {
-
//Render the SQL query
PreparedStatement delete;
int index = 1;
if ( useBatch ) {
- delete = session.getJDBCContext().getConnectionManager().prepareBatchStatement( this, sql, callable );
+ delete = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getBatch( deleteBatchKey )
+ .getBatchStatement( sql, callable );
}
else {
- delete = session.getJDBCContext().getConnectionManager().prepareStatement( sql, callable );
+ delete = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql, callable );
}
try {
@@ -2665,7 +2712,7 @@ public abstract class AbstractEntityPersister
}
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().addToBatch( this, sql, expectation );
+ session.getTransactionCoordinator().getJdbcCoordinator().getBatch( deleteBatchKey ).addToBatch();
}
else {
check( delete.executeUpdate(), id, j, expectation, delete );
@@ -2674,7 +2721,7 @@ public abstract class AbstractEntityPersister
}
catch ( SQLException sqle ) {
if ( useBatch ) {
- session.getJDBCContext().getConnectionManager().abortBatch();
+ session.getTransactionCoordinator().getJdbcCoordinator().abortBatch();
}
throw sqle;
}
@@ -3956,11 +4003,14 @@ public abstract class AbstractEntityPersister
SessionImplementor session,
String selectionSQL,
ValueInclusion[] includeds) {
-
- session.getJDBCContext().getConnectionManager().executeBatch(); //force immediate execution of the insert
+ // force immediate execution of the insert batch (if one)
+ session.getTransactionCoordinator().getJdbcCoordinator().executeBatch();
try {
- PreparedStatement ps = session.getJDBCContext().getConnectionManager().prepareSelectStatement( selectionSQL );
+ PreparedStatement ps = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( selectionSQL );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
ResultSet rs = ps.executeQuery();
@@ -3989,9 +4039,9 @@ public abstract class AbstractEntityPersister
ps.close();
}
}
- catch( SQLException sqle ) {
+ catch( SQLException e ) {
throw getFactory().getSQLExceptionHelper().convert(
- sqle,
+ e,
"unable to select generated column values",
selectionSQL
);
@@ -4056,7 +4106,10 @@ public abstract class AbstractEntityPersister
Object[] snapshot = new Object[ naturalIdPropertyCount ];
try {
- PreparedStatement ps = session.getJDBCContext().getConnectionManager().prepareSelectStatement( sql );
+ PreparedStatement ps = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( sql );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
ResultSet rs = ps.executeQuery();
@@ -4065,7 +4118,6 @@ public abstract class AbstractEntityPersister
if ( !rs.next() ) {
return null;
}
-
final EntityKey key = new EntityKey( id, this, session.getEntityMode() );
Object owner = session.getPersistenceContext().getEntity( key );
for ( int i = 0; i < naturalIdPropertyCount; i++ ) {
@@ -4084,13 +4136,12 @@ public abstract class AbstractEntityPersister
ps.close();
}
}
- catch ( SQLException sqle ) {
+ catch ( SQLException e ) {
throw getFactory().getSQLExceptionHelper().convert(
- sqle,
- "could not retrieve snapshot: " +
- MessageHelper.infoString( this, id, getFactory() ),
+ e,
+ "could not retrieve snapshot: " + MessageHelper.infoString( this, id, getFactory() ),
sql
- );
+ );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/ServiceInitializer.java b/hibernate-core/src/main/java/org/hibernate/service/internal/ServiceInitializer.java
index 48002ff973..4917e50c6f 100644
--- a/hibernate-core/src/main/java/org/hibernate/service/internal/ServiceInitializer.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/internal/ServiceInitializer.java
@@ -101,6 +101,9 @@ public class ServiceInitializer {
// PHASE 1 : create service
T service = createService( serviceRole );
+ if ( service == null ) {
+ return null;
+ }
// PHASE 2 : configure service (***potentially recursive***)
configureService( service );
@@ -145,13 +148,18 @@ public class ServiceInitializer {
}
private void applyInjections(T service) {
- for ( Method method : service.getClass().getMethods() ) {
- InjectService injectService = method.getAnnotation( InjectService.class );
- if ( injectService == null ) {
- continue;
- }
+ try {
+ for ( Method method : service.getClass().getMethods() ) {
+ InjectService injectService = method.getAnnotation( InjectService.class );
+ if ( injectService == null ) {
+ continue;
+ }
- applyInjection( service, method, injectService );
+ applyInjection( service, method, injectService );
+ }
+ }
+ catch (NullPointerException e) {
+ log.error( "NPE injecting service deps : " + service.getClass().getName() );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/ServiceRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/ServiceRegistryImpl.java
index 65f8e094cf..bb53ab4a03 100644
--- a/hibernate-core/src/main/java/org/hibernate/service/internal/ServiceRegistryImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/internal/ServiceRegistryImpl.java
@@ -39,6 +39,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
@@ -73,7 +74,7 @@ public class ServiceRegistryImpl implements ServiceRegistry, ServiceProxyTargetS
}
public void destroy() {
- ListIterator serviceIterator = serviceList.listIterator();
+ ListIterator serviceIterator = serviceList.listIterator( serviceList.size() );
while ( serviceIterator.hasPrevious() ) {
final Service service = serviceIterator.previous();
if ( Stoppable.class.isInstance( service ) ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java b/hibernate-core/src/main/java/org/hibernate/service/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java
index 8ce96e19c9..de059feb8d 100644
--- a/hibernate-core/src/main/java/org/hibernate/service/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java
@@ -51,6 +51,7 @@ import org.hibernate.util.ReflectHelper;
* @author Gavin King
* @author Steve Ebersole
*/
+@SuppressWarnings( {"UnnecessaryUnboxing"})
public class DriverManagerConnectionProviderImpl implements ConnectionProvider, Configurable, Stoppable {
private static final Logger log = LoggerFactory.getLogger( DriverManagerConnectionProviderImpl.class );
@@ -63,6 +64,8 @@ public class DriverManagerConnectionProviderImpl implements ConnectionProvider,
private final ArrayList pool = new ArrayList();
private int checkedOut = 0;
+ private boolean stopped;
+
@Override
public boolean isUnwrappableAs(Class unwrapType) {
return ConnectionProvider.class.equals( unwrapType ) ||
@@ -144,6 +147,7 @@ public class DriverManagerConnectionProviderImpl implements ConnectionProvider,
}
}
pool.clear();
+ stopped = true;
}
public Connection getConnection() throws SQLException {
@@ -157,7 +161,7 @@ public class DriverManagerConnectionProviderImpl implements ConnectionProvider,
log.trace( "using pooled JDBC connection, pool size: " + last );
checkedOut++;
}
- Connection pooled = (Connection) pool.remove(last);
+ Connection pooled = pool.remove(last);
if ( isolation != null ) {
pooled.setTransactionIsolation( isolation.intValue() );
}
@@ -205,8 +209,11 @@ public class DriverManagerConnectionProviderImpl implements ConnectionProvider,
conn.close();
}
- protected void finalize() {
- stop();
+ protected void finalize() throws Throwable {
+ if ( !stopped ) {
+ stop();
+ }
+ super.finalize();
}
public boolean supportsAggressiveRelease() {
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/AbstractJtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/AbstractJtaPlatform.java
new file mode 100644
index 0000000000..8a6f696b17
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/AbstractJtaPlatform.java
@@ -0,0 +1,133 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import org.hibernate.internal.util.config.ConfigurationHelper;
+import org.hibernate.service.jndi.spi.JndiService;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.service.spi.Configurable;
+import org.hibernate.service.spi.ServiceRegistry;
+import org.hibernate.service.spi.ServiceRegistryAwareService;
+
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+import java.util.Map;
+
+/**
+ * @author Steve Ebersole
+ */
+public abstract class AbstractJtaPlatform
+ implements JtaPlatform, Configurable, ServiceRegistryAwareService, TransactionManagerAccess {
+ private boolean cacheTransactionManager;
+ private boolean cacheUserTransaction;
+ private ServiceRegistry serviceRegistry;
+
+ @Override
+ public void injectServices(ServiceRegistry serviceRegistry) {
+ this.serviceRegistry = serviceRegistry;
+ }
+
+ protected ServiceRegistry serviceRegistry() {
+ return serviceRegistry;
+ }
+
+ protected JndiService jndiService() {
+ return serviceRegistry().getService( JndiService.class );
+ }
+
+ protected abstract TransactionManager locateTransactionManager();
+ protected abstract UserTransaction locateUserTransaction();
+
+ public void configure(Map configValues) {
+ cacheTransactionManager = ConfigurationHelper.getBoolean( CACHE_TM, configValues, true );
+ cacheUserTransaction = ConfigurationHelper.getBoolean( CACHE_UT, configValues, false );
+ }
+
+ protected boolean canCacheTransactionManager() {
+ return cacheTransactionManager;
+ }
+
+ protected boolean canCacheUserTransaction() {
+ return cacheUserTransaction;
+ }
+
+ private TransactionManager transactionManager;
+
+ @Override
+ public TransactionManager retrieveTransactionManager() {
+ if ( canCacheTransactionManager() ) {
+ if ( transactionManager == null ) {
+ transactionManager = locateTransactionManager();
+ }
+ return transactionManager;
+ }
+ else {
+ return locateTransactionManager();
+ }
+ }
+
+ @Override
+ public TransactionManager getTransactionManager() {
+ return retrieveTransactionManager();
+ }
+
+ private UserTransaction userTransaction;
+
+ @Override
+ public UserTransaction retrieveUserTransaction() {
+ if ( canCacheUserTransaction() ) {
+ if ( userTransaction == null ) {
+ userTransaction = locateUserTransaction();
+ }
+ return userTransaction;
+ }
+ return locateUserTransaction();
+ }
+
+ @Override
+ public Object getTransactionIdentifier(Transaction transaction) {
+ // generally we use the transaction itself.
+ return transaction;
+ }
+
+ protected abstract JtaSynchronizationStrategy getSynchronizationStrategy();
+
+ @Override
+ public void registerSynchronization(Synchronization synchronization) {
+ getSynchronizationStrategy().registerSynchronization( synchronization );
+ }
+
+ @Override
+ public boolean canRegisterSynchronization() {
+ return getSynchronizationStrategy().canRegisterSynchronization();
+ }
+
+ @Override
+ public int getCurrentStatus() throws SystemException {
+ return retrieveTransactionManager().getStatus();
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/BTMTransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/BitronixJtaPlatform.java
similarity index 51%
rename from hibernate-core/src/main/java/org/hibernate/transaction/BTMTransactionManagerLookup.java
rename to hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/BitronixJtaPlatform.java
index e59ed39a9e..f8c2978fa9 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/BTMTransactionManagerLookup.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/BitronixJtaPlatform.java
@@ -1,71 +1,62 @@
-/*
- * 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.transaction;
-
-import java.lang.reflect.Method;
-import java.util.Properties;
-
-import javax.transaction.TransactionManager;
-import javax.transaction.Transaction;
-
-import org.hibernate.HibernateException;
-
-/**
- * TransactionManager lookup strategy for BTM
- *
- * @author Ludovic Orban
- */
-@SuppressWarnings( {"UnusedDeclaration"})
-public class BTMTransactionManagerLookup implements TransactionManagerLookup {
-
- private static final String TM_CLASS_NAME = "bitronix.tm.TransactionManagerServices";
-
- /**
- * {@inheritDoc}
- */
- public TransactionManager getTransactionManager(Properties props) throws HibernateException {
- try {
- final Class clazz = Class.forName( TM_CLASS_NAME );
- final Method method = clazz.getMethod( "getTransactionManager", (Class[]) null );
- return (TransactionManager) method.invoke( null, (Object[]) null );
- }
- catch (Exception e) {
- throw new HibernateException( "Could not obtain BTM transaction manager instance", e );
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public String getUserTransactionName() {
- return "java:comp/UserTransaction";
- }
-
- /**
- * {@inheritDoc}
- */
- public Object getTransactionIdentifier(Transaction transaction) {
- return transaction;
- }
-}
\ No newline at end of file
+/*
+ * 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.service.jta.platform.internal;
+
+import org.hibernate.service.classloading.spi.ClassLoaderService;
+import org.hibernate.service.jta.platform.spi.JtaPlatformException;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+import java.lang.reflect.Method;
+
+/**
+ * @author Steve Ebersole
+ */
+public class BitronixJtaPlatform extends AbstractJtaPlatform {
+ private static final String TM_CLASS_NAME = "bitronix.tm.TransactionManagerServices";
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ try {
+ Class transactionManagerServicesClass = serviceRegistry().getService( ClassLoaderService.class ).classForName( TM_CLASS_NAME );
+ final Method getTransactionManagerMethod = transactionManagerServicesClass.getMethod( "getTransactionManager" );
+ return (TransactionManager) getTransactionManagerMethod.invoke( null );
+ }
+ catch (Exception e) {
+ throw new JtaPlatformException( "Could not locate Bitronix TransactionManager", e );
+ }
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) jndiService().locate( "java:comp/UserTransaction" );
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/BorlandEnterpriseServerJtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/BorlandEnterpriseServerJtaPlatform.java
new file mode 100644
index 0000000000..4a6c0770e7
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/BorlandEnterpriseServerJtaPlatform.java
@@ -0,0 +1,52 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * @author Steve Ebersole
+ */
+public class BorlandEnterpriseServerJtaPlatform extends AbstractJtaPlatform {
+ protected static final String TM_NAME = "java:pm/TransactionManager";
+ protected static final String UT_NAME = "java:comp/UserTransaction";
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ return (TransactionManager) jndiService().locate( TM_NAME );
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) jndiService().locate( UT_NAME );
+ }
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossAppServerPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossAppServerPlatform.java
index 6250106a95..c3202f8d23 100644
--- a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossAppServerPlatform.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossAppServerPlatform.java
@@ -23,72 +23,38 @@
*/
package org.hibernate.service.jta.platform.internal;
-import java.util.Map;
-import javax.transaction.Synchronization;
import javax.transaction.TransactionManager;
import javax.transaction.TransactionSynchronizationRegistry;
import javax.transaction.UserTransaction;
-import org.hibernate.internal.util.jta.JtaStatusHelper;
-import org.hibernate.service.jta.platform.spi.JtaPlatform;
-import org.hibernate.service.spi.Configurable;
-import org.hibernate.service.spi.InjectService;
-import org.hibernate.internal.util.config.ConfigurationHelper;
-import org.hibernate.service.jndi.spi.JndiService;
-
-
/**
- * TODO : javadoc
+ * JtaPlatform definition for JBoss Application Server.
*
* @author Steve Ebersole
*/
-public class JBossAppServerPlatform implements JtaPlatform, Configurable {
+public class JBossAppServerPlatform extends AbstractJtaPlatform implements SynchronizationRegistryAccess {
public static final String TM_NAME = "java:/TransactionManager";
public static final String UT_NAME = "UserTransaction";
public static final String REG_NAME = "java:comp/TransactionSynchronizationRegistry";
- private JndiService jndiService;
-
- @InjectService
- public void setJndiService(JndiService jndiService) {
- this.jndiService = jndiService;
+ private final JtaSynchronizationStrategy synchronizationStrategy = new SynchronizationRegistryBasedSynchronizationStrategy( this );
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ return (TransactionManager) jndiService().locate( TM_NAME );
}
- private boolean cacheTransactionManager;
-
- public void configure(Map configValues) {
- cacheTransactionManager = ConfigurationHelper.getBoolean( CACHE_TM, configValues, true );
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) jndiService().locate( UT_NAME );
}
- private TransactionManager transactionManager;
-
- public TransactionManager resolveTransactionManager() {
- if ( cacheTransactionManager ) {
- if ( transactionManager == null ) {
- transactionManager = (TransactionManager) jndiService.locate( TM_NAME );
- }
- return transactionManager;
- }
- else {
- return (TransactionManager) jndiService.locate( TM_NAME );
- }
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
}
- public UserTransaction resolveUserTransaction() {
- return (UserTransaction) jndiService.locate( UT_NAME );
- }
-
- public void registerSynchronization(Synchronization synchronization) {
- getTransactionSynchronizationRegistry().registerInterposedSynchronization( synchronization );
- }
-
- private TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() {
- return (TransactionSynchronizationRegistry) jndiService.locate( REG_NAME );
- }
-
- public boolean canRegisterSynchronization() {
- TransactionSynchronizationRegistry registry = getTransactionSynchronizationRegistry();
- int status = registry.getTransactionStatus();
- return JtaStatusHelper.isActive( status ) && ! registry.getRollbackOnly();
+ @Override
+ public TransactionSynchronizationRegistry getSynchronizationRegistry() {
+ return (TransactionSynchronizationRegistry) jndiService().locate( REG_NAME );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossStandAloneJtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossStandAloneJtaPlatform.java
new file mode 100644
index 0000000000..01f48e49fe
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossStandAloneJtaPlatform.java
@@ -0,0 +1,70 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import org.hibernate.service.classloading.spi.ClassLoaderService;
+import org.hibernate.service.jta.platform.spi.JtaPlatformException;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+import java.lang.reflect.Method;
+
+/**
+ * Return a standalone JTA transaction manager for JBoss Transactions
+ * Known to work for org.jboss.jbossts:jbossjta:4.11.0.Final
+ *
+ * @author Emmanuel Bernard
+ * @author Steve Ebersole
+ */
+public class JBossStandAloneJtaPlatform extends AbstractJtaPlatform {
+ private static final String PROPERTY_MANAGER_CLASS_NAME = "com.arjuna.ats.jta.common.jtaPropertyManager";
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ try {
+ final Class propertyManagerClass = serviceRegistry()
+ .getService( ClassLoaderService.class )
+ .classForName( PROPERTY_MANAGER_CLASS_NAME );
+ final Method getJTAEnvironmentBeanMethod = propertyManagerClass.getMethod( "getJTAEnvironmentBean" );
+ final Object jtaEnvironmentBean = getJTAEnvironmentBeanMethod.invoke( null );
+ final Method getTransactionManagerMethod = jtaEnvironmentBean.getClass().getMethod( "getTransactionManager" );
+ return ( TransactionManager ) getTransactionManagerMethod.invoke( jtaEnvironmentBean );
+ }
+ catch ( Exception e ) {
+ throw new JtaPlatformException( "Could not obtain JBoss Transactions transaction manager instance", e );
+ }
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return null;
+ }
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JOTMJtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JOTMJtaPlatform.java
new file mode 100644
index 0000000000..6360d3fb82
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JOTMJtaPlatform.java
@@ -0,0 +1,63 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import org.hibernate.service.classloading.spi.ClassLoaderService;
+import org.hibernate.service.jta.platform.spi.JtaPlatformException;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+import java.lang.reflect.Method;
+
+/**
+ * @author Steve Ebersole
+ */
+public class JOTMJtaPlatform extends AbstractJtaPlatform {
+ public static final String TM_CLASS_NAME = "org.objectweb.jotm.Current";
+ public static final String UT_NAME = "java:comp/UserTransaction";
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ try {
+ final Class tmClass = serviceRegistry().getService( ClassLoaderService.class ).classForName( TM_CLASS_NAME );
+ final Method getTransactionManagerMethod = tmClass.getMethod( "getTransactionManager" );
+ return (TransactionManager) getTransactionManagerMethod.invoke( null, (Object[]) null );
+ }
+ catch (Exception e) {
+ throw new JtaPlatformException( "Could not obtain JOTM transaction manager instance", e );
+ }
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) jndiService().locate( UT_NAME );
+ }
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/JOnASTransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JOnASJtaPlatform.java
similarity index 55%
rename from hibernate-core/src/main/java/org/hibernate/transaction/JOnASTransactionManagerLookup.java
rename to hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JOnASJtaPlatform.java
index 063033bf1d..617cdf4b90 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/JOnASTransactionManagerLookup.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JOnASJtaPlatform.java
@@ -21,50 +21,44 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.transaction;
+package org.hibernate.service.jta.platform.internal;
-import java.lang.reflect.Method;
-import java.util.Properties;
+import org.hibernate.service.jta.platform.spi.JtaPlatformException;
import javax.transaction.TransactionManager;
-import javax.transaction.Transaction;
-
-import org.hibernate.HibernateException;
+import javax.transaction.UserTransaction;
+import java.lang.reflect.Method;
/**
- * {@link TransactionManagerLookup} strategy for JOnAS
+ * JTA platform implementation for JOnAS
+ *
+ * @author Steve Ebersole
*/
-@SuppressWarnings( {"UnusedDeclaration"})
-public class JOnASTransactionManagerLookup implements TransactionManagerLookup {
-
+public class JOnASJtaPlatform extends AbstractJtaPlatform {
+ public static final String UT_NAME = "java:comp/UserTransaction";
private static final String TM_CLASS_NAME = "org.objectweb.jonas_tm.Current";
- /**
- * {@inheritDoc}
- */
- public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
try {
final Class clazz = Class.forName( TM_CLASS_NAME );
- final Method method = clazz.getMethod( "getTransactionManager", (Class[]) null );
- return (TransactionManager) method.invoke( null, (Object[]) null );
+ final Method getTransactionManagerMethod = clazz.getMethod( "getTransactionManager" );
+ return (TransactionManager) getTransactionManagerMethod.invoke( null );
}
catch (Exception e) {
- throw new HibernateException( "Could not obtain JOnAS transaction manager instance", e );
+ throw new JtaPlatformException( "Could not obtain JOnAS transaction manager instance", e );
}
}
- /**
- * {@inheritDoc}
- */
- public String getUserTransactionName() {
- return "java:comp/UserTransaction";
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) jndiService().locate( UT_NAME );
}
- /**
- * {@inheritDoc}
- */
- public Object getTransactionIdentifier(Transaction transaction) {
- return transaction;
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
}
}
-
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JRun4JtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JRun4JtaPlatform.java
new file mode 100644
index 0000000000..fde0d6eecd
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JRun4JtaPlatform.java
@@ -0,0 +1,55 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * {@link org.hibernate.service.jta.platform.spi.JtaPlatform} implementation for JRun4 AS
+ *
+ * @author Joseph Bissen
+ * @author Steve Ebersole
+ */
+public class JRun4JtaPlatform extends AbstractJtaPlatform {
+ public static final String TM_NAME = "java:/TransactionManager";
+ public static final String UT_NAME = "java:comp/UserTransaction";
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ return (TransactionManager) jndiService().locate( TM_NAME );
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) jndiService().locate( UT_NAME );
+ }
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaPlatformInitiator.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaPlatformInitiator.java
index 5e548dbee6..9254eb76a7 100644
--- a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaPlatformInitiator.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaPlatformInitiator.java
@@ -26,10 +26,16 @@ package org.hibernate.service.jta.platform.internal;
import java.util.Map;
import org.hibernate.HibernateException;
+import org.hibernate.cfg.Environment;
+import org.hibernate.internal.util.jndi.JndiHelper;
import org.hibernate.service.classloading.spi.ClassLoaderService;
import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.service.jta.platform.spi.JtaPlatformException;
import org.hibernate.service.spi.ServiceInitiator;
import org.hibernate.service.spi.ServiceRegistry;
+import org.hibernate.transaction.TransactionManagerLookup;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Standard initiator for the standard {@link org.hibernate.service.jta.platform.spi.JtaPlatform}
@@ -38,27 +44,24 @@ import org.hibernate.service.spi.ServiceRegistry;
*/
public class JtaPlatformInitiator implements ServiceInitiator {
public static final JtaPlatformInitiator INSTANCE = new JtaPlatformInitiator();
-
public static final String JTA_PLATFORM = "hibernate.jta.platform";
- /**
- * {@inheritDoc}
- */
+ private static final Logger log = LoggerFactory.getLogger( JtaPlatformInitiator.class );
+
+ @Override
public Class getServiceInitiated() {
return JtaPlatform.class;
}
- /**
- * {@inheritDoc}
- */
+ @Override
public JtaPlatform initiateService(Map configVales, ServiceRegistry registry) {
- final Object platform = configVales.get( JTA_PLATFORM );
- if ( JtaPlatform.class.isInstance( platform ) ) {
- return (JtaPlatform) platform;
+ final Object platform = getConfiguredPlatform( configVales, registry );
+ if ( platform == null ) {
+ return new NoJtaPlatform();
}
- if ( platform == null ) {
- return null;
+ if ( JtaPlatform.class.isInstance( platform ) ) {
+ return (JtaPlatform) platform;
}
final String platformImplName = platform.toString();
@@ -71,4 +74,107 @@ public class JtaPlatformInitiator implements ServiceInitiator {
throw new HibernateException( "Unable to create specified JtaPlatform class [" + platformImplName + "]", e );
}
}
+
+ private Object getConfiguredPlatform(Map configVales, ServiceRegistry registry) {
+ Object platform = configVales.get( JTA_PLATFORM );
+ if ( platform == null ) {
+ final String transactionManagerLookupImplName = (String) configVales.get( Environment.TRANSACTION_MANAGER_STRATEGY );
+ if ( transactionManagerLookupImplName != null ) {
+ log.warn(
+ "Using deprecated " + TransactionManagerLookup.class.getName() + " strategy [" +
+ Environment.TRANSACTION_MANAGER_STRATEGY +
+ "], use newer " + JtaPlatform.class.getName() +
+ " strategy instead [" + JTA_PLATFORM + "]"
+ );
+ platform = mapLegacyClasses( transactionManagerLookupImplName, configVales, registry );
+ log.debug( "Mapped {} -> {}", transactionManagerLookupImplName, platform );
+ }
+ }
+ return platform;
+ }
+
+ private JtaPlatform mapLegacyClasses(
+ String transactionManagerLookupImplName,
+ Map configVales,
+ ServiceRegistry registry) {
+ if ( transactionManagerLookupImplName == null ) {
+ return null;
+ }
+
+ log.info(
+ "Encountered legacy TransactionManagerLookup specified; convert to newer " +
+ JtaPlatform.class.getName() + " contract specified via " +
+ JTA_PLATFORM + "setting"
+ );
+
+ if ( "org.hibernate.transaction.BESTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new BorlandEnterpriseServerJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.BTMTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new BitronixJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.JBossTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new JBossAppServerPlatform();
+ }
+
+ if ( "org.hibernate.transaction.JBossTSStandaloneTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new JBossStandAloneJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.JOnASTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new JOnASJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.JOTMTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new JOTMJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.JRun4TransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new JRun4JtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.OC4JTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new OC4JJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.OrionTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new OrionJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.ResinTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new ResinJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.SunONETransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new SunOneJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.WeblogicTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new WeblogicJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.WebSphereTransactionManagerLookup".equals( transactionManagerLookupImplName ) ) {
+ return new WebSphereJtaPlatform();
+ }
+
+ if ( "org.hibernate.transaction.WebSphereExtendedJTATransactionLookup".equals( transactionManagerLookupImplName ) ) {
+ return new WebSphereExtendedJtaPlatform();
+ }
+
+ try {
+ TransactionManagerLookup lookup = (TransactionManagerLookup) registry.getService( ClassLoaderService.class )
+ .classForName( transactionManagerLookupImplName )
+ .newInstance();
+ return new TransactionManagerLookupBridge( lookup, JndiHelper.extractJndiProperties( configVales ) );
+ }
+ catch ( Exception e ) {
+ throw new JtaPlatformException(
+ "Unable to build " + TransactionManagerLookupBridge.class.getName() + " from specified " +
+ TransactionManagerLookup.class.getName() + " implementation: " +
+ transactionManagerLookupImplName
+ );
+ }
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaSynchronizationStrategy.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaSynchronizationStrategy.java
new file mode 100644
index 0000000000..64d89e8bb8
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaSynchronizationStrategy.java
@@ -0,0 +1,48 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import javax.transaction.Synchronization;
+import java.io.Serializable;
+
+/**
+ * Contract used to centralize {@link Synchronization} handling logic.
+ *
+ * @author Steve Ebersole
+ */
+public interface JtaSynchronizationStrategy extends Serializable {
+ /**
+ * Register a synchronization
+ *
+ * @param synchronization The synchronization to register.
+ */
+ public void registerSynchronization(Synchronization synchronization);
+
+ /**
+ * Can a synchronization be registered?
+ *
+ * @return {@literal true}/{@literal false}
+ */
+ public boolean canRegisterSynchronization();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/JOTMTransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/NoJtaPlatform.java
similarity index 53%
rename from hibernate-core/src/main/java/org/hibernate/transaction/JOTMTransactionManagerLookup.java
rename to hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/NoJtaPlatform.java
index 23a6ec967f..6d60fe198b 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/JOTMTransactionManagerLookup.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/NoJtaPlatform.java
@@ -21,57 +21,49 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.transaction;
+package org.hibernate.service.jta.platform.internal;
-import java.lang.reflect.Method;
-import java.util.Properties;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
-import javax.transaction.TransactionManager;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
import javax.transaction.Transaction;
-
-import org.hibernate.HibernateException;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
/**
- * {@link TransactionManagerLookup} strategy for JOTM
+ * The non-configured form of JTA platform. This is what is used if none was set up.
*
- * @author Low Heng Sin
+ * @author Steve Ebersole
*/
-@SuppressWarnings( {"UnusedDeclaration"})
-public class JOTMTransactionManagerLookup implements TransactionManagerLookup {
-
- private static final String TM_CLASS_NAME = "org.objectweb.jotm.Current";
-
- /**
- * {@inheritDoc}
- */
- public TransactionManager getTransactionManager(Properties props) throws HibernateException {
- try {
- final Class clazz = Class.forName( TM_CLASS_NAME );
- final Method method = clazz.getMethod( "getTransactionManager", (Class[]) null );
- return (TransactionManager) method.invoke( null, (Object[]) null );
- }
- catch (Exception e) {
- throw new HibernateException( "Could not obtain JOTM transaction manager instance", e );
- }
+public class NoJtaPlatform implements JtaPlatform {
+ @Override
+ public TransactionManager retrieveTransactionManager() {
+ return null;
}
- /**
- * {@inheritDoc}
- */
- public String getUserTransactionName() {
- return "java:comp/UserTransaction";
+ @Override
+ public UserTransaction retrieveUserTransaction() {
+ return null;
}
- /**
- * {@inheritDoc}
- */
+ @Override
public Object getTransactionIdentifier(Transaction transaction) {
- return transaction;
+ return null;
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization synchronization) {
+ }
+
+ @Override
+ public boolean canRegisterSynchronization() {
+ return false;
+ }
+
+ @Override
+ public int getCurrentStatus() throws SystemException {
+ return Status.STATUS_UNKNOWN;
}
}
-
-
-
-
-
-
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/OC4JJtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/OC4JJtaPlatform.java
new file mode 100644
index 0000000000..4112ebdf4d
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/OC4JJtaPlatform.java
@@ -0,0 +1,55 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * {@link org.hibernate.service.jta.platform.spi.JtaPlatform} implementation for the OC4J (Oracle) AS.
+ *
+ * @author Stijn Janssens
+ * @author Steve Ebersole
+ */
+public class OC4JJtaPlatform extends AbstractJtaPlatform {
+ public static final String TM_NAME = "java:comp/pm/TransactionManager";
+ public static final String UT_NAME = "java:comp/UserTransaction";
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ return (TransactionManager) jndiService().locate( TM_NAME );
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) jndiService().locate( UT_NAME );
+ }
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/OrionJtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/OrionJtaPlatform.java
new file mode 100644
index 0000000000..44b862c6c4
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/OrionJtaPlatform.java
@@ -0,0 +1,55 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * {@link org.hibernate.service.jta.platform.spi.JtaPlatform} implementation for Orion
+ *
+ * @author Gavin King
+ * @author Steve Ebersole
+ */
+public class OrionJtaPlatform extends AbstractJtaPlatform {
+ public static final String TM_NAME = "java:comp/UserTransaction";
+ public static final String UT_NAME = "java:comp/UserTransaction";
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ return (TransactionManager) jndiService().locate( TM_NAME );
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) jndiService().locate( UT_NAME );
+ }
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/ResinJtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/ResinJtaPlatform.java
new file mode 100644
index 0000000000..6b44cc305e
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/ResinJtaPlatform.java
@@ -0,0 +1,55 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * {@link org.hibernate.service.jta.platform.spi.JtaPlatform} implementation for Resin
+ *
+ * @author Aapo Laakkonen
+ * @author Steve Ebersole
+ */
+public class ResinJtaPlatform extends AbstractJtaPlatform {
+ public static final String TM_NAME = "java:comp/TransactionManager";
+ public static final String UT_NAME = "java:comp/UserTransaction";
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ return (TransactionManager) jndiService().locate( TM_NAME );
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) jndiService().locate( UT_NAME );
+ }
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/SunOneJtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/SunOneJtaPlatform.java
new file mode 100644
index 0000000000..0213b9e52a
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/SunOneJtaPlatform.java
@@ -0,0 +1,57 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * {@link org.hibernate.service.jta.platform.spi.JtaPlatform} implementation for Sun ONE Application Server 7 and above
+ *
+ * @author Robert Davidson
+ * @author Sanjeev Krishnan
+ * @author Emmanuel Bernard
+ * @author Steve Ebersole
+ */
+public class SunOneJtaPlatform extends AbstractJtaPlatform {
+ public static final String TM_NAME = "java:appserver/TransactionManager";
+ public static final String UT_NAME = "java:comp/UserTransaction";
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ return (TransactionManager) jndiService().locate( TM_NAME );
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) jndiService().locate( UT_NAME );
+ }
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/SynchronizationRegistryAccess.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/SynchronizationRegistryAccess.java
new file mode 100644
index 0000000000..2f7698f0fd
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/SynchronizationRegistryAccess.java
@@ -0,0 +1,42 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import javax.transaction.TransactionSynchronizationRegistry;
+import java.io.Serializable;
+
+/**
+ * Provides access to a {@link TransactionSynchronizationRegistry} for use by {@link TransactionSynchronizationRegistry}-based
+ * {@link JtaSynchronizationStrategy} implementations.
+ *
+ * @author Steve Ebersole
+ */
+public interface SynchronizationRegistryAccess extends Serializable {
+ /**
+ * Obtain the synchronization registry
+ *
+ * @return the synchronization registry
+ */
+ public TransactionSynchronizationRegistry getSynchronizationRegistry();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/SynchronizationRegistryBasedSynchronizationStrategy.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/SynchronizationRegistryBasedSynchronizationStrategy.java
new file mode 100644
index 0000000000..c735ec7cf5
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/SynchronizationRegistryBasedSynchronizationStrategy.java
@@ -0,0 +1,56 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
+
+import javax.transaction.Synchronization;
+import javax.transaction.TransactionSynchronizationRegistry;
+
+/**
+ * Implementation of the {@link JtaSynchronizationStrategy} contract based on using a
+ * {@link TransactionSynchronizationRegistry}
+ *
+ * @author Steve Ebersole
+ */
+public class SynchronizationRegistryBasedSynchronizationStrategy implements JtaSynchronizationStrategy {
+ private final SynchronizationRegistryAccess synchronizationRegistryAccess;
+
+ public SynchronizationRegistryBasedSynchronizationStrategy(SynchronizationRegistryAccess synchronizationRegistryAccess) {
+ this.synchronizationRegistryAccess = synchronizationRegistryAccess;
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization synchronization) {
+ synchronizationRegistryAccess.getSynchronizationRegistry().registerInterposedSynchronization(
+ synchronization
+ );
+ }
+
+ @Override
+ public boolean canRegisterSynchronization() {
+ final TransactionSynchronizationRegistry registry = synchronizationRegistryAccess.getSynchronizationRegistry();
+ return JtaStatusHelper.isActive( registry.getTransactionStatus() ) && ! registry.getRollbackOnly();
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/IsolatedWork.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/TransactionManagerAccess.java
similarity index 61%
rename from hibernate-core/src/main/java/org/hibernate/engine/transaction/IsolatedWork.java
rename to hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/TransactionManagerAccess.java
index 94269d99f4..788c8cc7c3 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/transaction/IsolatedWork.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/TransactionManagerAccess.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * 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 Middleware LLC.
+ * 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
@@ -20,27 +20,23 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
-package org.hibernate.engine.transaction;
+package org.hibernate.service.jta.platform.internal;
-import org.hibernate.HibernateException;
-
-import java.sql.Connection;
+import javax.transaction.TransactionManager;
+import java.io.Serializable;
/**
- * Represents work that needs to be performed in a manner
- * which isolates it from any current application unit of
- * work transaction.
+ * Provides access to a {@link TransactionManager} for use by {@link TransactionManager}-based
+ * {@link JtaSynchronizationStrategy} implementations.
*
* @author Steve Ebersole
*/
-public interface IsolatedWork {
+public interface TransactionManagerAccess extends Serializable {
/**
- * Perform the actual work to be done.
+ * Obtain the transaction manager
*
- * @param connection The JDBC connection to use.
- * @throws HibernateException
+ * @return The transaction manager.
*/
- public void doWork(Connection connection) throws HibernateException;
+ public TransactionManager getTransactionManager();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/TransactionManagerBasedSynchronizationStrategy.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/TransactionManagerBasedSynchronizationStrategy.java
new file mode 100644
index 0000000000..45f25531d8
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/TransactionManagerBasedSynchronizationStrategy.java
@@ -0,0 +1,58 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
+import org.hibernate.service.jta.platform.spi.JtaPlatformException;
+
+import javax.transaction.Synchronization;
+
+/**
+ * Implementation of the {@link JtaSynchronizationStrategy} contract based on using a
+ * {@link javax.transaction.TransactionManager}
+ *
+ * @author Steve Ebersole
+ */
+public class TransactionManagerBasedSynchronizationStrategy implements JtaSynchronizationStrategy {
+ private final TransactionManagerAccess transactionManagerAccess;
+
+ public TransactionManagerBasedSynchronizationStrategy(TransactionManagerAccess transactionManagerAccess) {
+ this.transactionManagerAccess = transactionManagerAccess;
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization synchronization) {
+ try {
+ transactionManagerAccess.getTransactionManager().getTransaction().registerSynchronization( synchronization );
+ }
+ catch (Exception e) {
+ throw new JtaPlatformException( "Could not access JTA Transaction to register synchronization", e );
+ }
+ }
+
+ @Override
+ public boolean canRegisterSynchronization() {
+ return JtaStatusHelper.isActive( transactionManagerAccess.getTransactionManager() );
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/TransactionManagerLookupBridge.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/TransactionManagerLookupBridge.java
new file mode 100644
index 0000000000..5d90ea8368
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/TransactionManagerLookupBridge.java
@@ -0,0 +1,67 @@
+/*
+ * 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.service.jta.platform.internal;
+
+import org.hibernate.service.jndi.spi.JndiService;
+import org.hibernate.transaction.TransactionManagerLookup;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+import java.util.Properties;
+
+/**
+ * @author Steve Ebersole
+ */
+public class TransactionManagerLookupBridge extends AbstractJtaPlatform {
+ private final TransactionManagerLookup lookup;
+ private final Properties jndiProperties;
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ public TransactionManagerLookupBridge(TransactionManagerLookup lookup, Properties jndiProperties) {
+ this.lookup = lookup;
+ this.jndiProperties = jndiProperties;
+ }
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ return lookup.getTransactionManager( jndiProperties );
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return (UserTransaction) serviceRegistry().getService( JndiService.class ).locate( lookup.getUserTransactionName() );
+ }
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+
+ @Override
+ public Object getTransactionIdentifier(Transaction transaction) {
+ return lookup.getTransactionIdentifier( transaction );
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/WebSphereExtendedJTATransactionLookup.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/WebSphereExtendedJtaPlatform.java
old mode 100755
new mode 100644
similarity index 73%
rename from hibernate-core/src/main/java/org/hibernate/transaction/WebSphereExtendedJTATransactionLookup.java
rename to hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/WebSphereExtendedJtaPlatform.java
index 300ae58a06..3449efbd0b
--- a/hibernate-core/src/main/java/org/hibernate/transaction/WebSphereExtendedJTATransactionLookup.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/WebSphereExtendedJtaPlatform.java
@@ -21,14 +21,10 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-package org.hibernate.transaction;
+package org.hibernate.service.jta.platform.internal;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.Properties;
+import org.hibernate.HibernateException;
-import javax.naming.NamingException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
@@ -36,64 +32,68 @@ import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
import javax.transaction.xa.XAResource;
-
-import org.hibernate.HibernateException;
-import org.hibernate.internal.util.jndi.JndiHelper;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
/**
- * TransactionManagerLookup implementation intended for use with WebSphere
- * Application Server (WAS).
+ * JTA platform implementation intended for use with WebSphere Application Server (WAS).
*
- * WAS, unlike every other app server on the planet, does not allow direct
- * access to the JTS TransactionManager. Instead, for common transaction-
- * related tasks users must utilize a proprietary API known as
- * ExtendedJTATransaction.
+ * WAS, unlike every other app server on the planet, does not allow direct access to the JTS TransactionManager.
+ * Instead, for common transaction-related tasks users must utilize a proprietary API known as ExtendedJTATransaction.
*
- * Even more unfortunate, the exact TransactionManagerLookup to use inside of
- * WAS is highly dependent upon (1) WAS version as well as (2) the WAS
- * container in which Hibernate will be utilized.
+ * Even more unfortunate, the exact TransactionManagerLookup to use inside of WAS is highly dependent upon
+ * - WAS version
+ * - the WAS container in which Hibernate will be utilized
+ *
*
- * WebSphereExtendedJTATransactionLookup is reported to work on WAS version 6
- * in any of the standard J2EE/JEE component containers.
+ * This class is reported to work on WAS version 6 in any of the standard J2EE/JEE component containers.
*
* @author Gavin King
* @author
+ * Generally speaking the transaction itself will be returned here. This method was added specifically
+ * for use in WebSphere and other unfriendly JEE containers (although WebSphere is still the only known
+ * such brain-dead, sales-driven impl).
+ *
+ * @param transaction The transaction to be identified.
+ * @return An appropriate identifier
+ */
+ public Object getTransactionIdentifier(Transaction transaction);
+
+ /**
+ * Can we currently register a {@link Synchronization}?
+ *
+ * @return True if registering a {@link Synchronization} is currently allowed; false otherwise.
+ */
+ public boolean canRegisterSynchronization();
/**
* Register a JTA {@link Synchronization} in the means defined by the platform.
@@ -66,9 +89,11 @@ public interface JtaPlatform extends Service {
public void registerSynchronization(Synchronization synchronization);
/**
- * Can we currently regsiter a {@link Synchronization}?
+ * Obtain the current transaction status using whatever means is preferred for this platform
*
- * @return True if regsitering a {@link Synchronization} is currently allowed; false otherwise.
+ * @return The current status.
+ *
+ * @throws SystemException Indicates a problem access the underlying status
*/
- public boolean canRegisterSynchronization();
+ public int getCurrentStatus() throws SystemException;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/OC4JTransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/spi/JtaPlatformException.java
similarity index 65%
rename from hibernate-core/src/main/java/org/hibernate/transaction/OC4JTransactionManagerLookup.java
rename to hibernate-core/src/main/java/org/hibernate/service/jta/platform/spi/JtaPlatformException.java
index f71e290c82..abc7f31d79 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/OC4JTransactionManagerLookup.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/spi/JtaPlatformException.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * 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 Middleware LLC.
+ * 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
@@ -20,21 +20,22 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
-package org.hibernate.transaction;
+package org.hibernate.service.jta.platform.spi;
+
+import org.hibernate.HibernateException;
/**
- * {@link TransactionManagerLookup} for the OC4J (Oracle) AS.
- *
- * @author Stijn Janssens
+ * Indicates a problem interacting with the underlying JTA platform.
+ *
+ * @author Steve Ebersole
*/
-public class OC4JTransactionManagerLookup extends JNDITransactionManagerLookup {
- protected String getName() {
- return "java:comp/pm/TransactionManager";
+public class JtaPlatformException extends HibernateException {
+ public JtaPlatformException(String s) {
+ super( s );
}
- public String getUserTransactionName() {
- return "java:comp/UserTransaction";
+ public JtaPlatformException(String string, Throwable root) {
+ super( string, root );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/spi/Service.java b/hibernate-core/src/main/java/org/hibernate/service/spi/Service.java
index 134f3e5836..796e1afd83 100644
--- a/hibernate-core/src/main/java/org/hibernate/service/spi/Service.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/spi/Service.java
@@ -23,10 +23,14 @@
*/
package org.hibernate.service.spi;
+import java.io.Serializable;
+
/**
* Marker interface for services.
+ *
+ * NOTE : All services must be {@link Serializable}!
*
* @author Steve Ebersole
*/
-public interface Service {
+public interface Service extends Serializable {
}
diff --git a/hibernate-core/src/main/java/org/hibernate/service/spi/StandardServiceInitiators.java b/hibernate-core/src/main/java/org/hibernate/service/spi/StandardServiceInitiators.java
index 06ea81e9e7..a6b8a545e7 100644
--- a/hibernate-core/src/main/java/org/hibernate/service/spi/StandardServiceInitiators.java
+++ b/hibernate-core/src/main/java/org/hibernate/service/spi/StandardServiceInitiators.java
@@ -23,7 +23,9 @@
*/
package org.hibernate.service.spi;
+import org.hibernate.engine.jdbc.batch.internal.BatchBuilderInitiator;
import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator;
+import org.hibernate.engine.transaction.internal.TransactionFactoryInitiator;
import org.hibernate.service.classloading.internal.ClassLoaderServiceInitiator;
import org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator;
import org.hibernate.service.jdbc.dialect.internal.DialectFactoryInitiator;
@@ -51,10 +53,11 @@ public class StandardServiceInitiators {
serviceInitiators.add( ConnectionProviderInitiator.INSTANCE );
serviceInitiators.add( DialectResolverInitiator.INSTANCE );
serviceInitiators.add( DialectFactoryInitiator.INSTANCE );
+ serviceInitiators.add( BatchBuilderInitiator.INSTANCE );
serviceInitiators.add( JdbcServicesInitiator.INSTANCE );
serviceInitiators.add( JtaPlatformInitiator.INSTANCE );
- //serviceInitiators.add( TransactionFactoryInitiator.INSTANCE );
+ serviceInitiators.add( TransactionFactoryInitiator.INSTANCE );
return serviceInitiators;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/BESTransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/transaction/BESTransactionManagerLookup.java
deleted file mode 100644
index 0d1e235f5d..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/BESTransactionManagerLookup.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-/**
- * A TransactionManager lookup strategy for Borland ES.
- *
- * @author Etienne Hardy
- */
-public final class BESTransactionManagerLookup extends JNDITransactionManagerLookup {
-
- protected String getName() {
- return "java:pm/TransactionManager";
- }
-
- public String getUserTransactionName() {
- return "java:comp/UserTransaction";
- }
-
-}
\ No newline at end of file
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/CMTTransaction.java b/hibernate-core/src/main/java/org/hibernate/transaction/CMTTransaction.java
deleted file mode 100755
index ab56daed6d..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/CMTTransaction.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
-import javax.transaction.SystemException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.hibernate.HibernateException;
-import org.hibernate.Transaction;
-import org.hibernate.TransactionException;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-import org.hibernate.util.JTAHelper;
-
-/**
- * Implements a basic transaction strategy for CMT transactions. All work is
- * done in the context of the container managed transaction.
- *
- * The term 'CMT' is potentially misleading here; the pertinent point simply
- * being that the transactions are being managed by something other than the
- * Hibernate transaction mechanism.
- *
- * @author Gavin King
- */
-public class CMTTransaction implements Transaction {
-
- private static final Logger log = LoggerFactory.getLogger(CMTTransaction.class);
-
- protected final JDBCContext jdbcContext;
- protected final TransactionFactory.Context transactionContext;
-
- private boolean begun;
-
- public CMTTransaction(JDBCContext jdbcContext, TransactionFactory.Context transactionContext) {
- this.jdbcContext = jdbcContext;
- this.transactionContext = transactionContext;
- }
-
- /**
- * {@inheritDoc}
- */
- public void begin() throws HibernateException {
- if (begun) {
- return;
- }
-
- log.debug("begin");
-
- boolean synchronization = jdbcContext.registerSynchronizationIfPossible();
-
- if ( !synchronization ) {
- throw new TransactionException("Could not register synchronization for container transaction");
- }
-
- begun = true;
-
- jdbcContext.afterTransactionBegin(this);
- }
-
- /**
- * {@inheritDoc}
- */
- public void commit() throws HibernateException {
- if (!begun) {
- throw new TransactionException("Transaction not successfully started");
- }
-
- log.debug("commit");
-
- boolean flush = !transactionContext.isFlushModeNever() &&
- !transactionContext.isFlushBeforeCompletionEnabled();
-
- if (flush) {
- transactionContext.managedFlush(); //if an exception occurs during flush, user must call rollback()
- }
-
- begun = false;
-
- }
-
- /**
- * {@inheritDoc}
- */
- public void rollback() throws HibernateException {
- if (!begun) {
- throw new TransactionException("Transaction not successfully started");
- }
-
- log.debug("rollback");
-
- try {
- getTransaction().setRollbackOnly();
- }
- catch (SystemException se) {
- log.error("Could not set transaction to rollback only", se);
- throw new TransactionException("Could not set transaction to rollback only", se);
- }
-
- begun = false;
-
- }
-
- /**
- * Getter for property 'transaction'.
- *
- * @return Value for property 'transaction'.
- */
- public javax.transaction.Transaction getTransaction() throws SystemException {
- return transactionContext.getFactory().getTransactionManager().getTransaction();
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isActive() throws TransactionException {
-
- if (!begun) return false;
-
- final int status;
- try {
- status = getTransaction().getStatus();
- }
- catch (SystemException se) {
- log.error("Could not determine transaction status", se);
- throw new TransactionException("Could not determine transaction status: ", se);
- }
- if (status==Status.STATUS_UNKNOWN) {
- throw new TransactionException("Could not determine transaction status");
- }
- else {
- return status==Status.STATUS_ACTIVE;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean wasRolledBack() throws TransactionException {
-
- if (!begun) return false;
-
- final int status;
- try {
- status = getTransaction().getStatus();
- }
- catch (SystemException se) {
- log.error("Could not determine transaction status", se);
- throw new TransactionException("Could not determine transaction status", se);
- }
- if (status==Status.STATUS_UNKNOWN) {
- throw new TransactionException("Could not determine transaction status");
- }
- else {
- return JTAHelper.isRollback(status);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean wasCommitted() throws TransactionException {
-
- if ( !begun ) return false;
-
- final int status;
- try {
- status = getTransaction().getStatus();
- }
- catch (SystemException se) {
- log.error("Could not determine transaction status", se);
- throw new TransactionException("Could not determine transaction status: ", se);
- }
- if (status==Status.STATUS_UNKNOWN) {
- throw new TransactionException("Could not determine transaction status");
- }
- else {
- return status==Status.STATUS_COMMITTED;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void registerSynchronization(Synchronization sync) throws HibernateException {
- try {
- getTransaction().registerSynchronization(sync);
- }
- catch (Exception e) {
- throw new TransactionException("Could not register synchronization", e);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void setTimeout(int seconds) {
- throw new UnsupportedOperationException("cannot set transaction timeout in CMT");
- }
-
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/CacheSynchronization.java b/hibernate-core/src/main/java/org/hibernate/transaction/CacheSynchronization.java
deleted file mode 100644
index 885443f9f3..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/CacheSynchronization.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.TransactionException;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-import org.hibernate.util.JTAHelper;
-
-/**
- * A JTA transaction synch used to allow the {@link org.hibernate.Session} to know about transaction
- * events.
- *
- * @author Gavin King
- */
-public final class CacheSynchronization implements Synchronization {
-
- private static final Logger log = LoggerFactory.getLogger(CacheSynchronization.class);
-
- private final TransactionFactory.Context ctx;
- private JDBCContext jdbcContext;
- private final Transaction transaction;
- private final org.hibernate.Transaction hibernateTransaction;
-
- public CacheSynchronization(
- TransactionFactory.Context ctx,
- JDBCContext jdbcContext,
- Transaction transaction,
- org.hibernate.Transaction tx) {
- this.ctx = ctx;
- this.jdbcContext = jdbcContext;
- this.transaction = transaction;
- this.hibernateTransaction = tx;
- }
-
- /**
- * {@inheritDoc}
- */
- public void beforeCompletion() {
- log.trace("transaction before completion callback");
-
- boolean flush;
- try {
- flush = !ctx.isFlushModeNever() &&
- ctx.isFlushBeforeCompletionEnabled() &&
- !JTAHelper.isRollback( transaction.getStatus() );
- //actually, this last test is probably unnecessary, since
- //beforeCompletion() doesn't get called during rollback
- }
- catch (SystemException se) {
- log.error("could not determine transaction status", se);
- setRollbackOnly();
- throw new TransactionException("could not determine transaction status in beforeCompletion()", se);
- }
-
- try {
- if (flush) {
- log.trace("automatically flushing session");
- ctx.managedFlush();
- }
- }
- catch (RuntimeException re) {
- setRollbackOnly();
- throw re;
- }
- finally {
- jdbcContext.beforeTransactionCompletion(hibernateTransaction);
- }
- }
-
- private void setRollbackOnly() {
- try {
- transaction.setRollbackOnly();
- }
- catch (SystemException se) {
- log.error("could not set transaction to rollback only", se);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void afterCompletion(int status) {
- if ( log.isTraceEnabled() ) {
- log.trace("transaction after completion callback, status: " + status);
- }
- try {
- jdbcContext.afterTransactionCompletion(status==Status.STATUS_COMMITTED, hibernateTransaction);
- }
- finally {
- if ( ctx.shouldAutoClose() && !ctx.isClosed() ) {
- log.trace("automatically closing session");
- ctx.managedClose();
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public String toString() {
- return CacheSynchronization.class.getName();
- }
-
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/JBossTSStandaloneTransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/transaction/JBossTSStandaloneTransactionManagerLookup.java
deleted file mode 100644
index 380e10bf5e..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/JBossTSStandaloneTransactionManagerLookup.java
+++ /dev/null
@@ -1,66 +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.transaction;
-
-import java.lang.reflect.Method;
-import java.util.Properties;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-import org.hibernate.HibernateException;
-
-/**
- * Return a standalone JTA transaction manager for JBoss Transactions
- * Known to work for org.jboss.jbossts:jbossjta:4.11.0.Final
- *
- * @author Emmanuel Bernard
- */
-public class JBossTSStandaloneTransactionManagerLookup implements TransactionManagerLookup {
-
- public TransactionManager getTransactionManager(Properties props) throws HibernateException {
- try {
- //Call jtaPropertyManager.getJTAEnvironmentBean().getTransactionManager();
-
- //improper camel case name for the class
- Class> propertyManager = Class.forName( "com.arjuna.ats.jta.common.jtaPropertyManager" );
- final Method getJTAEnvironmentBean = propertyManager.getMethod( "getJTAEnvironmentBean" );
- //static method
- final Object jtaEnvironmentBean = getJTAEnvironmentBean.invoke( null );
- final Method getTransactionManager = jtaEnvironmentBean.getClass().getMethod( "getTransactionManager" );
- return ( TransactionManager ) getTransactionManager.invoke( jtaEnvironmentBean );
- }
- catch ( Exception e ) {
- throw new HibernateException( "Could not obtain JBoss Transactions transaction manager instance", e );
- }
- }
-
- public String getUserTransactionName() {
- return null;
- }
-
- public Object getTransactionIdentifier(Transaction transaction) {
- return transaction;
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/JDBCTransaction.java b/hibernate-core/src/main/java/org/hibernate/transaction/JDBCTransaction.java
deleted file mode 100644
index f89813b646..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/JDBCTransaction.java
+++ /dev/null
@@ -1,275 +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.transaction;
-
-import java.sql.SQLException;
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.HibernateException;
-import org.hibernate.Transaction;
-import org.hibernate.TransactionException;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-import org.hibernate.engine.transaction.SynchronizationRegistry;
-
-/**
- * {@link Transaction} implementation based on transaction management through a JDBC {@link java.sql.Connection}.
- *
- * This the Hibernate's default transaction strategy.
- *
- * @author Anton van Straaten
- * @author Gavin King
- */
-public class JDBCTransaction implements Transaction {
- private static final Logger log = LoggerFactory.getLogger(JDBCTransaction.class);
-
- private final SynchronizationRegistry synchronizationRegistry = new SynchronizationRegistry();
- private final JDBCContext jdbcContext;
- private final TransactionFactory.Context transactionContext;
-
- private boolean toggleAutoCommit;
- private boolean begun;
- private boolean rolledBack;
- private boolean committed;
- private boolean commitFailed;
- private boolean callback;
- private int timeout = -1;
-
- public JDBCTransaction(JDBCContext jdbcContext, TransactionFactory.Context transactionContext) {
- this.jdbcContext = jdbcContext;
- this.transactionContext = transactionContext;
- }
-
- /**
- * {@inheritDoc}
- */
- public void begin() throws HibernateException {
- if (begun) {
- return;
- }
- if (commitFailed) {
- throw new TransactionException("cannot re-start transaction after failed commit");
- }
-
- log.debug("begin");
-
- try {
- toggleAutoCommit = jdbcContext.connection().getAutoCommit();
- if ( log.isDebugEnabled() ) {
- log.debug("current autocommit status: " + toggleAutoCommit);
- }
- if (toggleAutoCommit) {
- log.debug("disabling autocommit");
- jdbcContext.connection().setAutoCommit(false);
- }
- }
- catch (SQLException e) {
- log.error("JDBC begin failed", e);
- throw new TransactionException("JDBC begin failed: ", e);
- }
-
- callback = jdbcContext.registerCallbackIfNecessary();
-
- begun = true;
- committed = false;
- rolledBack = false;
-
- if ( timeout>0 ) {
- jdbcContext.getConnectionManager()
- .setTransactionTimeout(timeout);
- }
-
- jdbcContext.afterTransactionBegin(this);
- }
-
- private void closeIfRequired() throws HibernateException {
- if ( callback && transactionContext.shouldAutoClose() && !transactionContext.isClosed() ) {
- try {
- transactionContext.managedClose();
- }
- catch (HibernateException he) {
- log.error("Could not close session", he);
- //swallow, the transaction was finished
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void commit() throws HibernateException {
- if (!begun) {
- throw new TransactionException("Transaction not successfully started");
- }
-
- log.debug("commit");
-
- if ( !transactionContext.isFlushModeNever() && callback ) {
- transactionContext.managedFlush(); //if an exception occurs during flush, user must call rollback()
- }
-
- notifySynchronizationsBeforeTransactionCompletion();
- if ( callback ) {
- jdbcContext.beforeTransactionCompletion( this );
- }
-
- try {
- commitAndResetAutoCommit();
- log.debug("committed JDBC Connection");
- committed = true;
- if ( callback ) {
- jdbcContext.afterTransactionCompletion( true, this );
- }
- notifySynchronizationsAfterTransactionCompletion( Status.STATUS_COMMITTED );
- }
- catch (SQLException e) {
- log.error("JDBC commit failed", e);
- commitFailed = true;
- if ( callback ) {
- jdbcContext.afterTransactionCompletion( false, this );
- }
- notifySynchronizationsAfterTransactionCompletion( Status.STATUS_UNKNOWN );
- throw new TransactionException("JDBC commit failed", e);
- }
- finally {
- closeIfRequired();
- }
- }
-
- private void commitAndResetAutoCommit() throws SQLException {
- try {
- jdbcContext.connection().commit();
- }
- finally {
- toggleAutoCommit();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void rollback() throws HibernateException {
-
- if (!begun && !commitFailed) {
- throw new TransactionException("Transaction not successfully started");
- }
-
- log.debug("rollback");
-
- if (!commitFailed) {
-
- /*notifyLocalSynchsBeforeTransactionCompletion();
- if ( callback ) {
- jdbcContext.notifyLocalSynchsBeforeTransactionCompletion( this );
- }*/
-
- try {
- rollbackAndResetAutoCommit();
- log.debug("rolled back JDBC Connection");
- rolledBack = true;
- notifySynchronizationsAfterTransactionCompletion(Status.STATUS_ROLLEDBACK);
- }
- catch (SQLException e) {
- log.error("JDBC rollback failed", e);
- notifySynchronizationsAfterTransactionCompletion(Status.STATUS_UNKNOWN);
- throw new TransactionException("JDBC rollback failed", e);
- }
- finally {
- if ( callback ) {
- jdbcContext.afterTransactionCompletion( false, this );
- }
- closeIfRequired();
- }
- }
- }
-
- private void rollbackAndResetAutoCommit() throws SQLException {
- try {
- jdbcContext.connection().rollback();
- }
- finally {
- toggleAutoCommit();
- }
- }
-
- private void toggleAutoCommit() {
- try {
- if (toggleAutoCommit) {
- log.debug("re-enabling autocommit");
- jdbcContext.connection().setAutoCommit( true );
- }
- }
- catch (Exception sqle) {
- log.error("Could not toggle autocommit", sqle);
- //swallow it (the transaction _was_ successful or successfully rolled back)
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean wasRolledBack() {
- return rolledBack;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean wasCommitted() {
- return committed;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isActive() {
- return begun && ! ( rolledBack || committed | commitFailed );
- }
-
- /**
- * {@inheritDoc}
- */
- public void registerSynchronization(Synchronization sync) {
- synchronizationRegistry.registerSynchronization( sync );
- }
-
- private void notifySynchronizationsBeforeTransactionCompletion() {
- synchronizationRegistry.notifySynchronizationsBeforeTransactionCompletion();
- }
-
- private void notifySynchronizationsAfterTransactionCompletion(int status) {
- begun = false;
- synchronizationRegistry.notifySynchronizationsAfterTransactionCompletion( status );
- }
-
- /**
- * {@inheritDoc}
- */
- public void setTimeout(int seconds) {
- timeout = seconds;
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/JDBCTransactionFactory.java b/hibernate-core/src/main/java/org/hibernate/transaction/JDBCTransactionFactory.java
deleted file mode 100644
index a0f6136550..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/JDBCTransactionFactory.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-import java.util.Properties;
-
-import org.hibernate.ConnectionReleaseMode;
-import org.hibernate.HibernateException;
-import org.hibernate.Transaction;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-
-/**
- * Factory for {@link JDBCTransaction} instances.
- *
- * @author Anton van Straaten
- */
-public final class JDBCTransactionFactory implements TransactionFactory {
-
- /**
- * {@inheritDoc}
- */
- public ConnectionReleaseMode getDefaultReleaseMode() {
- return ConnectionReleaseMode.AFTER_TRANSACTION;
- }
-
- /**
- * {@inheritDoc}
- */
- public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)
- throws HibernateException {
- return new JDBCTransaction( jdbcContext, transactionContext );
- }
-
- /**
- * {@inheritDoc}
- */
- public void configure(Properties props) throws HibernateException {}
-
- /**
- * {@inheritDoc}
- */
- public boolean isTransactionManagerRequired() {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean areCallbacksLocalToHibernateTransactions() {
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isTransactionInProgress(
- JDBCContext jdbcContext,
- Context transactionContext,
- Transaction transaction) {
-// try {
-// // for JDBC-based transactions, we only want to return true
-// // here if we (this transaction) are managing the transaction
-// return transaction != null &&
-// transaction.isActive() &&
-// !jdbcContext.getConnectionManager().isAutoCommit();
-// }
-// catch ( SQLException e ) {
-// // assume we are in auto-commit!
-// return false;
-// }
- return transaction != null && transaction.isActive();
- }
-
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/JNDITransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/transaction/JNDITransactionManagerLookup.java
deleted file mode 100644
index 78b0a71bfc..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/JNDITransactionManagerLookup.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-import java.util.Properties;
-
-import javax.naming.NamingException;
-import javax.transaction.TransactionManager;
-import javax.transaction.Transaction;
-
-import org.hibernate.HibernateException;
-import org.hibernate.internal.util.jndi.JndiHelper;
-
-/**
- * Template implementation of {@link TransactionManagerLookup} where the
- * underlying {@link TransactionManager} is available via JNDI lookup at the
- * specified location - {@link #getName}.
- *
- * @author Gavin King
- */
-public abstract class JNDITransactionManagerLookup implements TransactionManagerLookup {
-
- /**
- * Get the JNDI namespace under wich we can locate the {@link TransactionManager}.
- *
- * @return The {@link TransactionManager} JNDI namespace
- */
- protected abstract String getName();
-
- /**
- * {@inheritDoc}
- */
- public TransactionManager getTransactionManager(Properties props) throws HibernateException {
- try {
- return (TransactionManager) JndiHelper.getInitialContext(props).lookup( getName() );
- }
- catch (NamingException ne) {
- throw new HibernateException( "Could not locate TransactionManager", ne );
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public Object getTransactionIdentifier(Transaction transaction) {
- // for sane JEE/JTA containers, the transaction itself functions as its identifier...
- return transaction;
- }
-}
-
-
-
-
-
-
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/JTATransaction.java b/hibernate-core/src/main/java/org/hibernate/transaction/JTATransaction.java
deleted file mode 100644
index 856362414e..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/JTATransaction.java
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
-import javax.transaction.SystemException;
-import javax.transaction.TransactionManager;
-import javax.transaction.UserTransaction;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.HibernateException;
-import org.hibernate.Transaction;
-import org.hibernate.TransactionException;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-import org.hibernate.util.JTAHelper;
-
-/**
- * {@link Transaction} implementation based on transaction management through
- * a JTA {@link UserTransaction}. Similar to {@link CMTTransaction}, except
- * here we are actually managing the transactions through the Hibernate
- * transaction mechanism.
- *
- * @author Gavin King
- * @author Steve Ebersole
- * @author Les Hazlewood
- */
-public class JTATransaction implements Transaction {
-
- private static final Logger log = LoggerFactory.getLogger( JTATransaction.class );
-
- private final JDBCContext jdbcContext;
- private final TransactionFactory.Context transactionContext;
-
- private UserTransaction userTransaction;
- private boolean newTransaction;
- private boolean begun;
- private boolean commitFailed;
- private boolean commitSucceeded;
- private boolean callback;
-
- public JTATransaction(
- UserTransaction userTransaction,
- JDBCContext jdbcContext,
- TransactionFactory.Context transactionContext) {
- this.jdbcContext = jdbcContext;
- this.transactionContext = transactionContext;
- this.userTransaction = userTransaction;
- }
-
- /**
- * {@inheritDoc}
- */
- public void begin() throws HibernateException {
- if ( begun ) {
- return;
- }
- if ( commitFailed ) {
- throw new TransactionException( "cannot re-start transaction after failed commit" );
- }
-
- log.debug( "begin" );
-
- try {
- newTransaction = userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION;
- if ( newTransaction ) {
- userTransaction.begin();
- log.debug( "Began a new JTA transaction" );
- }
- }
- catch ( Exception e ) {
- log.error( "JTA transaction begin failed", e );
- throw new TransactionException( "JTA transaction begin failed", e );
- }
-
- /*if (newTransaction) {
- // don't need a synchronization since we are committing
- // or rolling back the transaction ourselves - assuming
- // that we do no work in beforeTransactionCompletion()
- synchronization = false;
- }*/
-
- boolean synchronization = jdbcContext.registerSynchronizationIfPossible();
-
- if ( !newTransaction && !synchronization ) {
- log.warn( "You should set hibernate.transaction.manager_lookup_class if cache is enabled" );
- }
-
- if ( !synchronization ) {
- //if we could not register a synchronization,
- //do the before/after completion callbacks
- //ourself (but we need to let jdbcContext
- //know that this is what we are going to
- //do, so it doesn't keep trying to register
- //synchronizations)
- callback = jdbcContext.registerCallbackIfNecessary();
- }
-
- begun = true;
- commitSucceeded = false;
-
- jdbcContext.afterTransactionBegin( this );
- }
-
- /**
- * {@inheritDoc}
- */
- public void commit() throws HibernateException {
- if ( !begun ) {
- throw new TransactionException( "Transaction not successfully started" );
- }
-
- log.debug( "commit" );
-
- boolean flush = !transactionContext.isFlushModeNever()
- && ( callback || !transactionContext.isFlushBeforeCompletionEnabled() );
-
- if ( flush ) {
- transactionContext.managedFlush(); //if an exception occurs during flush, user must call rollback()
- }
-
- if ( callback && newTransaction ) {
- jdbcContext.beforeTransactionCompletion( this );
- }
-
- closeIfRequired();
-
- if ( newTransaction ) {
- try {
- userTransaction.commit();
- commitSucceeded = true;
- log.debug( "Committed JTA UserTransaction" );
- }
- catch ( Exception e ) {
- commitFailed = true; // so the transaction is already rolled back, by JTA spec
- log.error( "JTA commit failed", e );
- throw new TransactionException( "JTA commit failed: ", e );
- }
- finally {
- afterCommitRollback();
- }
- }
- else {
- // this one only really needed for badly-behaved applications!
- // (if the TransactionManager has a Sychronization registered,
- // its a noop)
- // (actually we do need it for downgrading locks)
- afterCommitRollback();
- }
-
- }
-
- /**
- * {@inheritDoc}
- */
- public void rollback() throws HibernateException {
- if ( !begun && !commitFailed ) {
- throw new TransactionException( "Transaction not successfully started" );
- }
-
- log.debug( "rollback" );
-
- try {
- closeIfRequired();
- }
- catch ( Exception e ) {
- // swallow it, and continue to roll back JTA transaction
- log.error( "could not close session during rollback", e );
- }
-
- try {
- if ( newTransaction ) {
- if ( !commitFailed ) {
- userTransaction.rollback();
- log.debug( "Rolled back JTA UserTransaction" );
- }
- }
- else {
- userTransaction.setRollbackOnly();
- log.debug( "set JTA UserTransaction to rollback only" );
- }
- }
- catch ( Exception e ) {
- log.error( "JTA rollback failed", e );
- throw new TransactionException( "JTA rollback failed", e );
- }
- finally {
- afterCommitRollback();
- }
- }
-
- private static final int NULL = Integer.MIN_VALUE;
-
- private void afterCommitRollback() throws TransactionException {
-
- begun = false;
- // this method is a noop if there is a Synchronization!
- if ( callback ) {
- if ( !newTransaction ) {
- log.warn( "You should set hibernate.transaction.manager_lookup_class if cache is enabled" );
- }
- int status = NULL;
- try {
- status = userTransaction.getStatus();
- }
- catch ( Exception e ) {
- log.error( "Could not determine transaction status after commit", e );
- throw new TransactionException( "Could not determine transaction status after commit", e );
- }
- finally {
- jdbcContext.afterTransactionCompletion( status == Status.STATUS_COMMITTED, this );
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean wasRolledBack() throws TransactionException {
- final int status;
- try {
- status = userTransaction.getStatus();
- }
- catch ( SystemException se ) {
- log.error( "Could not determine transaction status", se );
- throw new TransactionException( "Could not determine transaction status", se );
- }
- if ( status == Status.STATUS_UNKNOWN ) {
- throw new TransactionException( "Could not determine transaction status" );
- }
- else {
- return JTAHelper.isRollback( status );
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean wasCommitted() throws TransactionException {
- final int status;
- try {
- status = userTransaction.getStatus();
- }
- catch ( SystemException se ) {
- log.error( "Could not determine transaction status", se );
- throw new TransactionException( "Could not determine transaction status: ", se );
- }
- if ( status == Status.STATUS_UNKNOWN ) {
- throw new TransactionException( "Could not determine transaction status" );
- }
- else {
- return status == Status.STATUS_COMMITTED;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isActive() throws TransactionException {
- if ( !begun || commitFailed || commitSucceeded ) {
- return false;
- }
-
- final int status;
- try {
- status = userTransaction.getStatus();
- }
- catch ( SystemException se ) {
- log.error( "Could not determine transaction status", se );
- throw new TransactionException( "Could not determine transaction status: ", se );
- }
- if ( status == Status.STATUS_UNKNOWN ) {
- throw new TransactionException( "Could not determine transaction status" );
- }
- else {
- return status == Status.STATUS_ACTIVE;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void registerSynchronization(Synchronization sync) throws HibernateException {
- if ( getTransactionManager() == null ) {
- throw new IllegalStateException( "JTA TransactionManager not available" );
- }
- else {
- try {
- getTransactionManager().getTransaction().registerSynchronization( sync );
- }
- catch ( Exception e ) {
- throw new TransactionException( "could not register synchronization", e );
- }
- }
- }
-
- /**
- * Getter for property 'transactionManager'.
- *
- * @return Value for property 'transactionManager'.
- */
- private TransactionManager getTransactionManager() {
- return transactionContext.getFactory().getTransactionManager();
- }
-
- private void closeIfRequired() throws HibernateException {
- boolean close = callback &&
- transactionContext.shouldAutoClose() &&
- !transactionContext.isClosed();
- if ( close ) {
- transactionContext.managedClose();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void setTimeout(int seconds) {
- try {
- userTransaction.setTransactionTimeout( seconds );
- }
- catch ( SystemException se ) {
- throw new TransactionException( "could not set transaction timeout", se );
- }
- }
-
- /**
- * Getter for property 'userTransaction'.
- *
- * @return Value for property 'userTransaction'.
- */
- protected UserTransaction getUserTransaction() {
- return userTransaction;
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/JTATransactionFactory.java b/hibernate-core/src/main/java/org/hibernate/transaction/JTATransactionFactory.java
deleted file mode 100644
index 82b2713545..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/JTATransactionFactory.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-import java.util.Properties;
-
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.transaction.SystemException;
-import javax.transaction.UserTransaction;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.ConnectionReleaseMode;
-import org.hibernate.HibernateException;
-import org.hibernate.Transaction;
-import org.hibernate.TransactionException;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-import org.hibernate.internal.util.jndi.JndiHelper;
-import org.hibernate.cfg.Environment;
-import org.hibernate.util.JTAHelper;
-
-/**
- * Factory for {@link JTATransaction} instances.
- *
- * To be completely accurate to the JTA spec, JTA implementations should
- * publish their contextual {@link UserTransaction} reference into JNDI.
- * However, in practice there are quite a few stand-alone
- * implementations intended for use outside of J2EE/JEE containers and
- * which therefore do not publish their {@link UserTransaction} references
- * into JNDI but which otherwise follow the aspects of the JTA specification.
- * This {@link TransactionFactory} implementation can support both models.
- *
- * For complete JTA implementations (including dependence on JNDI), the
- * {@link UserTransaction} reference is obtained by a call to
- * {@link #resolveInitialContext}. Hibernate will then attempt to locate the
- * {@link UserTransaction} within this resolved
- * {@link InitialContext} based on the namespace returned by
- * {@link #resolveUserTransactionName}.
- *
- * For the so-called stand-alone implementations, we do not care at
- * all about the JNDI aspects just described. Here, the implementation would
- * have a specific manner to obtain a reference to its contextual
- * {@link UserTransaction}; usually this would be a static code reference, but
- * again it varies. Anyway, for each implementation the integration would need
- * to override the {@link #getUserTransaction} method and return the appropriate
- * thing.
- *
- * @author Gavin King
- * @author Steve Ebersole
- * @author Les Hazlewood
- */
-public class JTATransactionFactory implements TransactionFactory {
- public static final String DEFAULT_USER_TRANSACTION_NAME = "java:comp/UserTransaction";
- private static final Logger log = LoggerFactory.getLogger( JTATransactionFactory.class );
-
- protected InitialContext initialContext;
- protected String userTransactionName;
-
- /**
- * Configure this transaction factory. Specifically here we are attempting to
- * resolve both an {@link #getInitialContext InitialContext} as well as the
- * {@link #getUserTransactionName() JNDI namespace} for the {@link UserTransaction}.
- *
- * @param props The configuration properties
- *
- * @exception HibernateException
- */
- public void configure(Properties props) throws HibernateException {
- this.initialContext = resolveInitialContext( props );
- this.userTransactionName = resolveUserTransactionName( props );
- log.trace( "Configured JTATransactionFactory to use [{}] for UserTransaction JDNI namespace", userTransactionName );
- }
-
- /**
- * Given the lot of Hibernate configuration properties, resolve appropriate
- * reference to JNDI {@link InitialContext}.
- *
- * In general, the properties in which we are interested here all begin with
- * hibernate.jndi. Especially important depending on your
- * environment are {@link Environment#JNDI_URL hibernate.jndi.url} and
- * {@link Environment#JNDI_CLASS hibernate.jndi.class}
- *
- * @param properties The Hibernate config properties.
- * @return The resolved InitialContext.
- */
- protected final InitialContext resolveInitialContext(Properties properties) {
- try {
- return JndiHelper.getInitialContext( properties );
- }
- catch ( NamingException ne ) {
- throw new HibernateException( "Could not obtain initial context", ne );
- }
- }
-
- /**
- * Given the lot of Hibernate configuration properties, resolve appropriate
- * JNDI namespace to use for {@link UserTransaction} resolution.
- *
- * We determine the namespace to use by
- * - Any specified {@link Environment#USER_TRANSACTION jta.UserTransaction} config property
- * - If a {@link TransactionManagerLookup} was indicated, use its
- * {@link TransactionManagerLookup#getUserTransactionName}
- * - finally, as a last resort, we use {@link #DEFAULT_USER_TRANSACTION_NAME}
- *
- *
- * @param properties The Hibernate config properties.
- * @return The resolved {@link UserTransaction} namespace
- */
- protected final String resolveUserTransactionName(Properties properties) {
- String utName = properties.getProperty( Environment.USER_TRANSACTION );
- if ( utName == null ) {
- TransactionManagerLookup lookup = TransactionManagerLookupFactory.getTransactionManagerLookup( properties );
- if ( lookup != null ) {
- utName = lookup.getUserTransactionName();
- }
- }
- return utName == null ? DEFAULT_USER_TRANSACTION_NAME : utName;
- }
-
- /**
- * {@inheritDoc}
- */
- public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)
- throws HibernateException {
- UserTransaction ut = getUserTransaction();
- return new JTATransaction( ut, jdbcContext, transactionContext );
- }
-
- /**
- * Get the {@link UserTransaction} reference.
- *
- * @return The appropriate {@link UserTransaction} reference.
- */
- protected UserTransaction getUserTransaction() {
- final String utName = getUserTransactionName();
- log.trace( "Attempting to locate UserTransaction via JNDI [{}]", utName );
-
- try {
- UserTransaction ut = ( UserTransaction ) getInitialContext().lookup( utName );
- if ( ut == null ) {
- throw new TransactionException( "Naming service lookup for UserTransaction returned null [" + utName +"]" );
- }
-
- log.trace( "Obtained UserTransaction" );
-
- return ut;
- }
- catch ( NamingException ne ) {
- throw new TransactionException( "Could not find UserTransaction in JNDI [" + utName + "]", ne );
- }
- }
-
- /**
- * Getter for property 'initialContext'.
- *
- * @return Value for property 'initialContext'.
- */
- protected InitialContext getInitialContext() {
- return initialContext;
- }
-
- /**
- * Getter for property 'userTransactionName'.
- * The algorithm here is
- *
- * @return Value for property 'userTransactionName'.
- */
- protected String getUserTransactionName() {
- return userTransactionName;
- }
-
- /**
- * {@inheritDoc}
- */
- public ConnectionReleaseMode getDefaultReleaseMode() {
- return ConnectionReleaseMode.AFTER_STATEMENT;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isTransactionManagerRequired() {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean areCallbacksLocalToHibernateTransactions() {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isTransactionInProgress(
- JDBCContext jdbcContext,
- Context transactionContext,
- Transaction 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 = ( ( JTATransaction ) transaction ).getUserTransaction();
- if ( ut != null ) {
- return JTAHelper.isInProgress( ut.getStatus() );
- }
- }
-
- if ( jdbcContext.getFactory().getTransactionManager() != null ) {
- return JTAHelper.isInProgress( jdbcContext.getFactory().getTransactionManager().getStatus() );
- }
- else {
- UserTransaction ut = getUserTransaction();
- return ut != null && JTAHelper.isInProgress( ut.getStatus() );
- }
- }
- catch ( SystemException se ) {
- throw new TransactionException( "Unable to check transaction status", se );
- }
- }
-
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/SunONETransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/transaction/SunONETransactionManagerLookup.java
deleted file mode 100644
index 0bfd3283ce..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/SunONETransactionManagerLookup.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-/**
- * {@link TransactionManagerLookup} strategy for Sun ONE Application Server 7 and above
- *
- * @author Robert Davidson
- * @author Sanjeev Krishnan
- * @author Emmanuel Bernard
- */
-public class SunONETransactionManagerLookup extends JNDITransactionManagerLookup {
-
- /**
- * {@inheritDoc}
- */
- protected String getName() {
- return "java:appserver/TransactionManager";
- }
-
- /**
- * {@inheritDoc}
- */
- public String getUserTransactionName() {
- return "java:comp/UserTransaction";
- }
-
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/TransactionFactory.java b/hibernate-core/src/main/java/org/hibernate/transaction/TransactionFactory.java
deleted file mode 100644
index 1f55957649..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/TransactionFactory.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-import java.util.Properties;
-
-import org.hibernate.ConnectionReleaseMode;
-import org.hibernate.HibernateException;
-import org.hibernate.Transaction;
-import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-
-/**
- * Contract for generating Hibernate {@link Transaction} instances.
- *
- * The concrete implementation to be used is specified by the
- * {@link org.hibernate.cfg.Environment#TRANSACTION_STRATEGY} configuration
- * setting.
- *
- * Implementors must be threadsafe and should declare a public default constructor.
- *
- * @see Transaction
- *
- * @author Anton van Straaten
- * @author Gavin King
- */
-public interface TransactionFactory {
-
- /**
- * Callback mechanism; a context is always a {@link org.hibernate.Session}
- * in the Hibernate usage.
- */
- public static interface Context {
- public SessionFactoryImplementor getFactory();
- public boolean isClosed();
-
- public boolean isFlushModeNever();
- public boolean isFlushBeforeCompletionEnabled();
- public void managedFlush();
-
- public boolean shouldAutoClose();
- public void managedClose();
- }
-
- /**
- * Begin a transaction and return the associated Transaction instance.
- *
- * @param jdbcContext The jdbc context to which the transaction belongs
- * @param context The contract regarding the context in which this transaction will operate.
- * @return Transaction
- * @throws HibernateException Indicates a problem generating a transaction instance
- */
- public Transaction createTransaction(JDBCContext jdbcContext, Context context) throws HibernateException;
-
- /**
- * Configure from the given properties.
- *
- * @param props The configuration properties.
- * @throws HibernateException Indicates a problem configuring this factory.
- */
- public void configure(Properties props) throws HibernateException;
-
- /**
- * Get the default connection release mode.
- *
- * @return The default release mode associated with this strategy
- */
- public ConnectionReleaseMode getDefaultReleaseMode();
-
- /**
- * Do we require access to the JTA TransactionManager for
- * this strategy?
- *
- * @return True if this strategy requires access to the JTA TransactionManager;
- * false otherwise.
- */
- public boolean isTransactionManagerRequired();
-
- /**
- * Are all transaction callbacks local to Hibernate Transactions?
- * Or can the callbacks originate from some other source (e.g. a JTA
- * Synchronization).
- *
- * @return true if callbacks only ever originate from the Hibernate
- * {@link Transaction}; false otherwise.
- */
- public boolean areCallbacksLocalToHibernateTransactions();
-
- /**
- * Determine whether an underlying transaction is in progress.
- *
- * Mainly this is used in determining whether to register a
- * synchronization as well as whether or not to circumvent
- * auto flushing outside transactions.
- *
- * @param jdbcContext The JDBC context
- * @param transactionContext The transaction context
- * @param transaction The Hibernate transaction
- * @return true if an underlying transaction is know to be in effect.
- */
- public boolean isTransactionInProgress(JDBCContext jdbcContext, Context transactionContext, Transaction transaction);
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/TransactionFactoryFactory.java b/hibernate-core/src/main/java/org/hibernate/transaction/TransactionFactoryFactory.java
deleted file mode 100644
index 903ae90faa..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/TransactionFactoryFactory.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-import java.util.Properties;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.HibernateException;
-import org.hibernate.cfg.Environment;
-import org.hibernate.util.ReflectHelper;
-
-/**
- * Helper for creating {@link TransactionFactory} instances.
- *
- * @author Gavin King
- */
-public final class TransactionFactoryFactory {
-
- private static final Logger log = LoggerFactory.getLogger( TransactionFactoryFactory.class );
-
- /**
- * Create an appropriate transaction factory based on the given configuration
- * properties.
- *
- * @param transactionProps transaction properties
- *
- * @return The appropriate transaction factory.
- *
- * @throws HibernateException Indicates a problem creating the appropriate
- * transaction factory.
- */
- public static TransactionFactory buildTransactionFactory(Properties transactionProps) throws HibernateException {
- String strategyClassName = transactionProps.getProperty( Environment.TRANSACTION_STRATEGY );
- if ( strategyClassName == null ) {
- log.info( "Using default transaction strategy (direct JDBC transactions)" );
- return new JDBCTransactionFactory();
- }
- log.info( "Transaction strategy: " + strategyClassName );
- TransactionFactory factory;
- try {
- factory = ( TransactionFactory ) ReflectHelper.classForName( strategyClassName ).newInstance();
- }
- catch ( ClassNotFoundException e ) {
- log.error( "TransactionFactory class not found", e );
- throw new HibernateException( "TransactionFactory class not found: " + strategyClassName );
- }
- catch ( IllegalAccessException e ) {
- log.error( "Failed to instantiate TransactionFactory", e );
- throw new HibernateException( "Failed to instantiate TransactionFactory: " + e );
- }
- catch ( java.lang.InstantiationException e ) {
- log.error( "Failed to instantiate TransactionFactory", e );
- throw new HibernateException( "Failed to instantiate TransactionFactory: " + e );
- }
- factory.configure( transactionProps );
- return factory;
- }
-
- /**
- * Disallow instantiation
- */
- private TransactionFactoryFactory() {
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/TransactionManagerLookupFactory.java b/hibernate-core/src/main/java/org/hibernate/transaction/TransactionManagerLookupFactory.java
deleted file mode 100644
index 11509cd508..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/TransactionManagerLookupFactory.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-import java.util.Properties;
-
-import javax.transaction.TransactionManager;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.HibernateException;
-import org.hibernate.cfg.Environment;
-import org.hibernate.util.ReflectHelper;
-
-/**
- * Helper for generating {@link TransactionManagerLookup} instances.
- *
- * @author Gavin King
- */
-public final class TransactionManagerLookupFactory {
-
- private static final Logger log = LoggerFactory.getLogger(TransactionManagerLookupFactory.class);
-
- /**
- * Disallow instantiation
- */
- private TransactionManagerLookupFactory() {
- }
-
- /**
- * Convenience method for locating the JTA {@link TransactionManager} from the
- * given platform config.
- *
- * Same as calling {@link #getTransactionManager}.getTransactionManager( props )
- *
- * @param props The properties representing the platform config
- * @return The located {@link TransactionManager}
- * @throws HibernateException Indicates a problem either (a) generatng the
- * {@link TransactionManagerLookup} or (b) asking it to locate the {@link TransactionManager}.
- */
- public static TransactionManager getTransactionManager(Properties props) throws HibernateException {
- log.info( "obtaining TransactionManager" );
- return getTransactionManagerLookup( props ).getTransactionManager( props );
- }
-
- /**
- * Generate the appropriate {@link TransactionManagerLookup} given the
- * config settings being passed.
- *
- * @param props The config settings
- * @return The appropriate {@link TransactionManagerLookup}
- * @throws HibernateException Indicates problem generating {@link TransactionManagerLookup}
- */
- public static TransactionManagerLookup getTransactionManagerLookup(Properties props) throws HibernateException {
- String tmLookupClass = props.getProperty( Environment.TRANSACTION_MANAGER_STRATEGY );
- if ( tmLookupClass == null ) {
- log.info( "No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)" );
- return null;
- }
- else {
- log.info( "instantiating TransactionManagerLookup: " + tmLookupClass );
- try {
- TransactionManagerLookup lookup = ( TransactionManagerLookup )
- ReflectHelper.classForName( tmLookupClass ).newInstance();
- log.info( "instantiated TransactionManagerLookup" );
- return lookup;
- }
- catch ( Exception e ) {
- log.error( "Could not instantiate TransactionManagerLookup", e );
- throw new HibernateException( "Could not instantiate TransactionManagerLookup '" + tmLookupClass + "'" );
- }
- }
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/WebSphereTransactionManagerLookup.java b/hibernate-core/src/main/java/org/hibernate/transaction/WebSphereTransactionManagerLookup.java
deleted file mode 100644
index 713a916a47..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/transaction/WebSphereTransactionManagerLookup.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
- *
- * 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.transaction;
-
-import java.lang.reflect.Method;
-import java.util.Properties;
-
-import javax.transaction.TransactionManager;
-import javax.transaction.Transaction;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.HibernateException;
-
-/**
- * {@link TransactionManagerLookup} strategy for WebSphere (versions 4, 5.0 and 5.1)
- *
- * @author Gavin King
- */
-@SuppressWarnings( {"UnusedDeclaration"})
-public class WebSphereTransactionManagerLookup implements TransactionManagerLookup {
-
- private static final Logger log = LoggerFactory.getLogger(WebSphereTransactionManagerLookup.class);
- private final int wsVersion;
- private final Class tmfClass;
-
- /**
- * Constructs a new WebSphereTransactionManagerLookup.
- */
- public WebSphereTransactionManagerLookup() {
- try {
- Class clazz;
- int version;
- try {
- clazz = Class.forName( "com.ibm.ws.Transaction.TransactionManagerFactory" );
- version = 5;
- log.info( "WebSphere 5.1" );
- }
- catch ( Exception e ) {
- try {
- clazz = Class.forName( "com.ibm.ejs.jts.jta.TransactionManagerFactory" );
- version = 5;
- log.info( "WebSphere 5.0" );
- }
- catch ( Exception e2 ) {
- clazz = Class.forName( "com.ibm.ejs.jts.jta.JTSXA" );
- version = 4;
- log.info( "WebSphere 4" );
- }
- }
-
- tmfClass = clazz;
- wsVersion = version;
- }
- catch ( Exception e ) {
- throw new HibernateException( "Could not obtain WebSphere TransactionManagerFactory instance", e );
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public TransactionManager getTransactionManager(Properties props) throws HibernateException {
- try {
- final Method method = tmfClass.getMethod( "getTransactionManager", (Class[]) null );
- return ( TransactionManager ) method.invoke( null, (Object[]) null );
- }
- catch ( Exception e ) {
- throw new HibernateException( "Could not obtain WebSphere TransactionManager", e );
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public String getUserTransactionName() {
- return wsVersion == 5
- ? "java:comp/UserTransaction"
- : "jta/usertransaction";
- }
-
- /**
- * {@inheritDoc}
- */
- public Object getTransactionIdentifier(Transaction transaction) {
- return transaction;
- }
-}
\ No newline at end of file
diff --git a/hibernate-core/src/main/java/org/hibernate/type/DbTimestampType.java b/hibernate-core/src/main/java/org/hibernate/type/DbTimestampType.java
index 46df7b29c0..316048d320 100644
--- a/hibernate-core/src/main/java/org/hibernate/type/DbTimestampType.java
+++ b/hibernate-core/src/main/java/org/hibernate/type/DbTimestampType.java
@@ -89,7 +89,10 @@ public class DbTimestampType extends TimestampType {
private Timestamp usePreparedStatement(String timestampSelectString, SessionImplementor session) {
PreparedStatement ps = null;
try {
- ps = session.getJDBCContext().getConnectionManager().prepareStatement( timestampSelectString, false );
+ ps = session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( timestampSelectString, false );
ResultSet rs = ps.executeQuery();
rs.next();
Timestamp ts = rs.getTimestamp( 1 );
@@ -102,12 +105,12 @@ public class DbTimestampType extends TimestampType {
}
return ts;
}
- catch( SQLException sqle ) {
+ catch( SQLException e ) {
throw session.getFactory().getSQLExceptionHelper().convert(
- sqle,
+ e,
"could not select current db timestamp",
timestampSelectString
- );
+ );
}
finally {
if ( ps != null ) {
@@ -124,7 +127,10 @@ public class DbTimestampType extends TimestampType {
private Timestamp useCallableStatement(String callString, SessionImplementor session) {
CallableStatement cs = null;
try {
- cs = session.getJDBCContext().getConnectionManager().prepareCallableStatement( callString );
+ cs = (CallableStatement) session.getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getStatementPreparer()
+ .prepareStatement( callString, true );
cs.registerOutParameter( 1, java.sql.Types.TIMESTAMP );
cs.execute();
Timestamp ts = cs.getTimestamp( 1 );
@@ -137,12 +143,12 @@ public class DbTimestampType extends TimestampType {
}
return ts;
}
- catch( SQLException sqle ) {
+ catch( SQLException e ) {
throw session.getFactory().getSQLExceptionHelper().convert(
- sqle,
+ e,
"could not call current db timestamp function",
callString
- );
+ );
}
finally {
if ( cs != null ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/util/JTAHelper.java b/hibernate-core/src/main/java/org/hibernate/util/JTAHelper.java
index 68b75da64f..8267d93b74 100755
--- a/hibernate-core/src/main/java/org/hibernate/util/JTAHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/util/JTAHelper.java
@@ -30,6 +30,7 @@ import javax.transaction.TransactionManager;
import org.hibernate.TransactionException;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
/**
* @author Gavin King
@@ -54,7 +55,7 @@ public final class JTAHelper {
* and false in *every* other cases (including in a JDBC transaction).
*/
public static boolean isTransactionInProgress(SessionFactoryImplementor factory) {
- TransactionManager tm = factory.getTransactionManager();
+ TransactionManager tm = factory.getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager();
try {
return tm != null && isTransactionInProgress( tm.getTransaction() );
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java
index 31300f24ea..206a7e96a3 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java
@@ -3,6 +3,13 @@
package org.hibernate.test.annotations.manytomany;
+import org.hibernate.Hibernate;
+import org.hibernate.JDBCException;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.test.annotations.TestCase;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -11,13 +18,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import org.hibernate.Hibernate;
-import org.hibernate.JDBCException;
-import org.hibernate.Session;
-import org.hibernate.Transaction;
-import org.hibernate.criterion.Restrictions;
-import org.hibernate.test.annotations.TestCase;
-
/**
* Many to many tests
*
@@ -680,30 +680,29 @@ public class ManyToManyTest extends TestCase {
// or property.
public void testManyToManyEmbeddableBiDirectionalDotNotationInMappedBy() throws Exception {
Session s;
- Transaction tx;
s = openSession();
- tx = s.beginTransaction();
+ s.getTransaction().begin();
Employee e = new Employee();
e.setName( "Sharon" );
List phoneNumbers = new ArrayList();
Collection employees = new ArrayList();
employees.add( e );
- ContactInfo contactInfo = new ContactInfo();
+ ContactInfo contactInfo = new ContactInfo();
PhoneNumber number = new PhoneNumber();
number.setEmployees( employees );
phoneNumbers.add( number );
contactInfo.setPhoneNumbers( phoneNumbers );
e.setContactInfo( contactInfo );
s.persist( e );
- s.flush();
- s.clear();
- tx.commit();
+ s.getTransaction().commit();
+ s.close();
- tx.begin();
+ s = openSession();
+ s.getTransaction().begin();
e = (Employee)s.get( e.getClass(),e.getId() );
// follow both directions of many to many association
assertEquals("same employee", e.getName(), e.getContactInfo().getPhoneNumbers().get(0).getEmployees().iterator().next().getName());
- tx.commit();
+ s.getTransaction().commit();
s.close();
}
@@ -718,9 +717,8 @@ public class ManyToManyTest extends TestCase {
// with the dot notation is the name of the respective embedded field or property.
public void testOneToManyEmbeddableBiDirectionalDotNotationInMappedBy() throws Exception {
Session s;
- Transaction tx;
s = openSession();
- tx = s.beginTransaction();
+ s.getTransaction().begin();
Employee e = new Employee();
JobInfo job = new JobInfo();
job.setJobDescription( "Sushi Chef" );
@@ -731,16 +729,16 @@ public class ManyToManyTest extends TestCase {
job.setPm(pm);
e.setJobInfo( job );
s.persist( e );
- s.flush();
- s.clear();
- tx.commit();
+ s.getTransaction().commit();
+ s.close();
- tx.begin();
+ s = openSession();
+ s.getTransaction().begin();
e = (Employee) s.get( e.getClass(), e.getId() );
assertEquals( "same job in both directions",
e.getJobInfo().getJobDescription(),
e.getJobInfo().getPm().getManages().iterator().next().getJobInfo().getJobDescription() );
- tx.commit();
+ s.getTransaction().commit();
s.close();
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java
index f99a403405..de749ad461 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java
@@ -269,6 +269,26 @@ public class ManyToOneTest extends TestCase {
s.close();
}
+ public void testManyToOneNonPkSecondaryTable() throws Exception {
+ Session s = openSession();
+ Transaction tx = s.beginTransaction();
+ Order order = new Order();
+ order.setOrderNbr( "123" );
+ s.persist( order );
+ OrderLine ol = new OrderLine();
+ ol.setItem( "Mouse" );
+ ol.setReplacementOrder( order );
+ s.persist( ol );
+ s.flush();
+ s.clear();
+ ol = (OrderLine) s.get( OrderLine.class, ol.getId() );
+ assertNotNull( ol.getReplacementOrder() );
+ assertEquals( "123", ol.getReplacementOrder().getOrderNbr() );
+ assertFalse( ol.getReplacementOrder().getOrderLines().contains( ol ) );
+ tx.rollback();
+ s.close();
+ }
+
public void testTwoManyToOneNonPk() throws Exception {
//2 many to one non pk pointing to the same referencedColumnName should not fail
Session s = openSession();
diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/OrderLine.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/OrderLine.java
index 22fc79374c..1b8ed9517a 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/OrderLine.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/OrderLine.java
@@ -6,15 +6,18 @@ import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.ManyToOne;
import javax.persistence.JoinColumn;
+import javax.persistence.SecondaryTable;
/**
* @author Emmanuel Bernard
*/
@Entity
+@SecondaryTable(name="OrderLine_Extension")
public class OrderLine {
private Integer id;
private String item;
private Order order;
+ private Order replacementOrder;
@Id @GeneratedValue
public Integer getId() {
@@ -42,4 +45,14 @@ public class OrderLine {
public void setOrder(Order order) {
this.order = order;
}
+
+ @ManyToOne
+ @JoinColumn(name="replacement_order_nbr", table="OrderLine_Extension", referencedColumnName = "order_nbr")
+ public Order getReplacementOrder() {
+ return replacementOrder;
+ }
+
+ public void setReplacementOrder(Order replacementOrder) {
+ this.replacementOrder = replacementOrder;
+ }
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/Client.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/Client.java
index 44c0a2b456..79c64c1c00 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/Client.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/Client.java
@@ -7,16 +7,19 @@ import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
+import javax.persistence.SecondaryTable;
/**
* @author Emmanuel Bernard
*/
@Entity
+@SecondaryTable(name="CLIENT_EXTENSION")
public class Client {
private Integer id;
private String name;
private Address address;
+ private Address secondaryAddress;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "ADDRESS_ID")
@@ -28,6 +31,16 @@ public class Client {
this.address = address;
}
+ @OneToOne(cascade = CascadeType.ALL)
+ @JoinColumn(name = "SECONDARY_ADDRESS_ID", table="CLIENT_EXTENSION")
+ public Address getSecondaryAddress() {
+ return secondaryAddress;
+ }
+
+ public void setSecondaryAddress(Address secondaryAddress) {
+ this.secondaryAddress = secondaryAddress;
+ }
+
@Id
@GeneratedValue
public Integer getId() {
diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java
index a47bb96a90..7a97a0df75 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java
@@ -108,6 +108,31 @@ public class OneToOneTest extends TestCase {
s.close();
}
+ public void testOneToOneWithExplicitSecondaryTableFk() throws Exception {
+ Client c = new Client();
+ Address a = new Address();
+ a.setCity( "Paris" );
+ c.setName( "Emmanuel" );
+ c.setSecondaryAddress( a );
+
+ Session s;
+ Transaction tx;
+ s = openSession();
+ tx = s.beginTransaction();
+ s.persist( c );
+ tx.commit();
+ s.close();
+
+ s = openSession();
+ tx = s.beginTransaction();
+ c = ( Client ) s.get( Client.class, c.getId() );
+ assertNotNull( c );
+ assertNotNull( c.getSecondaryAddress() );
+ assertEquals( "Paris", c.getSecondaryAddress().getCity() );
+ tx.commit();
+ s.close();
+ }
+
public void testUnidirectionalTrueOneToOne() throws Exception {
Body b = new Body();
Heart h = new Heart();
diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/PolymorphismTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/PolymorphismTest.java
index 0929a56ff6..1b1acda0b3 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/PolymorphismTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/PolymorphismTest.java
@@ -17,7 +17,6 @@ public class PolymorphismTest extends TestCase {
car2.setModel( "350Z" );
Session s = openSession();
Transaction tx = s.beginTransaction();
- tx.begin();
s.persist( car );
s.persist( car2 );
s.flush();
diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/subselect/SubselectTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/subselect/SubselectTest.java
index 4614022d36..bf095d0692 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/annotations/subselect/SubselectTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/subselect/SubselectTest.java
@@ -43,8 +43,7 @@ public class SubselectTest extends TestCase {
Session s = openSession();
Transaction tx = s.beginTransaction();
- tx.begin();
-
+
//We don't use auto-generated ids because these seem to cause the session to flush.
//We want to test that the session flushes because of the 'synchronize' annotation
long itemId = 1;
diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/JournalingBatchObserver.java b/hibernate-core/src/test/java/org/hibernate/test/common/JournalingBatchObserver.java
new file mode 100644
index 0000000000..bf9edee45e
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/common/JournalingBatchObserver.java
@@ -0,0 +1,57 @@
+/*
+ * 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.test.common;
+
+import org.hibernate.engine.jdbc.batch.spi.BatchObserver;
+
+/**
+ * @author Steve Ebersole
+ */
+public class JournalingBatchObserver implements BatchObserver {
+ private int implicitExecutionCount;
+ private int explicitExecutionCount;
+
+ @Override
+ public void batchExplicitlyExecuted() {
+ explicitExecutionCount++;
+ }
+
+ @Override
+ public void batchImplicitlyExecuted() {
+ implicitExecutionCount++;
+ }
+
+ public int getImplicitExecutionCount() {
+ return implicitExecutionCount;
+ }
+
+ public int getExplicitExecutionCount() {
+ return explicitExecutionCount;
+ }
+
+ public void reset() {
+ explicitExecutionCount = 0;
+ implicitExecutionCount = 0;
+ }
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/JournalingConnectionObserver.java b/hibernate-core/src/test/java/org/hibernate/test/common/JournalingConnectionObserver.java
new file mode 100644
index 0000000000..d804d8fc68
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/common/JournalingConnectionObserver.java
@@ -0,0 +1,74 @@
+/*
+ * 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.test.common;
+
+import org.hibernate.engine.jdbc.spi.ConnectionObserver;
+
+import java.sql.Connection;
+
+/**
+ * @author Steve Ebersole
+ */
+public class JournalingConnectionObserver implements ConnectionObserver {
+ private int physicalConnectionObtainedCount = 0;
+ private int physicalConnectionReleasedCount = 0;
+ private int logicalConnectionClosedCount = 0;
+ private int statementPreparedCount = 0;
+
+ @Override
+ public void physicalConnectionObtained(Connection connection) {
+ physicalConnectionObtainedCount++;
+ }
+
+ @Override
+ public void physicalConnectionReleased() {
+ physicalConnectionReleasedCount++;
+ }
+
+ @Override
+ public void logicalConnectionClosed() {
+ logicalConnectionClosedCount++;
+ }
+
+ @Override
+ public void statementPrepared() {
+ statementPreparedCount++;
+ }
+
+ public int getPhysicalConnectionObtainedCount() {
+ return physicalConnectionObtainedCount;
+ }
+
+ public int getPhysicalConnectionReleasedCount() {
+ return physicalConnectionReleasedCount;
+ }
+
+ public int getLogicalConnectionClosedCount() {
+ return logicalConnectionClosedCount;
+ }
+
+ public int getStatementPreparedCount() {
+ return statementPreparedCount;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/transaction/WeblogicTransactionManagerLookup.java b/hibernate-core/src/test/java/org/hibernate/test/common/JournalingTransactionObserver.java
similarity index 50%
rename from hibernate-core/src/main/java/org/hibernate/transaction/WeblogicTransactionManagerLookup.java
rename to hibernate-core/src/test/java/org/hibernate/test/common/JournalingTransactionObserver.java
index de500b64ff..68dd256e87 100644
--- a/hibernate-core/src/main/java/org/hibernate/transaction/WeblogicTransactionManagerLookup.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/common/JournalingTransactionObserver.java
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * 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 Middleware LLC.
+ * 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
@@ -20,31 +20,41 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
-package org.hibernate.transaction;
+package org.hibernate.test.common;
+
+import org.hibernate.engine.transaction.spi.TransactionImplementor;
+import org.hibernate.engine.transaction.spi.TransactionObserver;
/**
- * TransactionManager lookup strategy for WebLogic
- * @author Gavin King
- */
-public final class WeblogicTransactionManagerLookup extends JNDITransactionManagerLookup {
+* @author Steve Ebersole
+*/
+public class JournalingTransactionObserver implements TransactionObserver {
+ private int begins = 0;
+ private int beforeCompletions = 0;
+ private int afterCompletions = 0;
- /**
- * @see org.hibernate.transaction.JNDITransactionManagerLookup#getName()
- */
- protected String getName() {
- return "javax.transaction.TransactionManager";
+ public void afterBegin(TransactionImplementor transaction) {
+ begins++;
}
- public String getUserTransactionName() {
- return "javax.transaction.UserTransaction";
+ public void beforeCompletion(TransactionImplementor transaction) {
+ beforeCompletions++;
}
+ public void afterCompletion(boolean successful, TransactionImplementor transaction) {
+ afterCompletions++;
+ }
+
+ public int getBegins() {
+ return begins;
+ }
+
+ public int getBeforeCompletions() {
+ return beforeCompletions;
+ }
+
+ public int getAfterCompletions() {
+ return afterCompletions;
+ }
}
-
-
-
-
-
-
diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/TransactionContextImpl.java b/hibernate-core/src/test/java/org/hibernate/test/common/TransactionContextImpl.java
new file mode 100644
index 0000000000..1557f81995
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/common/TransactionContextImpl.java
@@ -0,0 +1,95 @@
+/*
+ * 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.test.common;
+
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.engine.transaction.spi.TransactionContext;
+import org.hibernate.engine.transaction.spi.TransactionEnvironment;
+import org.hibernate.engine.transaction.spi.TransactionImplementor;
+
+/**
+ * @author Steve Ebersole
+ */
+public class TransactionContextImpl implements TransactionContext {
+ private final TransactionEnvironment transactionEnvironment;
+
+ public TransactionContextImpl(TransactionEnvironment transactionEnvironment) {
+ this.transactionEnvironment = transactionEnvironment;
+ }
+
+ @Override
+ public TransactionEnvironment getTransactionEnvironment() {
+ return transactionEnvironment;
+ }
+
+ @Override
+ public ConnectionReleaseMode getConnectionReleaseMode() {
+ return transactionEnvironment.getTransactionFactory().getDefaultReleaseMode();
+ }
+
+ @Override
+ public boolean isAutoCloseSessionEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean isClosed() {
+ return false;
+ }
+
+ @Override
+ public boolean isFlushModeNever() {
+ return false;
+ }
+
+ @Override
+ public boolean isFlushBeforeCompletionEnabled() {
+ return true;
+ }
+
+ @Override
+ public void managedFlush() {
+ }
+
+ @Override
+ public boolean shouldAutoClose() {
+ return false;
+ }
+
+ @Override
+ public void managedClose() {
+ }
+
+ @Override
+ public void afterTransactionBegin(TransactionImplementor hibernateTransaction) {
+ }
+
+ @Override
+ public void beforeTransactionCompletion(TransactionImplementor hibernateTransaction) {
+ }
+
+ @Override
+ public void afterTransactionCompletion(TransactionImplementor hibernateTransaction, boolean successful) {
+ }
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/TransactionEnvironmentImpl.java b/hibernate-core/src/test/java/org/hibernate/test/common/TransactionEnvironmentImpl.java
new file mode 100644
index 0000000000..82a3b2ba5d
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/common/TransactionEnvironmentImpl.java
@@ -0,0 +1,63 @@
+/*
+ * 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.test.common;
+
+import org.hibernate.cfg.NotYetImplementedException;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.jdbc.spi.JdbcServices;
+import org.hibernate.engine.transaction.spi.TransactionEnvironment;
+import org.hibernate.engine.transaction.spi.TransactionFactory;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.service.spi.ServiceRegistry;
+
+/**
+ * @author Steve Ebersole
+ */
+public class TransactionEnvironmentImpl implements TransactionEnvironment {
+ private final ServiceRegistry serviceRegistry;
+
+ public TransactionEnvironmentImpl(ServiceRegistry serviceRegistry) {
+ this.serviceRegistry = serviceRegistry;
+ }
+
+ @Override
+ public SessionFactoryImplementor getSessionFactory() {
+ throw new NotYetImplementedException( "Not available in this context" );
+ }
+
+ @Override
+ public JdbcServices getJdbcServices() {
+ return serviceRegistry.getService( JdbcServices.class );
+ }
+
+ @Override
+ public JtaPlatform getJtaPlatform() {
+ return serviceRegistry.getService( JtaPlatform.class );
+ }
+
+ @Override
+ public TransactionFactory getTransactionFactory() {
+ return serviceRegistry.getService( TransactionFactory.class );
+ }
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/jta/AtomikosDataSourceConnectionProvider.java b/hibernate-core/src/test/java/org/hibernate/test/common/jta/AtomikosDataSourceConnectionProvider.java
new file mode 100644
index 0000000000..bbb0fcbdda
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/common/jta/AtomikosDataSourceConnectionProvider.java
@@ -0,0 +1,82 @@
+/*
+ * 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.test.common.jta;
+
+import org.hibernate.service.internal.ServiceProxy;
+import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.service.spi.ServiceRegistry;
+import org.hibernate.service.spi.ServiceRegistryAwareService;
+import org.hibernate.service.spi.UnknownUnwrapTypeException;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * @author Steve Ebersole
+ */
+public class AtomikosDataSourceConnectionProvider implements ConnectionProvider, ServiceRegistryAwareService {
+ private DataSource dataSource;
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ return dataSource.getConnection();
+ }
+
+ @Override
+ public void closeConnection(Connection conn) throws SQLException {
+ conn.close();
+ }
+
+ @Override
+ public boolean supportsAggressiveRelease() {
+ return true;
+ }
+
+ @Override
+ public boolean isUnwrappableAs(Class unwrapType) {
+ return ConnectionProvider.class.equals( unwrapType )
+ || unwrapType.isInstance( this )
+ || DataSource.class.isAssignableFrom( unwrapType );
+ }
+
+ @Override
+ @SuppressWarnings( {"unchecked"})
+ public T unwrap(Class unwrapType) {
+ if ( ConnectionProvider.class.equals( unwrapType ) || unwrapType.isInstance( this ) ) {
+ return (T) this;
+ }
+ if ( DataSource.class.isAssignableFrom( unwrapType ) ) {
+ return (T) dataSource;
+ }
+ throw new UnknownUnwrapTypeException( unwrapType );
+ }
+
+ @Override
+ public void injectServices(ServiceRegistry serviceRegistry) {
+ AtomikosJtaPlatform jtaPlatform = (AtomikosJtaPlatform) ( (ServiceProxy) serviceRegistry.getService( JtaPlatform.class ) ).getTargetInstance();
+ dataSource = jtaPlatform.getDataSource();
+ }
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/jta/AtomikosJtaPlatform.java b/hibernate-core/src/test/java/org/hibernate/test/common/jta/AtomikosJtaPlatform.java
new file mode 100644
index 0000000000..9a41bb6752
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/common/jta/AtomikosJtaPlatform.java
@@ -0,0 +1,129 @@
+/*
+ * 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.test.common.jta;
+
+import com.atomikos.icatch.jta.UserTransactionImp;
+import com.atomikos.icatch.jta.UserTransactionManager;
+import com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean;
+
+import org.hibernate.service.internal.ServiceProxy;
+import org.hibernate.service.jta.platform.internal.AbstractJtaPlatform;
+import org.hibernate.service.jta.platform.internal.JtaSynchronizationStrategy;
+import org.hibernate.service.jta.platform.internal.TransactionManagerBasedSynchronizationStrategy;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.service.jta.platform.spi.JtaPlatformException;
+import org.hibernate.service.spi.ServiceRegistry;
+import org.hibernate.service.spi.Startable;
+import org.hibernate.service.spi.Stoppable;
+import org.hibernate.test.common.ConnectionProviderBuilder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.sql.DataSource;
+import javax.transaction.SystemException;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * @author Steve Ebersole
+ */
+public class AtomikosJtaPlatform extends AbstractJtaPlatform implements Startable, Stoppable {
+ private static final Logger log = LoggerFactory.getLogger( AtomikosJtaPlatform.class );
+
+ private final JtaSynchronizationStrategy synchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy( this );
+
+ private UserTransactionManager transactionManager;
+ private AtomikosNonXADataSourceBean dataSourceBean;
+
+ public DataSource getDataSource() {
+ return dataSourceBean;
+ }
+
+ @Override
+ protected TransactionManager locateTransactionManager() {
+ return transactionManager;
+ }
+
+ @Override
+ protected UserTransaction locateUserTransaction() {
+ return new UserTransactionImp();
+ }
+
+ @Override
+ protected JtaSynchronizationStrategy getSynchronizationStrategy() {
+ return synchronizationStrategy;
+ }
+
+ @Override
+ public void start() {
+ if ( transactionManager == null ) {
+ transactionManager = new UserTransactionManager();
+ try {
+ transactionManager.init();
+ }
+ catch (Exception e) {
+ throw new JtaPlatformException( "Unable to init Atomikos UserTransactionManager", e );
+ }
+ }
+
+ if ( dataSourceBean == null ) {
+ // todo : extract sys props to handle functional testing...
+ dataSourceBean = new AtomikosNonXADataSourceBean();
+ dataSourceBean.setUniqueResourceName( "h2" );
+ dataSourceBean.setDriverClassName( ConnectionProviderBuilder.DRIVER );
+ dataSourceBean.setUrl( ConnectionProviderBuilder.URL );
+ dataSourceBean.setUser( ConnectionProviderBuilder.USER );
+ dataSourceBean.setPassword( ConnectionProviderBuilder.PASS );
+ dataSourceBean.setPoolSize( 3 );
+ try {
+ dataSourceBean.init();
+ }
+ catch (Exception e) {
+ throw new JtaPlatformException( "Unable to init Atomikos DataSourceBean", e );
+ }
+ }
+ }
+
+ @Override
+ public void stop() {
+ if ( dataSourceBean != null ) {
+ try {
+ dataSourceBean.close();
+ }
+ catch (Exception e) {
+ log.debug( "Error closing DataSourceBean", e );
+ }
+ }
+
+ if ( transactionManager != null ) {
+ try {
+ transactionManager.close();
+ }
+ catch (Exception e) {
+ log.debug( "Error closing UserTransactionManager", e );
+ }
+ }
+ }
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/connections/AggressiveReleaseTest.java b/hibernate-core/src/test/java/org/hibernate/test/connections/AggressiveReleaseTest.java
index a46f1a10f3..a5bb35f5c1 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/connections/AggressiveReleaseTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/connections/AggressiveReleaseTest.java
@@ -1,11 +1,6 @@
// $Id: AggressiveReleaseTest.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $
package org.hibernate.test.connections;
-import java.sql.Connection;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
import junit.framework.Test;
import org.hibernate.ConnectionReleaseMode;
@@ -14,14 +9,21 @@ import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
+import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
import org.hibernate.impl.SessionImpl;
+import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.test.common.jta.AtomikosDataSourceConnectionProvider;
+import org.hibernate.test.common.jta.AtomikosJtaPlatform;
import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
-import org.hibernate.testing.tm.ConnectionProviderImpl;
-import org.hibernate.testing.tm.SimpleJtaTransactionManagerImpl;
-import org.hibernate.testing.tm.TransactionManagerLookupImpl;
-import org.hibernate.transaction.CMTTransactionFactory;
import org.hibernate.util.SerializationHelper;
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
/**
* Implementation of AggressiveReleaseTest.
*
@@ -39,8 +41,8 @@ public class AggressiveReleaseTest extends ConnectionManagementTestCase {
public void configure(Configuration cfg) {
super.configure( cfg );
- cfg.setProperty( Environment.CONNECTION_PROVIDER, ConnectionProviderImpl.class.getName() );
- cfg.setProperty( Environment.TRANSACTION_MANAGER_STRATEGY, TransactionManagerLookupImpl.class.getName() );
+ cfg.getProperties().put( JtaPlatformInitiator.JTA_PLATFORM, AtomikosJtaPlatform.class.getName() );
+ cfg.getProperties().put( Environment.CONNECTION_PROVIDER, AtomikosDataSourceConnectionProvider.class.getName() );
cfg.setProperty( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class.getName() );
cfg.setProperty( Environment.RELEASE_CONNECTIONS, ConnectionReleaseMode.AFTER_STATEMENT.toString() );
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
@@ -56,32 +58,36 @@ public class AggressiveReleaseTest extends ConnectionManagementTestCase {
}
protected void prepare() throws Throwable {
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
}
protected void done() throws Throwable {
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
}
// Some additional tests specifically for the aggressive-release functionality...
public void testSerializationOnAfterStatementAggressiveRelease() throws Throwable {
prepare();
- Session s = getSessionUnderTest();
- Silly silly = new Silly( "silly" );
- s.save( silly );
+ try {
+ Session s = getSessionUnderTest();
+ Silly silly = new Silly( "silly" );
+ s.save( silly );
- // this should cause the CM to obtain a connection, and then release it
- s.flush();
+ // this should cause the CM to obtain a connection, and then release it
+ s.flush();
- // We should be able to serialize the session at this point...
- SerializationHelper.serialize( s );
+ // We should be able to serialize the session at this point...
+ SerializationHelper.serialize( s );
- s.delete( silly );
- s.flush();
+ s.delete( silly );
+ s.flush();
- release( s );
- done();
+ release( s );
+ }
+ finally {
+ done();
+ }
}
public void testSerializationFailsOnAfterStatementAggressiveReleaseWithOpenResources() throws Throwable {
@@ -188,7 +194,7 @@ public class AggressiveReleaseTest extends ConnectionManagementTestCase {
public void testSuppliedConnection() throws Throwable {
prepare();
- Connection originalConnection = ConnectionProviderImpl.getActualConnectionProvider().getConnection();
+ Connection originalConnection = sfi().getServiceRegistry().getService( ConnectionProvider.class ).getConnection();
Session session = getSessions().openSession( originalConnection );
Silly silly = new Silly( "silly" );
@@ -197,8 +203,7 @@ public class AggressiveReleaseTest extends ConnectionManagementTestCase {
// this will cause the connection manager to cycle through the aggressive release logic;
// it should not release the connection since we explicitly suplied it ourselves.
session.flush();
-
- assertTrue( "Different connections", originalConnection == session.connection() );
+ assertTrue( session.isConnected() );
session.delete( silly );
session.flush();
@@ -206,17 +211,33 @@ public class AggressiveReleaseTest extends ConnectionManagementTestCase {
release( session );
done();
- ConnectionProviderImpl.getActualConnectionProvider().closeConnection( originalConnection );
+ sfi().getServiceRegistry().getService( ConnectionProvider.class ).closeConnection( originalConnection );
}
public void testBorrowedConnections() throws Throwable {
prepare();
Session s = getSessionUnderTest();
+ // todo : may need to come back here and make sure that closing the connection handles do not close the physical cached connection on LogicalConnection...
+
Connection conn = s.connection();
- assertTrue( ( ( SessionImpl ) s ).getJDBCContext().getConnectionManager().hasBorrowedConnection() );
+ assertFalse( conn.isClosed() );
+ assertFalse(
+ ((SessionImpl) s).getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getLogicalConnection()
+ .isPhysicallyConnected()
+ );
+ conn.getCatalog();
+ assertTrue(
+ ((SessionImpl) s).getTransactionCoordinator()
+ .getJdbcCoordinator()
+ .getLogicalConnection()
+ .isPhysicallyConnected()
+ );
conn.close();
- assertFalse( ( ( SessionImpl ) s ).getJDBCContext().getConnectionManager().hasBorrowedConnection() );
+ assertTrue( conn.isClosed() );
+ assertTrue( ( ( SessionImpl ) s ).getTransactionCoordinator().getJdbcCoordinator().getLogicalConnection().isPhysicallyConnected() );
release( s );
done();
diff --git a/hibernate-core/src/test/java/org/hibernate/test/connections/CurrentSessionConnectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/connections/CurrentSessionConnectionTest.java
index c570ad657f..de6adf5511 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/connections/CurrentSessionConnectionTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/connections/CurrentSessionConnectionTest.java
@@ -28,4 +28,9 @@ public class CurrentSessionConnectionTest extends AggressiveReleaseTest {
protected void release(Session session) {
// do nothing, txn synch should release session as part of current-session definition
}
+
+ @Override
+ public void testSerializationOnAfterStatementAggressiveRelease() throws Throwable {
+ super.testSerializationOnAfterStatementAggressiveRelease();
+ }
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/exception/SQLExceptionConversionTest.java b/hibernate-core/src/test/java/org/hibernate/test/exception/SQLExceptionConversionTest.java
index 5fd330f94e..be245432a0 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/exception/SQLExceptionConversionTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/exception/SQLExceptionConversionTest.java
@@ -59,12 +59,7 @@ public class SQLExceptionConversionTest extends FunctionalTestCase {
fail("INSERT should have failed");
}
- catch(SQLException sqle) {
- JDBCExceptionReporter.logExceptions(sqle, "Just output!!!!");
- JDBCException jdbcException = converter.convert(sqle, null, null);
- assertEquals( "Bad conversion [" + sqle.getMessage() + "]", ConstraintViolationException.class , jdbcException.getClass() );
- ConstraintViolationException ex = (ConstraintViolationException) jdbcException;
- System.out.println("Violated constraint name: " + ex.getConstraintName());
+ catch (ConstraintViolationException expected) {
}
finally {
if ( ps != null ) {
@@ -95,8 +90,7 @@ public class SQLExceptionConversionTest extends FunctionalTestCase {
fail("SQL compilation should have failed");
}
- catch( SQLException sqle ) {
- assertEquals( "Bad conversion [" + sqle.getMessage() + "]", SQLGrammarException.class, converter.convert(sqle, null, null).getClass() );
+ catch (SQLGrammarException expected) {
}
finally {
if ( ps != null ) {
diff --git a/hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingTest.java b/hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingTest.java
index 4df42c0a47..b5130784eb 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingTest.java
@@ -1,27 +1,26 @@
package org.hibernate.test.insertordering;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.sql.PreparedStatement;
-
import junit.framework.Test;
-import org.hibernate.engine.jdbc.batch.internal.BatchBuilder;
-import org.hibernate.engine.jdbc.batch.internal.BatchingBatch;
-import org.hibernate.engine.jdbc.batch.spi.Batch;
-import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
-import org.hibernate.engine.jdbc.spi.SQLStatementLogger;
-import org.hibernate.testing.junit.functional.FunctionalTestCase;
-import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
-import org.hibernate.Session;
-import org.hibernate.jdbc.Expectation;
+import org.hibernate.engine.jdbc.batch.internal.BatchBuilderImpl;
+import org.hibernate.engine.jdbc.batch.internal.BatchBuilderInitiator;
+import org.hibernate.engine.jdbc.batch.internal.BatchingBatch;
+import org.hibernate.engine.jdbc.batch.spi.Batch;
+import org.hibernate.engine.jdbc.batch.spi.BatchKey;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.test.common.JournalingBatchObserver;
+import org.hibernate.testing.junit.functional.FunctionalTestCase;
+import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
+
+import java.sql.PreparedStatement;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
/**
- * {@inheritDoc}
- *
* @author Steve Ebersole
*/
public class InsertOrderingTest extends FunctionalTestCase {
@@ -41,7 +40,7 @@ public class InsertOrderingTest extends FunctionalTestCase {
super.configure( cfg );
cfg.setProperty( Environment.ORDER_INSERTS, "true" );
cfg.setProperty( Environment.STATEMENT_BATCH_SIZE, "10" );
- cfg.setProperty( Environment.BATCH_STRATEGY, StatsBatchBuilder.class.getName() );
+ cfg.setProperty( BatchBuilderInitiator.BUILDER, StatsBatchBuilder.class.getName() );
}
public void testBatchOrdering() {
@@ -80,8 +79,8 @@ public class InsertOrderingTest extends FunctionalTestCase {
private static List batchSizes = new ArrayList();
private static int currentBatch = -1;
- public StatsBatch(Object key, SQLStatementLogger statementLogger, SQLExceptionHelper exceptionHelper, int jdbcBatchSize) {
- super( key, statementLogger, exceptionHelper, jdbcBatchSize );
+ public StatsBatch(BatchKey key, JdbcCoordinator jdbcCoordinator, int jdbcBatchSize) {
+ super( key, jdbcCoordinator, jdbcBatchSize );
}
static void reset() {
@@ -90,39 +89,34 @@ public class InsertOrderingTest extends FunctionalTestCase {
batchSQL = null;
}
- public void addBatchStatement(Object key, String sql, PreparedStatement ps) {
+ @Override
+ public PreparedStatement getBatchStatement(String sql, boolean callable) {
if ( batchSQL == null || ! batchSQL.equals( sql ) ) {
currentBatch++;
batchSQL = sql;
batchSizes.add( currentBatch, new Counter() );
- System.out.println( "--------------------------------------------------------" );
- System.out.println( "Preparing statement [" + sql + "]" );
}
- super.addBatchStatement( key, sql, ps );
+ return super.getBatchStatement( sql, callable );
}
- public void addToBatch(Object key, String sql, Expectation expectation) {
+ @Override
+ public void addToBatch() {
Counter counter = ( Counter ) batchSizes.get( currentBatch );
counter.count++;
- System.out.println( "Adding to batch [" + batchSQL + "]" );
- super.addToBatch( key, sql, expectation );
- }
-
- protected void doExecuteBatch() {
- System.out.println( "executing batch [" + batchSQL + "]" );
- System.out.println( "--------------------------------------------------------" );
- super.doExecuteBatch();
+ super.addToBatch();
}
}
- public static class StatsBatchBuilder extends BatchBuilder {
+ public static class StatsBatchBuilder extends BatchBuilderImpl {
private int jdbcBatchSize;
public void setJdbcBatchSize(int jdbcBatchSize) {
this.jdbcBatchSize = jdbcBatchSize;
}
- public Batch buildBatch(Object key, SQLStatementLogger statementLogger, SQLExceptionHelper exceptionHelper) {
- return new StatsBatch(key, statementLogger, exceptionHelper, jdbcBatchSize );
+
+ @Override
+ public Batch buildBatch(BatchKey key, JdbcCoordinator jdbcCoordinator) {
+ return new StatsBatch( key, jdbcCoordinator, jdbcBatchSize );
}
}
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/AggressiveReleaseTest.java b/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/AggressiveReleaseTest.java
index e32122b4ed..1acde23ec7 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/AggressiveReleaseTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/AggressiveReleaseTest.java
@@ -23,21 +23,20 @@
*/
package org.hibernate.test.jdbc.proxies;
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
+import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
+import org.hibernate.test.common.BasicTestingJdbcServiceImpl;
+import org.hibernate.test.common.JournalingConnectionObserver;
+import org.hibernate.testing.junit.UnitTestCase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.ConnectionReleaseMode;
-import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
-import org.hibernate.engine.jdbc.spi.ConnectionObserver;
-import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
-import org.hibernate.test.common.BasicTestingJdbcServiceImpl;
-import org.hibernate.testing.junit.UnitTestCase;
-
/**
* TODO : javadoc
*
@@ -48,22 +47,6 @@ public class AggressiveReleaseTest extends UnitTestCase {
private static final Logger log = LoggerFactory.getLogger( AggressiveReleaseTest.class );
private BasicTestingJdbcServiceImpl services = new BasicTestingJdbcServiceImpl();
- private static class ConnectionCounter implements ConnectionObserver {
- public int obtainCount = 0;
- public int releaseCount = 0;
-
- public void physicalConnectionObtained(Connection connection) {
- obtainCount++;
- }
-
- public void physicalConnectionReleased() {
- releaseCount++;
- }
-
- public void logicalConnectionClosed() {
- }
- }
-
public AggressiveReleaseTest(String string) {
super( string );
}
@@ -130,14 +113,9 @@ public class AggressiveReleaseTest extends UnitTestCase {
}
public void testBasicRelease() {
- LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
- null,
- ConnectionReleaseMode.AFTER_STATEMENT,
- services,
- null
- );
+ LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services );
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
- ConnectionCounter observer = new ConnectionCounter();
+ JournalingConnectionObserver observer = new JournalingConnectionObserver();
logicalConnection.addObserver( observer );
try {
@@ -146,12 +124,12 @@ public class AggressiveReleaseTest extends UnitTestCase {
ps.setString( 2, "name" );
ps.execute();
assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 1, observer.obtainCount );
- assertEquals( 0, observer.releaseCount );
+ assertEquals( 1, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 0, observer.getPhysicalConnectionReleasedCount() );
ps.close();
assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 1, observer.obtainCount );
- assertEquals( 1, observer.releaseCount );
+ assertEquals( 1, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 1, observer.getPhysicalConnectionReleasedCount() );
}
catch ( SQLException sqle ) {
fail( "incorrect exception type : sqlexception" );
@@ -164,14 +142,9 @@ public class AggressiveReleaseTest extends UnitTestCase {
}
public void testReleaseCircumventedByHeldResources() {
- LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
- null,
- ConnectionReleaseMode.AFTER_STATEMENT,
- services,
- null
- );
+ LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services );
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
- ConnectionCounter observer = new ConnectionCounter();
+ JournalingConnectionObserver observer = new JournalingConnectionObserver();
logicalConnection.addObserver( observer );
try {
@@ -180,33 +153,32 @@ public class AggressiveReleaseTest extends UnitTestCase {
ps.setString( 2, "name" );
ps.execute();
assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 1, observer.obtainCount );
- assertEquals( 0, observer.releaseCount );
+ assertEquals( 1, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 0, observer.getPhysicalConnectionReleasedCount() );
ps.close();
assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 1, observer.obtainCount );
- assertEquals( 1, observer.releaseCount );
+ assertEquals( 1, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 1, observer.getPhysicalConnectionReleasedCount() );
// open a result set and hold it open...
ps = proxiedConnection.prepareStatement( "select * from SANDBOX_JDBC_TST" );
ps.executeQuery();
assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 2, observer.obtainCount );
- assertEquals( 1, observer.releaseCount );
+ assertEquals( 2, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 1, observer.getPhysicalConnectionReleasedCount() );
// open a second result set
PreparedStatement ps2 = proxiedConnection.prepareStatement( "select * from SANDBOX_JDBC_TST" );
ps2.execute();
assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 2, observer.obtainCount );
- assertEquals( 1, observer.releaseCount );
+ assertEquals( 2, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 1, observer.getPhysicalConnectionReleasedCount() );
// and close it...
ps2.close();
// the release should be circumvented...
assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 2, observer.obtainCount );
- assertEquals( 1, observer.releaseCount );
+ assertEquals( 2, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 1, observer.getPhysicalConnectionReleasedCount() );
// let the close of the logical connection below release all resources (hopefully)...
}
@@ -218,19 +190,14 @@ public class AggressiveReleaseTest extends UnitTestCase {
}
assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 2, observer.obtainCount );
- assertEquals( 2, observer.releaseCount );
+ assertEquals( 2, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 2, observer.getPhysicalConnectionReleasedCount() );
}
public void testReleaseCircumventedManually() {
- LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
- null,
- ConnectionReleaseMode.AFTER_STATEMENT,
- services,
- null
- );
+ LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services );
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
- ConnectionCounter observer = new ConnectionCounter();
+ JournalingConnectionObserver observer = new JournalingConnectionObserver();
logicalConnection.addObserver( observer );
try {
@@ -239,12 +206,12 @@ public class AggressiveReleaseTest extends UnitTestCase {
ps.setString( 2, "name" );
ps.execute();
assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 1, observer.obtainCount );
- assertEquals( 0, observer.releaseCount );
+ assertEquals( 1, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 0, observer.getPhysicalConnectionReleasedCount() );
ps.close();
assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 1, observer.obtainCount );
- assertEquals( 1, observer.releaseCount );
+ assertEquals( 1, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 1, observer.getPhysicalConnectionReleasedCount() );
// disable releases...
logicalConnection.disableReleases();
@@ -253,14 +220,14 @@ public class AggressiveReleaseTest extends UnitTestCase {
ps = proxiedConnection.prepareStatement( "select * from SANDBOX_JDBC_TST" );
ps.executeQuery();
assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 2, observer.obtainCount );
- assertEquals( 1, observer.releaseCount );
+ assertEquals( 2, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 1, observer.getPhysicalConnectionReleasedCount() );
// and close it...
ps.close();
// the release should be circumvented...
assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 2, observer.obtainCount );
- assertEquals( 1, observer.releaseCount );
+ assertEquals( 2, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 1, observer.getPhysicalConnectionReleasedCount() );
// let the close of the logical connection below release all resources (hopefully)...
}
@@ -272,7 +239,7 @@ public class AggressiveReleaseTest extends UnitTestCase {
}
assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
- assertEquals( 2, observer.obtainCount );
- assertEquals( 2, observer.releaseCount );
+ assertEquals( 2, observer.getPhysicalConnectionObtainedCount() );
+ assertEquals( 2, observer.getPhysicalConnectionReleasedCount() );
}
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/BasicConnectionProxyTest.java b/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/BasicConnectionProxyTest.java
index 8107c1ea0b..30ba84c132 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/BasicConnectionProxyTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/BasicConnectionProxyTest.java
@@ -61,8 +61,7 @@ public class BasicConnectionProxyTest extends UnitTestCase {
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
null,
ConnectionReleaseMode.AFTER_TRANSACTION,
- services,
- null
+ services
);
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
try {
@@ -89,8 +88,7 @@ public class BasicConnectionProxyTest extends UnitTestCase {
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
null,
ConnectionReleaseMode.AFTER_TRANSACTION,
- services,
- null
+ services
);
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
try {
@@ -111,8 +109,7 @@ public class BasicConnectionProxyTest extends UnitTestCase {
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
null,
ConnectionReleaseMode.AFTER_TRANSACTION,
- services,
- null
+ services
);
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
diff --git a/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/BatchingTest.java b/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/BatchingTest.java
new file mode 100644
index 0000000000..9fee757052
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/BatchingTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.test.jdbc.proxies;
+
+import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
+import org.hibernate.engine.jdbc.batch.internal.BatchBuilderImpl;
+import org.hibernate.engine.jdbc.batch.internal.BatchingBatch;
+import org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch;
+import org.hibernate.engine.jdbc.batch.spi.Batch;
+import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
+import org.hibernate.engine.jdbc.batch.spi.BatchKey;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
+import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl;
+import org.hibernate.engine.transaction.spi.TransactionContext;
+import org.hibernate.engine.transaction.spi.TransactionImplementor;
+import org.hibernate.jdbc.Expectation;
+import org.hibernate.jdbc.Expectations;
+import org.hibernate.service.internal.ServiceRegistryImpl;
+import org.hibernate.service.spi.ServiceRegistry;
+import org.hibernate.service.spi.StandardServiceInitiators;
+import org.hibernate.test.common.ConnectionProviderBuilder;
+import org.hibernate.test.common.JournalingBatchObserver;
+import org.hibernate.test.common.JournalingTransactionObserver;
+import org.hibernate.test.common.TransactionContextImpl;
+import org.hibernate.test.common.TransactionEnvironmentImpl;
+import org.hibernate.testing.junit.UnitTestCase;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+
+/**
+ * @author Steve Ebersole
+ */
+public class BatchingTest extends UnitTestCase implements BatchKey {
+ private ServiceRegistry serviceRegistry;
+
+ public BatchingTest(String string) {
+ super( string );
+ }
+
+ public void setUp() throws Exception {
+ super.setUp();
+ serviceRegistry = new ServiceRegistryImpl(
+ StandardServiceInitiators.LIST,
+ ConnectionProviderBuilder.getConnectionProviderProperties()
+ );
+ }
+
+ public void tearDown() throws Exception {
+ ( (ServiceRegistryImpl) serviceRegistry).destroy();
+ super.tearDown();
+ }
+
+ @Override
+ public int getBatchedStatementCount() {
+ return 1;
+ }
+
+ @Override
+ public Expectation getExpectation() {
+ return Expectations.BASIC;
+ }
+
+ public void testNonBatchingUsage() throws Exception {
+ final TransactionContext transactionContext = new TransactionContextImpl( new TransactionEnvironmentImpl( serviceRegistry ) );
+
+ TransactionCoordinatorImpl transactionCoordinator = new TransactionCoordinatorImpl( null, transactionContext );
+ JournalingTransactionObserver observer = new JournalingTransactionObserver();
+ transactionCoordinator.addObserver( observer );
+
+ final JdbcCoordinator jdbcCoordinator = transactionCoordinator.getJdbcCoordinator();
+ LogicalConnectionImplementor logicalConnection = jdbcCoordinator.getLogicalConnection();
+ Connection connection = logicalConnection.getShareableConnectionProxy();
+
+ // set up some tables to use
+ Statement statement = connection.createStatement();
+ statement.execute( "drop table SANDBOX_JDBC_TST if exists" );
+ statement.execute( "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" );
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() );
+ statement.close();
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() ); // after_transaction specified
+
+ // ok, now we can get down to it...
+ TransactionImplementor txn = transactionCoordinator.getTransaction(); // same as Session#getTransaction
+ txn.begin();
+ assertEquals( 1, observer.getBegins() );
+
+ final String insertSql = "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )";
+
+ final BatchBuilder batchBuilder = new BatchBuilderImpl( -1 );
+ final BatchKey batchKey = new BasicBatchKey( "this", Expectations.BASIC );
+ final Batch insertBatch = batchBuilder.buildBatch( batchKey, jdbcCoordinator );
+
+ final JournalingBatchObserver batchObserver = new JournalingBatchObserver();
+ insertBatch.addObserver( batchObserver );
+
+ assertTrue( "unexpected Batch impl", NonBatchingBatch.class.isInstance( insertBatch ) );
+ PreparedStatement insert = insertBatch.getBatchStatement( insertSql, false );
+ insert.setLong( 1, 1 );
+ insert.setString( 2, "name" );
+ assertEquals( 0, batchObserver.getExplicitExecutionCount() );
+ assertEquals( 0, batchObserver.getImplicitExecutionCount() );
+ insertBatch.addToBatch();
+ assertEquals( 0, batchObserver.getExplicitExecutionCount() );
+ assertEquals( 1, batchObserver.getImplicitExecutionCount() );
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+
+ insertBatch.execute();
+ assertEquals( 1, batchObserver.getExplicitExecutionCount() );
+ assertEquals( 1, batchObserver.getImplicitExecutionCount() );
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+
+ insertBatch.release();
+
+ txn.commit();
+ logicalConnection.close();
+ }
+
+ public void testBatchingUsage() throws Exception {
+ final TransactionContext transactionContext = new TransactionContextImpl( new TransactionEnvironmentImpl( serviceRegistry ) );
+
+ TransactionCoordinatorImpl transactionCoordinator = new TransactionCoordinatorImpl( null, transactionContext );
+ JournalingTransactionObserver transactionObserver = new JournalingTransactionObserver();
+ transactionCoordinator.addObserver( transactionObserver );
+
+ final JdbcCoordinator jdbcCoordinator = transactionCoordinator.getJdbcCoordinator();
+ LogicalConnectionImplementor logicalConnection = jdbcCoordinator.getLogicalConnection();
+ Connection connection = logicalConnection.getShareableConnectionProxy();
+
+ // set up some tables to use
+ Statement statement = connection.createStatement();
+ statement.execute( "drop table SANDBOX_JDBC_TST if exists" );
+ statement.execute( "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" );
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() );
+ statement.close();
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() ); // after_transaction specified
+
+ // ok, now we can get down to it...
+ TransactionImplementor txn = transactionCoordinator.getTransaction(); // same as Session#getTransaction
+ txn.begin();
+ assertEquals( 1, transactionObserver.getBegins() );
+
+ final BatchBuilder batchBuilder = new BatchBuilderImpl( 2 );
+ final BatchKey batchKey = new BasicBatchKey( "this", Expectations.BASIC );
+ final Batch insertBatch = batchBuilder.buildBatch( batchKey, jdbcCoordinator );
+ assertTrue( "unexpected Batch impl", BatchingBatch.class.isInstance( insertBatch ) );
+
+ final JournalingBatchObserver batchObserver = new JournalingBatchObserver();
+ insertBatch.addObserver( batchObserver );
+
+ final String insertSql = "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )";
+
+ PreparedStatement insert = insertBatch.getBatchStatement( insertSql, false );
+ insert.setLong( 1, 1 );
+ insert.setString( 2, "name" );
+ assertEquals( 0, batchObserver.getExplicitExecutionCount() );
+ assertEquals( 0, batchObserver.getImplicitExecutionCount() );
+ insertBatch.addToBatch();
+ assertEquals( 0, batchObserver.getExplicitExecutionCount() );
+ assertEquals( 0, batchObserver.getImplicitExecutionCount() );
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+
+ PreparedStatement insert2 = insertBatch.getBatchStatement( insertSql, false );
+ assertSame( insert, insert2 );
+ insert = insert2;
+ insert.setLong( 1, 2 );
+ insert.setString( 2, "another name" );
+ assertEquals( 0, batchObserver.getExplicitExecutionCount() );
+ assertEquals( 0, batchObserver.getImplicitExecutionCount() );
+ insertBatch.addToBatch();
+ assertEquals( 0, batchObserver.getExplicitExecutionCount() );
+ assertEquals( 1, batchObserver.getImplicitExecutionCount() );
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+
+ insertBatch.execute();
+ assertEquals( 1, batchObserver.getExplicitExecutionCount() );
+ assertEquals( 1, batchObserver.getImplicitExecutionCount() );
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+
+ insertBatch.release();
+
+ txn.commit();
+ logicalConnection.close();
+ }
+
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomany/batchload/BatchedManyToManyTest.java b/hibernate-core/src/test/java/org/hibernate/test/manytomany/batchload/BatchedManyToManyTest.java
index ca66ad9aa1..1ce6885626 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/manytomany/batchload/BatchedManyToManyTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/manytomany/batchload/BatchedManyToManyTest.java
@@ -21,27 +21,28 @@
*/
package org.hibernate.test.manytomany.batchload;
-import java.util.List;
-
-import junit.framework.Test;
import junit.framework.Assert;
+import junit.framework.Test;
-import org.hibernate.engine.jdbc.batch.internal.BatchBuilder;
-import org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch;
-import org.hibernate.engine.jdbc.batch.spi.Batch;
-import org.hibernate.engine.jdbc.spi.SQLExceptionHelper;
-import org.hibernate.engine.jdbc.spi.SQLStatementLogger;
-import org.hibernate.testing.junit.functional.FunctionalTestCase;
-import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
-import org.hibernate.cfg.Configuration;
-import org.hibernate.cfg.Environment;
-import org.hibernate.Session;
+import org.hibernate.EmptyInterceptor;
import org.hibernate.Hibernate;
import org.hibernate.Interceptor;
-import org.hibernate.EmptyInterceptor;
-import org.hibernate.stat.CollectionStatistics;
+import org.hibernate.Session;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.engine.jdbc.batch.internal.BatchBuilderImpl;
+import org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch;
+import org.hibernate.engine.jdbc.batch.spi.Batch;
+import org.hibernate.engine.jdbc.batch.spi.BatchKey;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.loader.collection.BatchingCollectionInitializer;
import org.hibernate.persister.collection.AbstractCollectionPersister;
+import org.hibernate.stat.CollectionStatistics;
+import org.hibernate.testing.junit.functional.FunctionalTestCase;
+import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
+
+import java.util.List;
/**
* Tests loading of many-to-many collection which should trigger
@@ -68,20 +69,16 @@ public class BatchedManyToManyTest extends FunctionalTestCase {
cfg.setProperty( Environment.BATCH_STRATEGY, TestingBatchBuilder.class.getName() );
}
- public static class TestingBatchBuilder extends BatchBuilder {
- private int jdbcBatchSize;
-
- public void setJdbcBatchSize(int jdbcBatchSize) {
- this.jdbcBatchSize = jdbcBatchSize;
- }
- public Batch buildBatch(Object key, SQLStatementLogger statementLogger, SQLExceptionHelper exceptionHelper) {
- return new TestingBatch(key, statementLogger, exceptionHelper, jdbcBatchSize );
+ public static class TestingBatchBuilder extends BatchBuilderImpl {
+ @Override
+ public Batch buildBatch(BatchKey key, JdbcCoordinator jdbcCoordinator) {
+ return new TestingBatch( key, jdbcCoordinator );
}
}
public static class TestingBatch extends NonBatchingBatch {
- public TestingBatch(Object key, SQLStatementLogger statementLogger, SQLExceptionHelper exceptionHelper, int jdbcBatchSize) {
- super( key, statementLogger, exceptionHelper );
+ public TestingBatch(BatchKey key, JdbcCoordinator jdbcCoordinator) {
+ super( key, jdbcCoordinator );
}
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/nonflushedchanges/AbstractOperationTestCase.java b/hibernate-core/src/test/java/org/hibernate/test/nonflushedchanges/AbstractOperationTestCase.java
index 03bb8d760f..ffef92bea2 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/nonflushedchanges/AbstractOperationTestCase.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/nonflushedchanges/AbstractOperationTestCase.java
@@ -13,10 +13,10 @@ import org.hibernate.engine.EntityKey;
import org.hibernate.engine.NonFlushedChanges;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.StatefulPersistenceContext;
+import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
import org.hibernate.testing.tm.ConnectionProviderImpl;
import org.hibernate.testing.tm.TransactionManagerLookupImpl;
-import org.hibernate.transaction.CMTTransactionFactory;
import org.hibernate.util.SerializationHelper;
/**
diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/CreateTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/CreateTest.java
index 1f46942b64..7e1ca35733 100755
--- a/hibernate-core/src/test/java/org/hibernate/test/ops/CreateTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/ops/CreateTest.java
@@ -124,7 +124,7 @@ public class CreateTest extends AbstractOperationTestCase {
s.persist(dupe);
try {
tx.commit();
- assertFalse(true);
+ fail( "Expecting constraint failure" );
}
catch (ConstraintViolationException cve) {
//verify that an exception is thrown!
diff --git a/hibernate-core/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java b/hibernate-core/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java
index 22e1b7a527..e2cba3b811 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java
@@ -1495,7 +1495,6 @@ public class ReadOnlyProxyTest extends AbstractReadOnlyTest {
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
}
finally {
- s.beginTransaction();
s.delete( dp );
s.getTransaction().commit();
s.close();
@@ -1654,7 +1653,6 @@ public class ReadOnlyProxyTest extends AbstractReadOnlyTest {
assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
}
finally {
- s.beginTransaction();
s.delete( dp );
s.getTransaction().commit();
s.close();
diff --git a/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java b/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java
index ee4c15e577..67c52d680e 100755
--- a/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java
@@ -1,12 +1,6 @@
//$Id: CMTTest.java 11303 2007-03-19 22:06:14Z steve.ebersole@jboss.com $
package org.hibernate.test.tm;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import javax.transaction.Transaction;
-
import junit.framework.Test;
import org.hibernate.ConnectionReleaseMode;
@@ -16,14 +10,21 @@ import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.criterion.Order;
+import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
+import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.test.common.jta.AtomikosDataSourceConnectionProvider;
+import org.hibernate.test.common.jta.AtomikosJtaPlatform;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
-import org.hibernate.testing.tm.ConnectionProviderImpl;
-import org.hibernate.testing.tm.SimpleJtaTransactionManagerImpl;
-import org.hibernate.testing.tm.TransactionManagerLookupImpl;
-import org.hibernate.transaction.CMTTransactionFactory;
import org.hibernate.util.SerializationHelper;
+import javax.transaction.Transaction;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
/**
* @author Gavin King
*/
@@ -38,8 +39,8 @@ public class CMTTest extends FunctionalTestCase {
}
public void configure(Configuration cfg) {
- cfg.setProperty( Environment.CONNECTION_PROVIDER, ConnectionProviderImpl.class.getName() );
- cfg.setProperty( Environment.TRANSACTION_MANAGER_STRATEGY, TransactionManagerLookupImpl.class.getName() );
+ cfg.getProperties().put( JtaPlatformInitiator.JTA_PLATFORM, AtomikosJtaPlatform.class.getName() );
+ cfg.getProperties().put( Environment.CONNECTION_PROVIDER, AtomikosDataSourceConnectionProvider.class.getName() );
cfg.setProperty( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class.getName() );
cfg.setProperty( Environment.AUTO_CLOSE_SESSION, "true" );
cfg.setProperty( Environment.FLUSH_BEFORE_COMPLETION, "true" );
@@ -62,7 +63,7 @@ public class CMTTest extends FunctionalTestCase {
assertNotNull( sfi().getEntityPersister( "Item" ).getCacheAccessStrategy() );
assertEquals( 0, getSessions().getStatistics().getEntityLoadCount() );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s = openSession();
Map foo = new HashMap();
foo.put( "name", "Foo" );
@@ -72,46 +73,46 @@ public class CMTTest extends FunctionalTestCase {
bar.put( "name", "Bar" );
bar.put( "description", "a small bar" );
s.persist( "Item", bar );
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
getSessions().evictEntity( "Item" );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s1 = openSession();
foo = ( Map ) s1.get( "Item", "Foo" );
//foo.put("description", "a big red foo");
//s1.flush();
- Transaction tx1 = SimpleJtaTransactionManagerImpl.getInstance().suspend();
+ Transaction tx1 = sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().suspend();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s2 = openSession();
foo = ( Map ) s2.get( "Item", "Foo" );
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
- SimpleJtaTransactionManagerImpl.getInstance().resume( tx1 );
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().resume( tx1 );
tx1.commit();
getSessions().evictEntity( "Item" );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s1 = openSession();
s1.createCriteria( "Item" ).list();
//foo.put("description", "a big red foo");
//s1.flush();
- tx1 = SimpleJtaTransactionManagerImpl.getInstance().suspend();
+ tx1 = sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().suspend();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s2 = openSession();
s2.createCriteria( "Item" ).list();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
- SimpleJtaTransactionManagerImpl.getInstance().resume( tx1 );
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().resume( tx1 );
tx1.commit();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s2 = openSession();
s2.createCriteria( "Item" ).list();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
assertEquals( 7, getSessions().getStatistics().getEntityLoadCount() );
assertEquals( 0, getSessions().getStatistics().getEntityFetchCount() );
@@ -119,15 +120,15 @@ public class CMTTest extends FunctionalTestCase {
assertEquals( 0, getSessions().getStatistics().getQueryCacheHitCount() );
assertEquals( 0, getSessions().getStatistics().getQueryCacheMissCount() );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = openSession();
s.createQuery( "delete from Item" ).executeUpdate();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
}
public void testConcurrentCachedQueries() throws Exception {
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s = openSession();
Map foo = new HashMap();
foo.put( "name", "Foo" );
@@ -137,7 +138,7 @@ public class CMTTest extends FunctionalTestCase {
bar.put( "name", "Bar" );
bar.put( "description", "a small bar" );
s.persist( "Item", bar );
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
synchronized ( this ) {
wait( 1000 );
@@ -147,23 +148,23 @@ public class CMTTest extends FunctionalTestCase {
getSessions().evictEntity( "Item" );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s4 = openSession();
- Transaction tx4 = SimpleJtaTransactionManagerImpl.getInstance().suspend();
+ Transaction tx4 = sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().suspend();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s1 = openSession();
List r1 = s1.createCriteria( "Item" ).addOrder( Order.asc( "description" ) )
.setCacheable( true ).list();
assertEquals( r1.size(), 2 );
- Transaction tx1 = SimpleJtaTransactionManagerImpl.getInstance().suspend();
+ Transaction tx1 = sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().suspend();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s2 = openSession();
List r2 = s2.createCriteria( "Item" ).addOrder( Order.asc( "description" ) )
.setCacheable( true ).list();
assertEquals( r2.size(), 2 );
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
assertEquals( getSessions().getStatistics().getSecondLevelCacheHitCount(), 2 );
assertEquals( getSessions().getStatistics().getSecondLevelCacheMissCount(), 0 );
@@ -174,14 +175,14 @@ public class CMTTest extends FunctionalTestCase {
assertEquals( getSessions().getStatistics().getQueryCacheHitCount(), 1 );
assertEquals( getSessions().getStatistics().getQueryCacheMissCount(), 1 );
- SimpleJtaTransactionManagerImpl.getInstance().resume( tx1 );
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().resume( tx1 );
tx1.commit();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s3 = openSession();
s3.createCriteria( "Item" ).addOrder( Order.asc( "description" ) )
.setCacheable( true ).list();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
assertEquals( getSessions().getStatistics().getSecondLevelCacheHitCount(), 4 );
assertEquals( getSessions().getStatistics().getSecondLevelCacheMissCount(), 0 );
@@ -192,7 +193,7 @@ public class CMTTest extends FunctionalTestCase {
assertEquals( getSessions().getStatistics().getQueryCacheHitCount(), 2 );
assertEquals( getSessions().getStatistics().getQueryCacheMissCount(), 1 );
- SimpleJtaTransactionManagerImpl.getInstance().resume( tx4 );
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().resume( tx4 );
List r4 = s4.createCriteria( "Item" ).addOrder( Order.asc( "description" ) )
.setCacheable( true ).list();
assertEquals( r4.size(), 2 );
@@ -207,10 +208,10 @@ public class CMTTest extends FunctionalTestCase {
assertEquals( getSessions().getStatistics().getQueryCacheHitCount(), 3 );
assertEquals( getSessions().getStatistics().getQueryCacheMissCount(), 1 );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = openSession();
s.createQuery( "delete from Item" ).executeUpdate();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
}
public void testConcurrentCachedDirtyQueries() throws Exception {
@@ -219,7 +220,7 @@ public class CMTTest extends FunctionalTestCase {
return;
}
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s = openSession();
Map foo = new HashMap();
foo.put( "name", "Foo" );
@@ -229,7 +230,7 @@ public class CMTTest extends FunctionalTestCase {
bar.put( "name", "Bar" );
bar.put( "description", "a small bar" );
s.persist( "Item", bar );
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
synchronized ( this ) {
wait( 1000 );
@@ -239,11 +240,11 @@ public class CMTTest extends FunctionalTestCase {
getSessions().evictEntity( "Item" );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s4 = openSession();
- Transaction tx4 = SimpleJtaTransactionManagerImpl.getInstance().suspend();
+ Transaction tx4 = sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().suspend();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s1 = openSession();
List r1 = s1.createCriteria( "Item" ).addOrder( Order.asc( "description" ) )
.setCacheable( true ).list();
@@ -251,14 +252,14 @@ public class CMTTest extends FunctionalTestCase {
foo = ( Map ) r1.get( 0 );
foo.put( "description", "a big red foo" );
s1.flush();
- Transaction tx1 = SimpleJtaTransactionManagerImpl.getInstance().suspend();
+ Transaction tx1 = sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().suspend();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s2 = openSession();
List r2 = s2.createCriteria( "Item" ).addOrder( Order.asc( "description" ) )
.setCacheable( true ).list();
assertEquals( r2.size(), 2 );
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
assertEquals( getSessions().getStatistics().getSecondLevelCacheHitCount(), 0 );
assertEquals( getSessions().getStatistics().getSecondLevelCacheMissCount(), 0 );
@@ -269,14 +270,14 @@ public class CMTTest extends FunctionalTestCase {
assertEquals( getSessions().getStatistics().getQueryCacheHitCount(), 0 );
assertEquals( getSessions().getStatistics().getQueryCacheMissCount(), 2 );
- SimpleJtaTransactionManagerImpl.getInstance().resume( tx1 );
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().resume( tx1 );
tx1.commit();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s3 = openSession();
s3.createCriteria( "Item" ).addOrder( Order.asc( "description" ) )
.setCacheable( true ).list();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
assertEquals( getSessions().getStatistics().getSecondLevelCacheHitCount(), 0 );
assertEquals( getSessions().getStatistics().getSecondLevelCacheMissCount(), 0 );
@@ -287,7 +288,7 @@ public class CMTTest extends FunctionalTestCase {
assertEquals( getSessions().getStatistics().getQueryCacheHitCount(), 0 );
assertEquals( getSessions().getStatistics().getQueryCacheMissCount(), 3 );
- SimpleJtaTransactionManagerImpl.getInstance().resume( tx4 );
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().resume( tx4 );
List r4 = s4.createCriteria( "Item" ).addOrder( Order.asc( "description" ) )
.setCacheable( true ).list();
assertEquals( r4.size(), 2 );
@@ -302,42 +303,42 @@ public class CMTTest extends FunctionalTestCase {
assertEquals( getSessions().getStatistics().getQueryCacheHitCount(), 1 );
assertEquals( getSessions().getStatistics().getQueryCacheMissCount(), 3 );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = openSession();
s.createQuery( "delete from Item" ).executeUpdate();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
}
public void testCMT() throws Exception {
getSessions().getStatistics().clear();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s = openSession();
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
assertFalse( s.isOpen() );
assertEquals( getSessions().getStatistics().getFlushCount(), 0 );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = openSession();
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().rollback();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().rollback();
assertFalse( s.isOpen() );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = openSession();
Map item = new HashMap();
item.put( "name", "The Item" );
item.put( "description", "The only item we have" );
s.persist( "Item", item );
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
assertFalse( s.isOpen() );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = openSession();
item = ( Map ) s.createQuery( "from Item" ).uniqueResult();
assertNotNull( item );
s.delete( item );
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
assertFalse( s.isOpen() );
assertEquals( getSessions().getStatistics().getTransactionCount(), 4 );
@@ -349,19 +350,19 @@ public class CMTTest extends FunctionalTestCase {
assertEquals( getSessions().getStatistics().getQueryExecutionCount(), 1 );
assertEquals( getSessions().getStatistics().getFlushCount(), 2 );
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = openSession();
s.createQuery( "delete from Item" ).executeUpdate();
- SimpleJtaTransactionManagerImpl.getInstance().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
}
public void testCurrentSession() throws Exception {
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s = getSessions().getCurrentSession();
Session s2 = getSessions().getCurrentSession();
assertSame( s, s2 );
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
assertFalse( s.isOpen() );
// TODO : would be nice to automate-test that the SF internal map actually gets cleaned up
@@ -369,7 +370,7 @@ public class CMTTest extends FunctionalTestCase {
}
public void testCurrentSessionWithIterate() throws Exception {
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s = openSession();
Map item1 = new HashMap();
item1.put( "name", "Item - 1" );
@@ -380,11 +381,11 @@ public class CMTTest extends FunctionalTestCase {
item2.put( "name", "Item - 2" );
item2.put( "description", "The second item" );
s.persist( "Item", item2 );
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
// First, test iterating the partial iterator; iterate to past
// the first, but not the second, item
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = getSessions().getCurrentSession();
Iterator itr = s.createQuery( "from Item" ).iterate();
if ( !itr.hasNext() ) {
@@ -394,10 +395,10 @@ public class CMTTest extends FunctionalTestCase {
if ( !itr.hasNext() ) {
fail( "Only one result in iterator" );
}
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
// Next, iterate the entire result
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = getSessions().getCurrentSession();
itr = s.createQuery( "from Item" ).iterate();
if ( !itr.hasNext() ) {
@@ -406,16 +407,16 @@ public class CMTTest extends FunctionalTestCase {
while ( itr.hasNext() ) {
itr.next();
}
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = openSession();
s.createQuery( "delete from Item" ).executeUpdate();
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
}
public void testCurrentSessionWithScroll() throws Exception {
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s = getSessions().getCurrentSession();
Map item1 = new HashMap();
item1.put( "name", "Item - 1" );
@@ -426,50 +427,50 @@ public class CMTTest extends FunctionalTestCase {
item2.put( "name", "Item - 2" );
item2.put( "description", "The second item" );
s.persist( "Item", item2 );
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
// First, test partially scrolling the result with out closing
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = getSessions().getCurrentSession();
ScrollableResults results = s.createQuery( "from Item" ).scroll();
results.next();
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
// Next, test partially scrolling the result with closing
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = getSessions().getCurrentSession();
results = s.createQuery( "from Item" ).scroll();
results.next();
results.close();
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
// Next, scroll the entire result (w/o closing)
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = getSessions().getCurrentSession();
results = s.createQuery( "from Item" ).scroll();
while ( results.next() ) {
// do nothing
}
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
// Next, scroll the entire result (closing)
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = getSessions().getCurrentSession();
results = s.createQuery( "from Item" ).scroll();
while ( results.next() ) {
// do nothing
}
results.close();
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = getSessions().getCurrentSession();
s.createQuery( "delete from Item" ).executeUpdate();
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
}
public void testAggressiveReleaseWithExplicitDisconnectReconnect() throws Exception {
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s = getSessions().getCurrentSession();
s.createQuery( "from Item" ).list();
@@ -481,11 +482,11 @@ public class CMTTest extends FunctionalTestCase {
s.createQuery( "from Item" ).list();
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
}
public void testAggressiveReleaseWithConnectionRetreival() throws Exception {
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
Session s = openSession();
Map item1 = new HashMap();
item1.put( "name", "Item - 1" );
@@ -496,20 +497,20 @@ public class CMTTest extends FunctionalTestCase {
item2.put( "name", "Item - 2" );
item2.put( "description", "The second item" );
s.save( "Item", item2 );
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
try {
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = getSessions().getCurrentSession();
s.createQuery( "from Item" ).scroll().next();
s.connection();
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
}
finally {
- SimpleJtaTransactionManagerImpl.getInstance().begin();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().begin();
s = openSession();
s.createQuery( "delete from Item" ).executeUpdate();
- SimpleJtaTransactionManagerImpl.getInstance().getTransaction().commit();
+ sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager().commit();
}
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/transaction/jdbc/TestExpectedUsage.java b/hibernate-core/src/test/java/org/hibernate/test/transaction/jdbc/TestExpectedUsage.java
new file mode 100644
index 0000000000..871f544f9c
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/transaction/jdbc/TestExpectedUsage.java
@@ -0,0 +1,139 @@
+/*
+ * 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.test.transaction.jdbc;
+
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
+import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl;
+import org.hibernate.engine.transaction.spi.TransactionContext;
+import org.hibernate.engine.transaction.spi.TransactionImplementor;
+import org.hibernate.service.internal.ServiceRegistryImpl;
+import org.hibernate.service.spi.ServiceRegistry;
+import org.hibernate.service.spi.StandardServiceInitiators;
+import org.hibernate.test.common.ConnectionProviderBuilder;
+import org.hibernate.test.common.JournalingTransactionObserver;
+import org.hibernate.test.common.TransactionContextImpl;
+import org.hibernate.test.common.TransactionEnvironmentImpl;
+import org.hibernate.testing.junit.UnitTestCase;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class TestExpectedUsage extends UnitTestCase {
+ private ServiceRegistry serviceRegistry;
+
+ public TestExpectedUsage(String string) {
+ super( string );
+ }
+
+ public void setUp() throws Exception {
+ super.setUp();
+ serviceRegistry = new ServiceRegistryImpl(
+ StandardServiceInitiators.LIST,
+ ConnectionProviderBuilder.getConnectionProviderProperties()
+ );
+ }
+
+ public void tearDown() throws Exception {
+ ( (ServiceRegistryImpl) serviceRegistry).destroy();
+ super.tearDown();
+ }
+
+ public void testBasicUsage() {
+ final TransactionContext transactionContext = new TransactionContextImpl( new TransactionEnvironmentImpl( serviceRegistry ) ) {
+ @Override
+ public ConnectionReleaseMode getConnectionReleaseMode() {
+ return ConnectionReleaseMode.AFTER_TRANSACTION;
+ }
+ };
+
+ TransactionCoordinatorImpl transactionCoordinator = new TransactionCoordinatorImpl( null, transactionContext );
+ JournalingTransactionObserver observer = new JournalingTransactionObserver();
+ transactionCoordinator.addObserver( observer );
+
+ LogicalConnectionImplementor logicalConnection = transactionCoordinator.getJdbcCoordinator().getLogicalConnection();
+ Connection connection = logicalConnection.getShareableConnectionProxy();
+
+ // set up some tables to use
+ try {
+ Statement statement = connection.createStatement();
+ statement.execute( "drop table SANDBOX_JDBC_TST if exists" );
+ statement.execute( "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" );
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() );
+ statement.close();
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() ); // after_transaction specified
+ }
+ catch ( SQLException sqle ) {
+ fail( "incorrect exception type : SQLException" );
+ }
+
+ // ok, now we can get down to it...
+ TransactionImplementor txn = transactionCoordinator.getTransaction(); // same as Session#getTransaction
+ txn.begin();
+ assertEquals( 1, observer.getBegins() );
+ try {
+ PreparedStatement ps = connection.prepareStatement( "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )" );
+ ps.setLong( 1, 1 );
+ ps.setString( 2, "name" );
+ ps.execute();
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ ps.close();
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+
+ ps = connection.prepareStatement( "select * from SANDBOX_JDBC_TST" );
+ ps.executeQuery();
+ connection.prepareStatement( "delete from SANDBOX_JDBC_TST" ).execute();
+ // lets forget to close these...
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+
+ // and commit the transaction...
+ txn.commit();
+
+ // we should now have:
+ // 1) no resources because of after_transaction release mode
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ // 2) non-physically connected logical connection, again because of after_transaction release mode
+ assertFalse( logicalConnection.isPhysicallyConnected() );
+ // 3) transaction observer callbacks
+ assertEquals( 1, observer.getBeforeCompletions() );
+ assertEquals( 1, observer.getAfterCompletions() );
+ }
+ catch ( SQLException sqle ) {
+ fail( "incorrect exception type : SQLException" );
+ }
+ finally {
+ logicalConnection.close();
+ }
+ }
+
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/transaction/jta/BasicDrivingTest.java b/hibernate-core/src/test/java/org/hibernate/test/transaction/jta/BasicDrivingTest.java
new file mode 100644
index 0000000000..d38a056c02
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/transaction/jta/BasicDrivingTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.test.transaction.jta;
+
+import org.hibernate.cfg.Environment;
+import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
+import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl;
+import org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory;
+import org.hibernate.engine.transaction.spi.TransactionContext;
+import org.hibernate.engine.transaction.spi.TransactionImplementor;
+import org.hibernate.service.internal.ServiceProxy;
+import org.hibernate.service.internal.ServiceRegistryImpl;
+import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.service.spi.ServiceRegistry;
+import org.hibernate.service.spi.StandardServiceInitiators;
+import org.hibernate.test.common.ConnectionProviderBuilder;
+import org.hibernate.test.common.JournalingTransactionObserver;
+import org.hibernate.test.common.TransactionContextImpl;
+import org.hibernate.test.common.TransactionEnvironmentImpl;
+import org.hibernate.test.common.jta.AtomikosDataSourceConnectionProvider;
+import org.hibernate.test.common.jta.AtomikosJtaPlatform;
+import org.hibernate.testing.junit.UnitTestCase;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Testing transaction handling when the JTA transaction facade is the driver.
+ *
+ * @author Steve Ebersole
+ */
+public class BasicDrivingTest extends UnitTestCase {
+ private ServiceRegistry serviceRegistry;
+
+ public BasicDrivingTest(String string) {
+ super( string );
+ }
+
+ public void setUp() throws Exception {
+ super.setUp();
+
+ Map configValues = new HashMap();
+ configValues.putAll( ConnectionProviderBuilder.getConnectionProviderProperties() );
+ configValues.put( Environment.TRANSACTION_STRATEGY, JtaTransactionFactory.class.getName() );
+ configValues.put( JtaPlatformInitiator.JTA_PLATFORM, AtomikosJtaPlatform.class.getName() );
+ configValues.put( Environment.CONNECTION_PROVIDER, AtomikosDataSourceConnectionProvider.class.getName() );
+ serviceRegistry = new ServiceRegistryImpl( StandardServiceInitiators.LIST, configValues );
+ }
+
+ public void tearDown() throws Exception {
+ ( (ServiceRegistryImpl) serviceRegistry).destroy();
+ super.tearDown();
+ }
+
+ public void testBasicUsage() throws Throwable {
+ final TransactionContext transactionContext = new TransactionContextImpl( new TransactionEnvironmentImpl( serviceRegistry ) );
+
+ TransactionCoordinatorImpl transactionCoordinator = new TransactionCoordinatorImpl( null, transactionContext );
+ JournalingTransactionObserver observer = new JournalingTransactionObserver();
+ transactionCoordinator.addObserver( observer );
+
+ LogicalConnectionImplementor logicalConnection = transactionCoordinator.getJdbcCoordinator().getLogicalConnection();
+ Connection connection = logicalConnection.getShareableConnectionProxy();
+
+ // set up some tables to use
+ try {
+ Statement statement = connection.createStatement();
+ statement.execute( "drop table SANDBOX_JDBC_TST if exists" );
+ statement.execute( "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" );
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() );
+ statement.close();
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertFalse( logicalConnection.isPhysicallyConnected() ); // after_statement specified
+ }
+ catch ( SQLException sqle ) {
+ fail( "incorrect exception type : SQLException" );
+ }
+
+ // ok, now we can get down to it...
+ TransactionImplementor txn = transactionCoordinator.getTransaction(); // same as Session#getTransaction
+ txn.begin();
+ assertEquals( 1, observer.getBegins() );
+ assertTrue( txn.isInitiator() );
+ try {
+ PreparedStatement ps = connection.prepareStatement( "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )" );
+ ps.setLong( 1, 1 );
+ ps.setString( 2, "name" );
+ ps.execute();
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ ps.close();
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+
+ ps = connection.prepareStatement( "select * from SANDBOX_JDBC_TST" );
+ ps.executeQuery();
+ connection.prepareStatement( "delete from SANDBOX_JDBC_TST" ).execute();
+ // lets forget to close these...
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() );
+
+ // and commit the transaction...
+ txn.commit();
+
+ // we should now have:
+ // 1) no resources because of after_transaction release mode
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ // 2) non-physically connected logical connection, again because of after_transaction release mode
+ assertFalse( logicalConnection.isPhysicallyConnected() );
+ // 3) transaction observer callbacks
+ assertEquals( 1, observer.getBeforeCompletions() );
+ assertEquals( 1, observer.getAfterCompletions() );
+ }
+ catch ( SQLException sqle ) {
+ try {
+ JtaPlatform instance = ( (ServiceProxy) serviceRegistry.getService( JtaPlatform.class ) ).getTargetInstance();
+ instance.retrieveTransactionManager().rollback();
+ }
+ catch (Exception ignore) {
+ }
+ fail( "incorrect exception type : SQLException" );
+ }
+ catch (Throwable reThrowable) {
+ try {
+ JtaPlatform instance = ( (ServiceProxy) serviceRegistry.getService( JtaPlatform.class ) ).getTargetInstance();
+ instance.retrieveTransactionManager().rollback();
+ }
+ catch (Exception ignore) {
+ }
+ throw reThrowable;
+ }
+ finally {
+ logicalConnection.close();
+ }
+ }
+
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/transaction/jta/ManagedDrivingTest.java b/hibernate-core/src/test/java/org/hibernate/test/transaction/jta/ManagedDrivingTest.java
new file mode 100644
index 0000000000..746497f89a
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/transaction/jta/ManagedDrivingTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.test.transaction.jta;
+
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.cfg.Environment;
+import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
+import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl;
+import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
+import org.hibernate.engine.transaction.spi.TransactionContext;
+import org.hibernate.engine.transaction.spi.TransactionImplementor;
+import org.hibernate.service.internal.ServiceProxy;
+import org.hibernate.service.internal.ServiceRegistryImpl;
+import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.service.spi.ServiceRegistry;
+import org.hibernate.service.spi.StandardServiceInitiators;
+import org.hibernate.test.common.ConnectionProviderBuilder;
+import org.hibernate.test.common.JournalingTransactionObserver;
+import org.hibernate.test.common.TransactionContextImpl;
+import org.hibernate.test.common.TransactionEnvironmentImpl;
+import org.hibernate.test.common.jta.AtomikosDataSourceConnectionProvider;
+import org.hibernate.test.common.jta.AtomikosJtaPlatform;
+import org.hibernate.testing.junit.UnitTestCase;
+
+import javax.transaction.TransactionManager;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Testing transaction facacde handling when the transaction is being driven by somethign other than the facade.
+ *
+ * @author Steve Ebersole
+ */
+public class ManagedDrivingTest extends UnitTestCase {
+ private ServiceRegistry serviceRegistry;
+
+ public ManagedDrivingTest(String string) {
+ super( string );
+ }
+
+ public void setUp() throws Exception {
+ super.setUp();
+
+ Map configValues = new HashMap();
+ configValues.putAll( ConnectionProviderBuilder.getConnectionProviderProperties() );
+ configValues.put( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class.getName() );
+ configValues.put( JtaPlatformInitiator.JTA_PLATFORM, AtomikosJtaPlatform.class.getName() );
+ configValues.put( Environment.CONNECTION_PROVIDER, AtomikosDataSourceConnectionProvider.class.getName() );
+
+ serviceRegistry = new ServiceRegistryImpl( StandardServiceInitiators.LIST, configValues );
+ }
+
+
+ public void tearDown() throws Exception {
+ ( (ServiceRegistryImpl) serviceRegistry).destroy();
+ super.tearDown();
+ }
+
+ public void testBasicUsage() throws Throwable {
+ final TransactionContext transactionContext = new TransactionContextImpl( new TransactionEnvironmentImpl( serviceRegistry ) ) {
+ @Override
+ public ConnectionReleaseMode getConnectionReleaseMode() {
+ return ConnectionReleaseMode.AFTER_STATEMENT;
+ }
+ };
+
+ final TransactionCoordinatorImpl transactionCoordinator = new TransactionCoordinatorImpl( null, transactionContext );
+ final JournalingTransactionObserver transactionObserver = new JournalingTransactionObserver();
+ transactionCoordinator.addObserver( transactionObserver );
+
+ final LogicalConnectionImplementor logicalConnection = transactionCoordinator.getJdbcCoordinator().getLogicalConnection();
+ Connection connection = logicalConnection.getShareableConnectionProxy();
+
+ // set up some tables to use
+ try {
+ Statement statement = connection.createStatement();
+ statement.execute( "drop table SANDBOX_JDBC_TST if exists" );
+ statement.execute( "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" );
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() );
+ statement.close();
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertFalse( logicalConnection.isPhysicallyConnected() ); // after_statement specified
+ }
+ catch ( SQLException sqle ) {
+ fail( "incorrect exception type : SQLException" );
+ }
+
+ JtaPlatform instance = ( (ServiceProxy) serviceRegistry.getService( JtaPlatform.class ) ).getTargetInstance();
+ TransactionManager transactionManager = instance.retrieveTransactionManager();
+
+ // start the cmt
+ transactionManager.begin();
+
+ // ok, now we can get down to it...
+ TransactionImplementor txn = transactionCoordinator.getTransaction(); // same as Session#getTransaction
+ txn.begin();
+ assertEquals( 1, transactionObserver.getBegins() );
+ assertFalse( txn.isInitiator() );
+ connection = logicalConnection.getShareableConnectionProxy();
+ try {
+ PreparedStatement ps = connection.prepareStatement( "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )" );
+ ps.setLong( 1, 1 );
+ ps.setString( 2, "name" );
+ ps.execute();
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ ps.close();
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+
+ ps = connection.prepareStatement( "select * from SANDBOX_JDBC_TST" );
+ ps.executeQuery();
+ connection.prepareStatement( "delete from SANDBOX_JDBC_TST" ).execute();
+ // lets forget to close these...
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() );
+
+ // and commit the transaction...
+ txn.commit();
+
+ // since txn is not a driver, nothing should have changed...
+ assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertTrue( logicalConnection.isPhysicallyConnected() );
+ assertEquals( 0, transactionObserver.getBeforeCompletions() );
+ assertEquals( 0, transactionObserver.getAfterCompletions() );
+
+ transactionManager.commit();
+ assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() );
+ assertFalse( logicalConnection.isPhysicallyConnected() );
+ assertEquals( 1, transactionObserver.getBeforeCompletions() );
+ assertEquals( 1, transactionObserver.getAfterCompletions() );
+ }
+ catch ( SQLException sqle ) {
+ try {
+ transactionManager.rollback();
+ }
+ catch (Exception ignore) {
+ }
+ fail( "incorrect exception type : SQLException" );
+ }
+ catch (Throwable reThrowable) {
+ try {
+ transactionManager.rollback();
+ }
+ catch (Exception ignore) {
+ }
+ throw reThrowable;
+ }
+ finally {
+ logicalConnection.close();
+ }
+ }
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/testing/cache/BaseCacheProviderTestCase.java b/hibernate-core/src/test/java/org/hibernate/testing/cache/BaseCacheProviderTestCase.java
index 8b5dbff242..58f8f0b5e4 100644
--- a/hibernate-core/src/test/java/org/hibernate/testing/cache/BaseCacheProviderTestCase.java
+++ b/hibernate-core/src/test/java/org/hibernate/testing/cache/BaseCacheProviderTestCase.java
@@ -30,12 +30,12 @@ import org.hibernate.Transaction;
import org.hibernate.cache.ReadWriteCache;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
+import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;
import org.hibernate.testing.tm.ConnectionProviderImpl;
import org.hibernate.testing.tm.TransactionManagerLookupImpl;
-import org.hibernate.transaction.JDBCTransactionFactory;
/**
* Common requirement testing for each {@link org.hibernate.cache.CacheProvider} impl.
@@ -78,7 +78,7 @@ public abstract class BaseCacheProviderTestCase extends FunctionalTestCase {
cfg.setProperty( Environment.TRANSACTION_MANAGER_STRATEGY, TransactionManagerLookupImpl.class.getName() );
}
else {
- cfg.setProperty( Environment.TRANSACTION_STRATEGY, JDBCTransactionFactory.class.getName() );
+ cfg.setProperty( Environment.TRANSACTION_STRATEGY, JdbcTransactionFactory.class.getName() );
}
}
diff --git a/hibernate-core/src/test/resources/log4j.properties b/hibernate-core/src/test/resources/log4j.properties
index cd9c5224cf..c13e5d4f48 100644
--- a/hibernate-core/src/test/resources/log4j.properties
+++ b/hibernate-core/src/test/resources/log4j.properties
@@ -17,3 +17,4 @@ log4j.logger.org.hibernate.hql.ast.SqlGenerator=trace
log4j.logger.org.hibernate.hql.ast.AST=trace
log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder=trace
log4j.logger.org.hibernate.type.BasicTypeRegistry=trace
+
diff --git a/hibernate-entitymanager/hibernate-entitymanager.gradle b/hibernate-entitymanager/hibernate-entitymanager.gradle
index b9fb474d99..52cac0e6cb 100644
--- a/hibernate-entitymanager/hibernate-entitymanager.gradle
+++ b/hibernate-entitymanager/hibernate-entitymanager.gradle
@@ -1,4 +1,4 @@
-import org.apache.tools.ant.filters.*
+import org.apache.tools.ant.filters.ReplaceTokens
apply plugin: 'java'
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
index aca398a737..ed1c48cc97 100755
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
@@ -1,4 +1,3 @@
-// $Id$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@@ -24,15 +23,51 @@
*/
package org.hibernate.ejb;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import org.hibernate.AssertionFailure;
+import org.hibernate.CacheMode;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
+import org.hibernate.LockOptions;
+import org.hibernate.MappingException;
+import org.hibernate.ObjectDeletedException;
+import org.hibernate.ObjectNotFoundException;
+import org.hibernate.QueryException;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.StaleStateException;
+import org.hibernate.TransientObjectException;
+import org.hibernate.TypeMismatchException;
+import org.hibernate.UnresolvableObjectException;
+import org.hibernate.cfg.Environment;
+import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
+import org.hibernate.ejb.criteria.ValueHandlerFactory;
+import org.hibernate.ejb.criteria.expression.CompoundSelectionImpl;
+import org.hibernate.ejb.util.CacheModeHelper;
+import org.hibernate.ejb.util.ConfigurationHelper;
+import org.hibernate.ejb.util.LockModeTypeHelper;
+import org.hibernate.engine.NamedSQLQueryDefinition;
+import org.hibernate.engine.ResultSetMappingDefinition;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.query.sql.NativeSQLQueryReturn;
+import org.hibernate.engine.query.sql.NativeSQLQueryRootReturn;
+import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
+import org.hibernate.engine.transaction.spi.JoinStatus;
+import org.hibernate.engine.transaction.spi.TransactionCoordinator;
+import org.hibernate.engine.transaction.spi.TransactionImplementor;
+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.proxy.HibernateProxy;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.transform.BasicTransformerAdapter;
+import org.hibernate.util.ReflectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import javax.persistence.CacheRetrieveMode;
import javax.persistence.CacheStoreMode;
import javax.persistence.EntityManager;
@@ -59,55 +94,17 @@ import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Selection;
import javax.persistence.metamodel.Metamodel;
import javax.persistence.spi.PersistenceUnitTransactionType;
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.AssertionFailure;
-import org.hibernate.CacheMode;
-import org.hibernate.FlushMode;
-import org.hibernate.HibernateException;
-import org.hibernate.LockMode;
-import org.hibernate.LockOptions;
-import org.hibernate.MappingException;
-import org.hibernate.ObjectDeletedException;
-import org.hibernate.ObjectNotFoundException;
-import org.hibernate.QueryException;
-import org.hibernate.SQLQuery;
-import org.hibernate.Session;
-import org.hibernate.StaleObjectStateException;
-import org.hibernate.StaleStateException;
-import org.hibernate.Transaction;
-import org.hibernate.TransientObjectException;
-import org.hibernate.TypeMismatchException;
-import org.hibernate.UnresolvableObjectException;
-import org.hibernate.cfg.Environment;
-import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
-import org.hibernate.ejb.criteria.ValueHandlerFactory;
-import org.hibernate.ejb.criteria.expression.CompoundSelectionImpl;
-import org.hibernate.ejb.transaction.JoinableCMTTransaction;
-import org.hibernate.ejb.util.CacheModeHelper;
-import org.hibernate.ejb.util.ConfigurationHelper;
-import org.hibernate.ejb.util.LockModeTypeHelper;
-import org.hibernate.engine.NamedSQLQueryDefinition;
-import org.hibernate.engine.ResultSetMappingDefinition;
-import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.engine.SessionImplementor;
-import org.hibernate.engine.query.sql.NativeSQLQueryReturn;
-import org.hibernate.engine.query.sql.NativeSQLQueryRootReturn;
-import org.hibernate.proxy.HibernateProxy;
-import org.hibernate.transaction.TransactionFactory;
-import org.hibernate.transaction.synchronization.AfterCompletionAction;
-import org.hibernate.transaction.synchronization.BeforeCompletionManagedFlushChecker;
-import org.hibernate.transaction.synchronization.CallbackCoordinator;
-import org.hibernate.transaction.synchronization.ExceptionMapper;
-import org.hibernate.transform.BasicTransformerAdapter;
-import org.hibernate.util.JTAHelper;
-import org.hibernate.util.ReflectHelper;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
/**
* @author Gavin King
@@ -944,6 +941,10 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
return ( ( SessionImplementor ) getRawSession() ).isTransactionInProgress();
}
+ private SessionFactoryImplementor sfi() {
+ return ( SessionFactoryImplementor ) getRawSession().getSessionFactory();
+ }
+
protected void markAsRollback() {
log.debug( "mark transaction for rollback" );
if ( tx.isActive() ) {
@@ -952,8 +953,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
else {
//no explicit use of the tx. boundaries methods
if ( PersistenceUnitTransactionType.JTA == transactionType ) {
- TransactionManager transactionManager =
- ( ( SessionFactoryImplementor ) getRawSession().getSessionFactory() ).getTransactionManager();
+ TransactionManager transactionManager = sfi().getServiceRegistry().getService( JtaPlatform.class ).retrieveTransactionManager();
if ( transactionManager == null ) {
throw new PersistenceException(
"Using a JTA persistence context wo setting hibernate.transaction.manager_lookup_class"
@@ -987,105 +987,52 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
}
private void joinTransaction(boolean ignoreNotJoining) {
- //set the joined status
- getSession().isOpen(); //for sync
- if ( transactionType == PersistenceUnitTransactionType.JTA ) {
- try {
- log.debug( "Looking for a JTA transaction to join" );
- final Session session = getSession();
- final Transaction transaction = session.getTransaction();
- if ( transaction != null && transaction instanceof JoinableCMTTransaction ) {
- //can't handle it if not a joinnable transaction
- final JoinableCMTTransaction joinableCMTTransaction = ( JoinableCMTTransaction ) transaction;
-
- if ( joinableCMTTransaction.getStatus() == JoinableCMTTransaction.JoinStatus.JOINED ) {
- log.debug( "Transaction already joined" );
- return; //no-op
- }
- joinableCMTTransaction.markForJoined();
- session.isOpen(); //register to the Tx
- if ( joinableCMTTransaction.getStatus() == JoinableCMTTransaction.JoinStatus.NOT_JOINED ) {
- if ( ignoreNotJoining ) {
- log.debug( "No JTA transaction found" );
- return;
- }
- else {
- throw new TransactionRequiredException(
- "No active JTA transaction on joinTransaction call"
- );
- }
- }
- else if ( joinableCMTTransaction.getStatus() == JoinableCMTTransaction.JoinStatus.MARKED_FOR_JOINED ) {
- throw new AssertionFailure( "Transaction MARKED_FOR_JOINED after isOpen() call" );
- }
- //flush before completion and
- //register clear on rollback
- log.trace( "Adding flush() and close() synchronization" );
- CallbackCoordinator callbackCoordinator = ( (SessionImplementor ) getSession() ).getJDBCContext().getJtaSynchronizationCallbackCoordinator();
- if ( callbackCoordinator == null ) {
- throw new AssertionFailure( "Expecting CallbackCoordinator to be non-null" );
- }
- callbackCoordinator.setBeforeCompletionManagedFlushChecker(
- new BeforeCompletionManagedFlushChecker() {
- public boolean shouldDoManagedFlush(TransactionFactory.Context ctx, javax.transaction.Transaction jtaTransaction)
- throws SystemException {
- if ( transaction == null ) {
- log.warn( "Transaction not available on beforeCompletion: assuming valid" );
- }
- return !ctx.isFlushModeNever()
- && ( jtaTransaction == null || !JTAHelper.isRollback( jtaTransaction.getStatus() ) );
- }
- }
- );
- callbackCoordinator.setAfterCompletionAction(
- new AfterCompletionAction() {
- public void doAction(TransactionFactory.Context ctx, int status) {
- try {
- if ( !ctx.isClosed() ) {
- if ( Status.STATUS_ROLLEDBACK == status
- && transactionType == PersistenceUnitTransactionType.JTA ) {
- session.clear();
- }
- JoinableCMTTransaction joinable = ( JoinableCMTTransaction ) session.getTransaction();
- joinable.resetStatus();
- }
- }
- catch ( HibernateException e ) {
- throw convert( e );
- }
- }
- }
- );
- callbackCoordinator.setExceptionMapper(
- new ExceptionMapper() {
- public RuntimeException mapStatusCheckFailure(String message, SystemException systemException) {
- throw new PersistenceException( message, systemException );
- }
-
- public RuntimeException mapManagedFlushFailure(String message, RuntimeException failure) {
- if ( HibernateException.class.isInstance( failure ) ) {
- throw convert( failure );
- }
- if ( PersistenceException.class.isInstance( failure ) ) {
- throw failure;
- }
- throw new PersistenceException( message, failure );
- }
- }
- );
- }
- else {
- log.warn( "Cannot join transaction: do not override {}", Environment.TRANSACTION_STRATEGY );
- }
- }
- catch ( HibernateException he ) {
- throw convert( he );
- }
- }
- else {
+ if ( transactionType != PersistenceUnitTransactionType.JTA ) {
if ( !ignoreNotJoining ) {
log.warn( "Calling joinTransaction() on a non JTA EntityManager" );
}
+ return;
+ }
+
+ final SessionImplementor session = (SessionImplementor) getSession();
+ session.getTransactionCoordinator().pulse();
+
+ log.debug( "Looking for a JTA transaction to join" );
+ if ( ! session.getTransactionCoordinator().isTransactionJoinable() ) {
+ log.warn( "Cannot join transaction: do not override {}", Environment.TRANSACTION_STRATEGY );
+ }
+
+ try {
+ final TransactionImplementor transaction = session.getTransactionCoordinator().getTransaction();
+
+ if ( transaction.getJoinStatus() == JoinStatus.JOINED ) {
+ log.debug( "Transaction already joined" );
+ return; // noop
+ }
+
+ // join the transaction and then recheck the status
+ transaction.join();
+ if ( transaction.getJoinStatus() == JoinStatus.NOT_JOINED ) {
+ if ( ignoreNotJoining ) {
+ log.debug( "No JTA transaction found" );
+ return;
+ }
+ else {
+ throw new TransactionRequiredException( "No active JTA transaction on joinTransaction call" );
+ }
+ }
+ else if ( transaction.getJoinStatus() == JoinStatus.MARKED_FOR_JOINED ) {
+ throw new AssertionFailure( "Transaction MARKED_FOR_JOINED after isOpen() call" );
+ }
+
+ // register behavior changes
+ SynchronizationCallbackCoordinator callbackCoordinator = session.getTransactionCoordinator().getSynchronizationCallbackCoordinator();
+ callbackCoordinator.setManagedFlushChecker( new ManagedFlushCheckerImpl() );
+ callbackCoordinator.setExceptionMapper( new CallbackExceptionMapperImpl() );
+ callbackCoordinator.setAfterCompletionAction( new AfterCompletionActionImpl( session, transactionType ) );
+ }
+ catch ( HibernateException he ) {
+ throw convert( he );
}
}
@@ -1278,4 +1225,54 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
}
return pe;
}
+
+ private static class AfterCompletionActionImpl implements AfterCompletionAction {
+ private final SessionImplementor session;
+ private final PersistenceUnitTransactionType transactionType;
+
+ private AfterCompletionActionImpl(SessionImplementor session, PersistenceUnitTransactionType transactionType) {
+ this.session = session;
+ this.transactionType = transactionType;
+ }
+
+ @Override
+ public void doAction(TransactionCoordinator transactionCoordinator, int status) {
+ if ( session.isClosed() ) {
+ log.trace( "Session was closed; nothing to do" );
+ return;
+ }
+
+ final boolean successful = JtaStatusHelper.isCommitted( status );
+ if ( !successful && transactionType == PersistenceUnitTransactionType.JTA ) {
+ ( (Session) session ).clear();
+ }
+ session.getTransactionCoordinator().resetJoinStatus();
+ }
+ }
+
+ private static class ManagedFlushCheckerImpl implements ManagedFlushChecker {
+ @Override
+ public boolean shouldDoManagedFlush(TransactionCoordinator coordinator, int jtaStatus) {
+ return ! coordinator.getTransactionContext().isFlushModeNever() &&
+ ! JtaStatusHelper.isRollback( jtaStatus );
+ }
+ }
+
+ private class CallbackExceptionMapperImpl implements ExceptionMapper {
+ @Override
+ public RuntimeException mapStatusCheckFailure(String message, SystemException systemException) {
+ throw new PersistenceException( message, systemException );
+ }
+
+ @Override
+ public RuntimeException mapManagedFlushFailure(String message, RuntimeException failure) {
+ if ( HibernateException.class.isInstance( failure ) ) {
+ throw convert( failure );
+ }
+ if ( PersistenceException.class.isInstance( failure ) ) {
+ throw failure;
+ }
+ throw new PersistenceException( message, failure );
+ }
+ }
}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/Ejb3Configuration.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/Ejb3Configuration.java
index c61d3a2a0a..07eaa01b90 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/Ejb3Configuration.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/Ejb3Configuration.java
@@ -87,6 +87,7 @@ import org.hibernate.ejb.util.ConfigurationHelper;
import org.hibernate.ejb.util.LogHelper;
import org.hibernate.ejb.util.NamingHelper;
import org.hibernate.engine.FilterDefinition;
+import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory;
import org.hibernate.event.EventListeners;
import org.hibernate.mapping.AuxiliaryDatabaseObject;
import org.hibernate.mapping.PersistentClass;
@@ -95,7 +96,6 @@ import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.secure.JACCConfiguration;
import org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator;
import org.hibernate.service.spi.ServiceRegistry;
-import org.hibernate.transaction.JDBCTransactionFactory;
import org.hibernate.util.CollectionHelper;
import org.hibernate.util.ReflectHelper;
import org.hibernate.util.StringHelper;
@@ -1256,7 +1256,7 @@ public class Ejb3Configuration implements Serializable, Referenceable {
);
}
else if ( ! hasTxStrategy && transactionType == PersistenceUnitTransactionType.RESOURCE_LOCAL ) {
- preparedProperties.setProperty( Environment.TRANSACTION_STRATEGY, JDBCTransactionFactory.class.getName() );
+ preparedProperties.setProperty( Environment.TRANSACTION_STRATEGY, JdbcTransactionFactory.class.getName() );
}
if ( hasTxStrategy ) {
log.warn(
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/transaction/JoinableCMTTransaction.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/transaction/JoinableCMTTransaction.java
index d4531a0739..19df58762c 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/transaction/JoinableCMTTransaction.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/transaction/JoinableCMTTransaction.java
@@ -21,79 +21,63 @@
*/
package org.hibernate.ejb.transaction;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-
import org.hibernate.HibernateException;
-import org.hibernate.TransactionException;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-import org.hibernate.transaction.CMTTransaction;
-import org.hibernate.transaction.TransactionFactory;
-import org.hibernate.util.JTAHelper;
+import org.hibernate.engine.transaction.internal.jta.CMTTransaction;
+import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
+import org.hibernate.engine.transaction.spi.JoinStatus;
+import org.hibernate.engine.transaction.spi.TransactionCoordinator;
/**
* Implements a joinable transaction. Until the transaction is marked for joined, the TM.isTransactionInProgress()
* must return false
*
* @author Emmanuel Bernard
+ * @author Steve Ebersole
*/
public class JoinableCMTTransaction extends CMTTransaction {
- private JoinStatus status;
+ private JoinStatus joinStatus = JoinStatus.NOT_JOINED;
- public JoinableCMTTransaction(JDBCContext jdbcContext, TransactionFactory.Context transactionContext) {
- super( jdbcContext, transactionContext );
- //status = JoinStatus.MARKED_FOR_JOINED;
- //tryJoiningTransaction();
+ public JoinableCMTTransaction(TransactionCoordinator transactionCoordinator) {
+ super( transactionCoordinator );
}
- public boolean isTransactionInProgress(
- JDBCContext jdbcContext,
- TransactionFactory.Context transactionContext) {
- try {
- return status == JoinStatus.JOINED && isTransactionInProgress(
- transactionContext.getFactory().getTransactionManager().getTransaction()
- );
- }
- catch (SystemException se) {
- throw new TransactionException( "Unable to check transaction status", se );
- }
+ boolean isJoinable() {
+ return joinStatus == JoinStatus.JOINED && JtaStatusHelper.isActive( transactionManager() );
}
- private boolean isTransactionInProgress() {
- try {
- Transaction transaction = transactionContext.getFactory().getTransactionManager().getTransaction();
- return isTransactionInProgress(transaction);
- }
- catch (SystemException se) {
- throw new TransactionException( "Unable to check transaction status", se );
- }
+ public JoinStatus getJoinStatus() {
+ return joinStatus;
}
- private boolean isTransactionInProgress(Transaction tx) throws SystemException {
- return JTAHelper.isTransactionInProgress(tx) && ! JTAHelper.isRollback( tx.getStatus() );
- }
-
- void tryJoiningTransaction() {
- if ( status == JoinStatus.MARKED_FOR_JOINED ) {
- if ( isTransactionInProgress() ) {
- status = JoinStatus.JOINED;
+ @Override
+ public void join() {
+ if ( joinStatus == JoinStatus.MARKED_FOR_JOINED ) {
+ if ( JtaStatusHelper.isActive( transactionManager() ) ) {
+ joinStatus = JoinStatus.JOINED;
+ // register synchronization if needed
+ transactionCoordinator().pulse();
}
else {
- status = JoinStatus.NOT_JOINED;
+ joinStatus = JoinStatus.NOT_JOINED;
}
}
}
+ @Override
+ public void resetJoinStatus() {
+ joinStatus = JoinStatus.NOT_JOINED;
+ }
+
@Override
public void begin() throws HibernateException {
super.begin();
- status = JoinStatus.JOINED;
+ joinStatus = JoinStatus.JOINED;
}
@Override
public void commit() throws HibernateException {
/* this method is not supposed to be called
- * it breaks the flushBeforeCompletion flag optimizeation
+ * it breaks the flushBeforeCompletion flag optimization
* regarding flushing skip.
* In its current form, it will generate too much flush() calls
*/
@@ -102,20 +86,11 @@ public class JoinableCMTTransaction extends CMTTransaction {
public JoinStatus getStatus() {
- return status;
+ return joinStatus;
}
public void resetStatus() {
- status = JoinStatus.NOT_JOINED;
+ joinStatus = JoinStatus.NOT_JOINED;
}
- public void markForJoined() {
- if ( status != JoinStatus.JOINED ) status = JoinStatus.MARKED_FOR_JOINED;
- }
-
- public static enum JoinStatus {
- NOT_JOINED,
- MARKED_FOR_JOINED,
- JOINED
- }
}
diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/transaction/JoinableCMTTransactionFactory.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/transaction/JoinableCMTTransactionFactory.java
index b4f3239342..95832b763e 100644
--- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/transaction/JoinableCMTTransactionFactory.java
+++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/transaction/JoinableCMTTransactionFactory.java
@@ -1,8 +1,10 @@
/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009-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 Middleware LLC.
+ * 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
@@ -21,34 +23,46 @@
*/
package org.hibernate.ejb.transaction;
-import org.hibernate.HibernateException;
-import org.hibernate.Transaction;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
-import org.hibernate.transaction.CMTTransactionFactory;
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.engine.transaction.spi.JoinStatus;
+import org.hibernate.engine.transaction.spi.TransactionCoordinator;
+import org.hibernate.engine.transaction.spi.TransactionFactory;
/**
* A transaction is in progress if the underlying JTA tx is in progress and if the Tx is marked as
* MARKED_FOR_JOINED
*
* @author Emmanuel Bernard
+ * @author Steve Ebersole
*/
-public class JoinableCMTTransactionFactory extends CMTTransactionFactory {
- public Transaction createTransaction(
- JDBCContext jdbcContext,
- Context transactionContext) throws HibernateException {
- return new JoinableCMTTransaction( jdbcContext, transactionContext );
+public class JoinableCMTTransactionFactory implements TransactionFactory {
+ @Override
+ public boolean compatibleWithJtaSynchronization() {
+ return true;
}
@Override
- public boolean isTransactionInProgress(
- JDBCContext jdbcContext,
- Context transactionContext,
- Transaction transaction) {
- if ( transaction == null ) {
- return false; //should not happen though
- }
- JoinableCMTTransaction joinableCMTTransaction = ( (JoinableCMTTransaction) transaction );
- joinableCMTTransaction.tryJoiningTransaction();
- return joinableCMTTransaction.isTransactionInProgress( jdbcContext, transactionContext );
+ public boolean canBeDriver() {
+ return false;
+ }
+
+ @Override
+ public JoinableCMTTransaction createTransaction(TransactionCoordinator transactionCoordinator) {
+ return new JoinableCMTTransaction( transactionCoordinator );
+ }
+
+ @Override
+ public boolean isJoinableJtaTransaction(TransactionCoordinator transactionCoordinator, JoinableCMTTransaction transaction) {
+ return transaction.isJoinable();
+ }
+
+ @Override
+ public JoinStatus getJoinStatus(TransactionCoordinator transactionCoordinator, JoinableCMTTransaction transaction) {
+ return transaction.getJoinStatus();
+ }
+
+ @Override
+ public ConnectionReleaseMode getDefaultReleaseMode() {
+ return ConnectionReleaseMode.AFTER_STATEMENT;
}
}
diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/TestCase.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/TestCase.java
index fceafbe65b..77526dec99 100644
--- a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/TestCase.java
+++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/TestCase.java
@@ -106,15 +106,15 @@ public abstract class TestCase extends HibernateTestCase {
}
protected void handleUnclosedResources() {
- cleanUnclosed( this.em );
- for ( Iterator iter = isolatedEms.iterator(); iter.hasNext(); ) {
- cleanUnclosed( ( EntityManager ) iter.next() );
- }
-
cfg = null;
}
protected void closeResources() {
+ cleanUnclosed( this.em );
+ for ( Object isolatedEm : isolatedEms ) {
+ cleanUnclosed( (EntityManager) isolatedEm );
+ }
+
if ( factory != null ) {
factory.close();
}
diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java b/hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java
index 5de4173e21..8fa33710df 100644
--- a/hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java
+++ b/hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java
@@ -46,8 +46,8 @@ import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.NonFlushedChanges;
-import org.hibernate.engine.jdbc.spi.JDBCContext;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
+import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.event.EventListeners;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.loader.custom.CustomQuery;
@@ -140,14 +140,6 @@ public abstract class AbstractDelegateSessionImplementor implements SessionImple
return delegate.getEntityUsingInterceptor(key);
}
- public void afterTransactionCompletion(boolean successful, Transaction tx) {
- delegate.afterTransactionCompletion(successful, tx);
- }
-
- public void beforeTransactionCompletion(Transaction tx) {
- delegate.beforeTransactionCompletion(tx);
- }
-
public Serializable getContextEntityIdentifier(Object object) {
return delegate.getContextEntityIdentifier(object);
}
@@ -280,11 +272,12 @@ public abstract class AbstractDelegateSessionImplementor implements SessionImple
return delegate.getFetchProfile();
}
- public JDBCContext getJDBCContext() {
- return delegate.getJDBCContext();
- }
+ @Override
+ public TransactionCoordinator getTransactionCoordinator() {
+ return delegate.getTransactionCoordinator();
+ }
- public boolean isClosed() {
+ public boolean isClosed() {
return delegate.isClosed();
}
}
diff --git a/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java b/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java
index ea8d7b0993..ef80e7c300 100644
--- a/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java
+++ b/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java
@@ -21,12 +21,11 @@
*/
package org.hibernate.cache.infinispan.tm;
-import java.util.Properties;
+import org.hibernate.cfg.Settings;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
import javax.transaction.TransactionManager;
-
-import org.hibernate.cfg.Settings;
-import org.hibernate.transaction.TransactionManagerLookup;
+import java.util.Properties;
/**
* HibernateTransactionManagerLookup.
@@ -35,20 +34,19 @@ import org.hibernate.transaction.TransactionManagerLookup;
* @since 3.5
*/
public class HibernateTransactionManagerLookup implements org.infinispan.transaction.lookup.TransactionManagerLookup {
- private final TransactionManagerLookup hibernateLookup;
-
- private final Properties properties;
-
- public HibernateTransactionManagerLookup(Settings settings, Properties properties) {
- if (settings != null)
- this.hibernateLookup = settings.getTransactionManagerLookup();
- else
- this.hibernateLookup = null;
- this.properties = properties;
- }
-
- public TransactionManager getTransactionManager() throws Exception {
- return hibernateLookup == null ? null : hibernateLookup.getTransactionManager(properties);
- }
+ private final JtaPlatform jtaPlatform;
+
+ public HibernateTransactionManagerLookup(Settings settings, Properties properties) {
+ if ( settings != null ) {
+ jtaPlatform = settings.getJtaPlatform();
+ }
+ else {
+ jtaPlatform = null;
+ }
+ }
+
+ public TransactionManager getTransactionManager() throws Exception {
+ return jtaPlatform == null ? null : jtaPlatform.retrieveTransactionManager();
+ }
}
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractEntityCollectionRegionTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractEntityCollectionRegionTestCase.java
index 2ce1305f9f..590a7d844e 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractEntityCollectionRegionTestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractEntityCollectionRegionTestCase.java
@@ -32,7 +32,9 @@ import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
+import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+import org.hibernate.testing.ServiceRegistryBuilder;
/**
* Base class for tests of EntityRegion and CollectionRegion implementations.
@@ -65,7 +67,9 @@ public abstract class AbstractEntityCollectionRegionTestCase extends AbstractReg
String entityCfg = "entity";
cfg.setProperty(InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, entityCfg);
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ ServiceRegistryBuilder.buildServiceRegistry( cfg.getProperties() ),
+ cfg,
+ getCacheTestSupport()
);
supportedAccessTypeTest(regionFactory, cfg.getProperties());
}
@@ -85,16 +89,20 @@ public abstract class AbstractEntityCollectionRegionTestCase extends AbstractReg
public void testIsTransactionAware() throws Exception {
Configuration cfg = CacheTestUtil.buildConfiguration("test", InfinispanRegionFactory.class, true, false);
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ ServiceRegistryBuilder.buildServiceRegistry( cfg.getProperties() ),
+ cfg,
+ getCacheTestSupport()
);
TransactionalDataRegion region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
assertTrue("Region is transaction-aware", region.isTransactionAware());
CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
cfg = CacheTestUtil.buildConfiguration("test", InfinispanRegionFactory.class, true, false);
// Make it non-transactional
- cfg.getProperties().remove(Environment.TRANSACTION_MANAGER_STRATEGY);
+ cfg.getProperties().remove( JtaPlatformInitiator.JTA_PLATFORM );
regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ ServiceRegistryBuilder.buildServiceRegistry( cfg.getProperties() ),
+ cfg,
+ getCacheTestSupport()
);
region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
assertFalse("Region is not transaction-aware", region.isTransactionAware());
@@ -104,7 +112,9 @@ public abstract class AbstractEntityCollectionRegionTestCase extends AbstractReg
public void testGetCacheDataDescription() throws Exception {
Configuration cfg = CacheTestUtil.buildConfiguration("test", InfinispanRegionFactory.class, true, false);
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ ServiceRegistryBuilder.buildServiceRegistry( cfg.getProperties() ),
+ cfg,
+ getCacheTestSupport()
);
TransactionalDataRegion region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
CacheDataDescription cdd = region.getCacheDataDescription();
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java
index 7f959ab380..eaa6a6ec7e 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java
@@ -73,7 +73,7 @@ public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionIm
private void evictOrRemoveTest() throws Exception {
Configuration cfg = createConfiguration();
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ getServiceRegistry(), cfg, getCacheTestSupport()
);
CacheAdapter localCache = getInfinispanCache(regionFactory);
boolean invalidation = localCache.isClusteredInvalidation();
@@ -86,7 +86,7 @@ public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionIm
cfg = createConfiguration();
regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ getServiceRegistry(), cfg, getCacheTestSupport()
);
GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(regionFactory,
@@ -126,7 +126,7 @@ public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionIm
private void evictOrRemoveAllTest(String configName) throws Exception {
Configuration cfg = createConfiguration();
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ getServiceRegistry(), cfg, getCacheTestSupport()
);
CacheAdapter localCache = getInfinispanCache(regionFactory);
@@ -138,7 +138,7 @@ public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionIm
cfg = createConfiguration();
regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ getServiceRegistry(), cfg, getCacheTestSupport()
);
CacheAdapter remoteCache = getInfinispanCache(regionFactory);
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractCollectionRegionAccessStrategyTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractCollectionRegionAccessStrategyTestCase.java
index d63e697314..d98f34b3ed 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractCollectionRegionAccessStrategyTestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractCollectionRegionAccessStrategyTestCase.java
@@ -43,7 +43,6 @@ import org.hibernate.cache.infinispan.util.CacheAdapter;
import org.hibernate.cache.infinispan.util.FlagAdapter;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
-import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.service.spi.ServiceRegistry;
import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeJtaTransactionManagerImpl;
@@ -519,7 +518,9 @@ public abstract class AbstractCollectionRegionAccessStrategyTestCase extends Abs
private final String configResource;
private final String configName;
private String preferIPv4Stack;
- private ServiceRegistry serviceRegistry;
+
+ private ServiceRegistry localServiceRegistry;
+ private ServiceRegistry remoteServiceRegistry;
public AccessStrategyTestSetup(Test test, String configName) {
this(test, configName, null);
@@ -539,19 +540,13 @@ public abstract class AbstractCollectionRegionAccessStrategyTestCase extends Abs
preferIPv4Stack = System.getProperty(PREFER_IPV4STACK);
System.setProperty(PREFER_IPV4STACK, "true");
- serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( Environment.getProperties() );
+ localCfg = createConfiguration(configName, configResource);
+ localServiceRegistry = ServiceRegistryBuilder.buildServiceRegistry( localCfg.getProperties() );
+ localRegionFactory = CacheTestUtil.startRegionFactory( localServiceRegistry, localCfg );
- localCfg = createConfiguration(configName, configResource);
- localRegionFactory = CacheTestUtil.startRegionFactory(
- serviceRegistry.getService( JdbcServices.class ),
- localCfg
- );
-
- remoteCfg = createConfiguration(configName, configResource);
- remoteRegionFactory = CacheTestUtil.startRegionFactory(
- serviceRegistry.getService( JdbcServices.class ),
- remoteCfg
- );
+ remoteCfg = createConfiguration(configName, configResource);
+ remoteServiceRegistry = ServiceRegistryBuilder.buildServiceRegistry( remoteCfg.getProperties() );
+ remoteRegionFactory = CacheTestUtil.startRegionFactory( remoteServiceRegistry, remoteCfg );
}
@Override
@@ -573,8 +568,11 @@ public abstract class AbstractCollectionRegionAccessStrategyTestCase extends Abs
remoteRegionFactory.stop();
}
finally {
- if ( serviceRegistry != null ) {
- ServiceRegistryBuilder.destroy( serviceRegistry );
+ if ( localServiceRegistry != null ) {
+ ServiceRegistryBuilder.destroy( localServiceRegistry );
+ }
+ if ( remoteServiceRegistry != null ) {
+ ServiceRegistryBuilder.destroy( remoteServiceRegistry );
}
}
}
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/TransactionalExtraAPITestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/TransactionalExtraAPITestCase.java
index 70ce3a30c0..16bbbff6c0 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/TransactionalExtraAPITestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/TransactionalExtraAPITestCase.java
@@ -55,7 +55,7 @@ public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase
if (getCollectionAccessStrategy() == null) {
Configuration cfg = createConfiguration();
InfinispanRegionFactory rf = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ getServiceRegistry(), cfg, getCacheTestSupport()
);
// Sleep a bit to avoid concurrent FLUSH problem
@@ -93,30 +93,18 @@ public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase
localAccessStrategy = strategy;
}
- /**
- * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
- */
public void testLockItem() {
assertNull(getCollectionAccessStrategy().lockItem(KEY, new Integer(1)));
}
- /**
- * Test method for {@link TransactionalAccess#lockRegion()}.
- */
public void testLockRegion() {
assertNull(getCollectionAccessStrategy().lockRegion());
}
- /**
- * Test method for {@link TransactionalAccess#unlockItem(java.lang.Object, org.hibernate.cache.access.SoftLock)}.
- */
public void testUnlockItem() {
getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock());
}
- /**
- * Test method for {@link TransactionalAccess#unlockRegion(org.hibernate.cache.access.SoftLock)}.
- */
public void testUnlockRegion() {
getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock());
}
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractEntityRegionAccessStrategyTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractEntityRegionAccessStrategyTestCase.java
index b70c41ffd6..f7197cdf3a 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractEntityRegionAccessStrategyTestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractEntityRegionAccessStrategyTestCase.java
@@ -666,16 +666,10 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( Environment.getProperties() );
localCfg = createConfiguration(configName);
- localRegionFactory = CacheTestUtil.startRegionFactory(
- serviceRegistry.getService( JdbcServices.class ),
- localCfg
- );
+ localRegionFactory = CacheTestUtil.startRegionFactory( serviceRegistry, localCfg );
remoteCfg = createConfiguration(configName);
- remoteRegionFactory = CacheTestUtil.startRegionFactory(
- serviceRegistry.getService( JdbcServices.class ),
- remoteCfg
- );
+ remoteRegionFactory = CacheTestUtil.startRegionFactory( serviceRegistry, remoteCfg );
}
@Override
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/TransactionalExtraAPITestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/TransactionalExtraAPITestCase.java
index 0aac7c9792..bc04f1a625 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/TransactionalExtraAPITestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/TransactionalExtraAPITestCase.java
@@ -61,7 +61,7 @@ public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase
if (getEntityAccessStrategy() == null) {
Configuration cfg = createConfiguration();
InfinispanRegionFactory rf = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ getServiceRegistry(), cfg, getCacheTestSupport()
);
// Sleep a bit to avoid concurrent FLUSH problem
@@ -99,44 +99,26 @@ public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase
localAccessStrategy = strategy;
}
- /**
- * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
- */
public void testLockItem() {
assertNull(getEntityAccessStrategy().lockItem(KEY, new Integer(1)));
}
- /**
- * Test method for {@link TransactionalAccess#lockRegion()}.
- */
public void testLockRegion() {
assertNull(getEntityAccessStrategy().lockRegion());
}
- /**
- * Test method for {@link TransactionalAccess#unlockItem(java.lang.Object, org.hibernate.cache.access.SoftLock)}.
- */
public void testUnlockItem() {
getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock());
}
- /**
- * Test method for {@link TransactionalAccess#unlockRegion(org.hibernate.cache.access.SoftLock)}.
- */
public void testUnlockRegion() {
getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock());
}
- /**
- * Test method for {@link TransactionalAccess#afterInsert(java.lang.Object, java.lang.Object, java.lang.Object)}.
- */
public void testAfterInsert() {
assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterInsert(KEY, VALUE1, new Integer(1)));
}
- /**
- * Test method for {@link TransactionalAccess#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, org.hibernate.cache.access.SoftLock)}.
- */
public void testAfterUpdate() {
assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock()));
}
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicJdbcTransactionalTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicJdbcTransactionalTestCase.java
index e04b63b49f..9413afc309 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicJdbcTransactionalTestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicJdbcTransactionalTestCase.java
@@ -25,10 +25,10 @@ package org.hibernate.test.cache.infinispan.functional;
import java.util.Map;
import org.hibernate.Session;
+import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory;
+import org.hibernate.engine.transaction.spi.TransactionFactory;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;
-import org.hibernate.transaction.JDBCTransactionFactory;
-import org.hibernate.transaction.TransactionFactory;
import org.hibernate.transaction.TransactionManagerLookup;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
@@ -47,7 +47,7 @@ public class BasicJdbcTransactionalTestCase extends SingleNodeTestCase {
}
protected Class extends TransactionFactory> getTransactionFactoryClass() {
- return JDBCTransactionFactory.class;
+ return JdbcTransactionFactory.class;
}
protected Class extends TransactionManagerLookup> getTransactionManagerLookupClass() {
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/ConcurrentWriteTest.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/ConcurrentWriteTest.java
index 9f165aaf11..ddc37bc383 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/ConcurrentWriteTest.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/ConcurrentWriteTest.java
@@ -47,12 +47,12 @@ import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
import org.hibernate.stat.SecondLevelCacheStatistics;
+import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeJtaPlatformImpl;
import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeTestCase;
import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeConnectionProviderImpl;
import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeJtaTransactionManagerImpl;
-import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeTransactionManagerLookup;
-import org.hibernate.transaction.TransactionManagerLookup;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
@@ -104,12 +104,12 @@ public class ConcurrentWriteTest extends SingleNodeTestCase {
return DualNodeConnectionProviderImpl.class;
}
- @Override
- protected Class extends TransactionManagerLookup> getTransactionManagerLookupClass() {
- return DualNodeTransactionManagerLookup.class;
- }
+ @Override
+ protected Class extends JtaPlatform> getJtaPlatform() {
+ return DualNodeJtaPlatformImpl.class;
+ }
- /**
+ /**
* test that DB can be queried
*
* @throws java.lang.Exception
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/SingleNodeTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/SingleNodeTestCase.java
index 88ad695cfb..2764c14ea6 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/SingleNodeTestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/SingleNodeTestCase.java
@@ -7,13 +7,13 @@ import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
+import org.hibernate.engine.transaction.spi.TransactionFactory;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.test.cache.infinispan.tm.JtaPlatformImpl;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
-import org.hibernate.stat.SecondLevelCacheStatistics;
-import org.hibernate.stat.Statistics;
-import org.hibernate.transaction.CMTTransactionFactory;
-import org.hibernate.transaction.TransactionFactory;
-import org.hibernate.transaction.TransactionManagerLookup;
+import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
@@ -30,19 +30,22 @@ public abstract class SingleNodeTestCase extends FunctionalTestCase {
tm = getTransactionManager();
}
- protected TransactionManager getTransactionManager() {
- try {
- if (getTransactionManagerLookupClass() == null)
- return null;
- else
- return getTransactionManagerLookupClass().newInstance().getTransactionManager(null);
- } catch (Exception e) {
- log.error("Error", e);
- throw new RuntimeException(e);
- }
- }
+ protected TransactionManager getTransactionManager() {
+ try {
+ Class extends JtaPlatform> jtaPlatformClass = getJtaPlatform();
+ if ( jtaPlatformClass == null ) {
+ return null;
+ }
+ else {
+ return jtaPlatformClass.newInstance().retrieveTransactionManager();
+ }
+ }
+ catch (Exception e) {
+ log.error("Error", e);
+ throw new RuntimeException(e);
+ }
+ }
-
public String[] getMappings() {
return new String[] {
"cache/infinispan/functional/Item.hbm.xml",
@@ -67,9 +70,9 @@ public abstract class SingleNodeTestCase extends FunctionalTestCase {
return org.hibernate.test.cache.infinispan.tm.XaConnectionProvider.class;
}
- protected Class extends TransactionManagerLookup> getTransactionManagerLookupClass() {
- return org.hibernate.test.cache.infinispan.tm.XaTransactionManagerLookup.class;
- }
+ protected Class extends JtaPlatform> getJtaPlatform() {
+ return JtaPlatformImpl.class;
+ }
protected boolean getUseQueryCache() {
return true;
@@ -81,11 +84,12 @@ public abstract class SingleNodeTestCase extends FunctionalTestCase {
cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(getUseQueryCache()));
cfg.setProperty(Environment.CACHE_REGION_FACTORY, getCacheRegionFactory().getName());
- cfg.setProperty(Environment.CONNECTION_PROVIDER, getConnectionProviderClass().getName());
- if (getTransactionManagerLookupClass() != null) {
- cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, getTransactionManagerLookupClass().getName());
- }
- cfg.setProperty(Environment.TRANSACTION_STRATEGY, getTransactionFactoryClass().getName());
+
+ if ( getJtaPlatform() != null ) {
+ cfg.getProperties().put( JtaPlatformInitiator.JTA_PLATFORM, getJtaPlatform() );
+ }
+ cfg.setProperty( Environment.TRANSACTION_STRATEGY, getTransactionFactoryClass().getName() );
+ cfg.setProperty( Environment.CONNECTION_PROVIDER, getConnectionProviderClass().getName() );
}
protected void beginTx() throws Exception {
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java
index d737cd6c4c..344f626ef2 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java
@@ -34,14 +34,16 @@ import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.classic.Session;
+import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
+import org.hibernate.engine.transaction.spi.TransactionFactory;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.test.cache.infinispan.tm.JtaPlatformImpl;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.test.cache.infinispan.functional.Contact;
import org.hibernate.test.cache.infinispan.functional.Customer;
-import org.hibernate.transaction.CMTTransactionFactory;
-import org.hibernate.transaction.TransactionFactory;
-import org.hibernate.transaction.TransactionManagerLookup;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
@@ -82,9 +84,9 @@ public class BulkOperationsTestCase extends FunctionalTestCase {
return org.hibernate.test.cache.infinispan.tm.XaConnectionProvider.class;
}
- protected Class extends TransactionManagerLookup> getTransactionManagerLookupClass() {
- return org.hibernate.test.cache.infinispan.tm.XaTransactionManagerLookup.class;
- }
+ protected JtaPlatform getJtaPlatform() {
+ return new JtaPlatformImpl();
+ }
public void configure(Configuration cfg) {
super.configure(cfg);
@@ -92,16 +94,16 @@ public class BulkOperationsTestCase extends FunctionalTestCase {
cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
cfg.setProperty(Environment.USE_QUERY_CACHE, "false");
cfg.setProperty(Environment.CACHE_REGION_FACTORY, getCacheRegionFactory().getName());
- cfg.setProperty(Environment.CONNECTION_PROVIDER, getConnectionProviderClass().getName());
- cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, getTransactionManagerLookupClass().getName());
cfg.setProperty(Environment.TRANSACTION_STRATEGY, getTransactionFactoryClass().getName());
+ cfg.getProperties().put( JtaPlatformInitiator.JTA_PLATFORM, getJtaPlatform() );
+ cfg.setProperty(Environment.CONNECTION_PROVIDER, getConnectionProviderClass().getName());
}
public void testBulkOperations() throws Throwable {
log.info("*** testBulkOperations()");
boolean cleanedUp = false;
try {
- tm = getTransactionManagerLookupClass().newInstance().getTransactionManager(null);
+ tm = getJtaPlatform().retrieveTransactionManager();
createContacts();
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaPlatformImpl.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaPlatformImpl.java
new file mode 100644
index 0000000000..b376ef8148
--- /dev/null
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaPlatformImpl.java
@@ -0,0 +1,87 @@
+/*
+ * 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.test.cache.infinispan.functional.cluster;
+
+import org.hibernate.HibernateException;
+import org.hibernate.TransactionException;
+import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+import org.hibernate.service.spi.Configurable;
+
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+import java.util.Map;
+
+/**
+ * @author Steve Ebersole
+ */
+public class DualNodeJtaPlatformImpl implements JtaPlatform, Configurable {
+ private String nodeId;
+
+ @Override
+ public void configure(Map configurationValues) {
+ nodeId = (String) configurationValues.get( DualNodeTestCase.NODE_ID_PROP );
+ if ( nodeId == null ) {
+ throw new HibernateException(DualNodeTestCase.NODE_ID_PROP + " not configured");
+ }
+ }
+
+ @Override
+ public TransactionManager retrieveTransactionManager() {
+ return DualNodeJtaTransactionManagerImpl.getInstance( nodeId );
+ }
+
+ @Override
+ public UserTransaction retrieveUserTransaction() {
+ throw new TransactionException( "UserTransaction not used in these tests" );
+ }
+
+ @Override
+ public Object getTransactionIdentifier(Transaction transaction) {
+ return transaction;
+ }
+
+ @Override
+ public boolean canRegisterSynchronization() {
+ return JtaStatusHelper.isActive( retrieveTransactionManager() );
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization synchronization) {
+ try {
+ retrieveTransactionManager().getTransaction().registerSynchronization( synchronization );
+ }
+ catch (Exception e) {
+ throw new TransactionException( "Could not obtain transaction from TM" );
+ }
+ }
+
+ @Override
+ public int getCurrentStatus() throws SystemException {
+ return JtaStatusHelper.getStatus( retrieveTransactionManager() );
+ }
+}
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTestCase.java
index a63d0ea325..773901e536 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTestCase.java
@@ -30,9 +30,11 @@ import org.hibernate.cfg.Environment;
import org.hibernate.cfg.Mappings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
+import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
import org.hibernate.testing.junit.functional.ExecutionEnvironment;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
-import org.hibernate.transaction.CMTTransactionFactory;
+
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
@@ -133,20 +135,14 @@ public abstract class DualNodeTestCase extends FunctionalTestCase {
return DualNodeConnectionProviderImpl.class;
}
- protected Class getTransactionManagerLookupClass() {
- return DualNodeTransactionManagerLookup.class;
+ protected Class getJtaPlatformClass() {
+ return DualNodeJtaPlatformImpl.class;
}
protected Class getTransactionFactoryClass() {
return CMTTransactionFactory.class;
}
- /**
- * Apply any node-specific configurations to our first node.
- *
- * @param the
- * Configuration to update.
- */
protected void configureFirstNode(Configuration cfg) {
cfg.setProperty(NODE_ID_PROP, LOCAL);
}
@@ -155,12 +151,6 @@ public abstract class DualNodeTestCase extends FunctionalTestCase {
return Collections.singletonMap( NODE_ID_FIELD, LOCAL );
}
- /**
- * Apply any node-specific configurations to our second node.
- *
- * @param the
- * Configuration to update.
- */
protected void configureSecondNode(Configuration cfg) {
cfg.setProperty(NODE_ID_PROP, REMOTE);
}
@@ -186,7 +176,7 @@ public abstract class DualNodeTestCase extends FunctionalTestCase {
super.configure(cfg);
cfg.setProperty(Environment.CONNECTION_PROVIDER, getConnectionProviderClass().getName());
- cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, getTransactionManagerLookupClass().getName());
+ cfg.setProperty( JtaPlatformInitiator.JTA_PLATFORM, getJtaPlatformClass().getName());
cfg.setProperty(Environment.TRANSACTION_STRATEGY, getTransactionFactoryClass().getName());
cfg.setProperty(Environment.CACHE_REGION_FACTORY, getCacheRegionFactory().getName());
cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(getUseQueryCache()));
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java
index e1180116d9..ed711b955b 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java
@@ -91,7 +91,7 @@ public class QueryRegionImplTestCase extends AbstractGeneralDataRegionTestCase {
private void putDoesNotBlockGetTest() throws Exception {
Configuration cfg = createConfiguration();
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport());
+ getServiceRegistry(), cfg, getCacheTestSupport());
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
@@ -177,7 +177,7 @@ public class QueryRegionImplTestCase extends AbstractGeneralDataRegionTestCase {
private void getDoesNotBlockPutTest() throws Exception {
Configuration cfg = createConfiguration();
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ getServiceRegistry(), cfg, getCacheTestSupport()
);
// Sleep a bit to avoid concurrent FLUSH problem
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java
index afd8dfc663..c27080f2f0 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java
@@ -87,14 +87,14 @@ public class TimestampsRegionImplTestCase extends AbstractGeneralDataRegionTestC
public void testClearTimestampsRegionInIsolated() throws Exception {
Configuration cfg = createConfiguration();
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg, getCacheTestSupport()
+ getServiceRegistry(), cfg, getCacheTestSupport()
);
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
Configuration cfg2 = createConfiguration();
InfinispanRegionFactory regionFactory2 = CacheTestUtil.startRegionFactory(
- getJdbcServices(), cfg2, getCacheTestSupport()
+ getServiceRegistry(), cfg2, getCacheTestSupport()
);
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java
index 170655a2aa..cebf648378 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java
@@ -226,7 +226,7 @@ public class JBossStandaloneJtaExampleTest extends TestCase {
}
private void bindUserTransaction() throws Exception {
- // also the UserTransaction must be registered on jndi: org.hibernate.transaction.JTATransactionFactory#getUserTransaction() requires this
+ // also the UserTransaction must be registered on jndi: org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory#getUserTransaction() requires this
bind("UserTransaction", lookup.getUserTransaction(), lookup.getUserTransaction().getClass(), ctx);
}
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JtaPlatformImpl.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JtaPlatformImpl.java
new file mode 100644
index 0000000000..265b052497
--- /dev/null
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JtaPlatformImpl.java
@@ -0,0 +1,74 @@
+/*
+ * 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.test.cache.infinispan.tm;
+
+import org.hibernate.TransactionException;
+import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * @author Steve Ebersole
+ */
+public class JtaPlatformImpl implements JtaPlatform {
+ @Override
+ public TransactionManager retrieveTransactionManager() {
+ return XaTransactionManagerImpl.getInstance();
+ }
+
+ @Override
+ public UserTransaction retrieveUserTransaction() {
+ throw new TransactionException( "UserTransaction not used in these tests" );
+ }
+
+ @Override
+ public Object getTransactionIdentifier(Transaction transaction) {
+ return transaction;
+ }
+
+ @Override
+ public boolean canRegisterSynchronization() {
+ return JtaStatusHelper.isActive( XaTransactionManagerImpl.getInstance() );
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization synchronization) {
+ try {
+ XaTransactionManagerImpl.getInstance().getTransaction().registerSynchronization( synchronization );
+ }
+ catch (Exception e) {
+ throw new TransactionException( "Could not obtain transaction from TM" );
+ }
+ }
+
+ @Override
+ public int getCurrentStatus() throws SystemException {
+ return JtaStatusHelper.getStatus( XaTransactionManagerImpl.getInstance() );
+ }
+}
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java
deleted file mode 100644
index e6e2e5c3fb..0000000000
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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 software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.hibernate.test.cache.infinispan.tm;
-
-import java.util.Properties;
-
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-import org.hibernate.HibernateException;
-import org.hibernate.transaction.TransactionManagerLookup;
-
-/**
- * XaResourceCapableTransactionManagerLookup.
- *
- * @author Galder ZamarreƱo
- * @since 3.5
- */
-public class XaTransactionManagerLookup implements TransactionManagerLookup {
-
- public Object getTransactionIdentifier(Transaction transaction) {
- return transaction;
- }
-
- public TransactionManager getTransactionManager(Properties props) throws HibernateException {
- return XaTransactionManagerImpl.getInstance();
- }
-
- public String getUserTransactionName() {
- throw new UnsupportedOperationException( "jndi currently not implemented for these tests" );
- }
-
-}
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeJtaPlatform.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeJtaPlatform.java
new file mode 100644
index 0000000000..a5daab66c8
--- /dev/null
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeJtaPlatform.java
@@ -0,0 +1,82 @@
+/*
+ * 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.test.cache.infinispan.util;
+
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+
+import org.hibernate.HibernateException;
+import org.hibernate.TransactionException;
+import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
+import org.hibernate.service.jta.platform.spi.JtaPlatform;
+
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+/**
+ * @author Steve Ebersole
+ */
+public class BatchModeJtaPlatform implements JtaPlatform {
+ @Override
+ public TransactionManager retrieveTransactionManager() {
+ try {
+ return BatchModeTransactionManager.getInstance();
+ }
+ catch (Exception e) {
+ throw new HibernateException("Failed getting BatchModeTransactionManager", e);
+ }
+ }
+
+ @Override
+ public UserTransaction retrieveUserTransaction() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object getTransactionIdentifier(Transaction transaction) {
+ return transaction;
+ }
+
+ @Override
+ public boolean canRegisterSynchronization() {
+ return JtaStatusHelper.isActive( retrieveTransactionManager() );
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization synchronization) {
+ try {
+ retrieveTransactionManager().getTransaction().registerSynchronization( synchronization );
+ }
+ catch (Exception e) {
+ throw new TransactionException( "Could not obtain transaction from TM" );
+ }
+ }
+
+ @Override
+ public int getCurrentStatus() throws SystemException {
+ return JtaStatusHelper.getStatus( retrieveTransactionManager() );
+ }
+}
diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java
index 1db018c176..0d4ee1202a 100644
--- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java
+++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java
@@ -37,6 +37,8 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.cfg.Settings;
import org.hibernate.engine.jdbc.spi.JdbcServices;
+import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
+import org.hibernate.service.spi.ServiceRegistry;
/**
* Utilities for cache testing.
@@ -49,7 +51,7 @@ public class CacheTestUtil {
Configuration cfg = new Configuration();
cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
cfg.setProperty(Environment.USE_STRUCTURED_CACHE, "true");
- cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, BatchModeTransactionManagerLookup.class.getName());
+ cfg.setProperty( JtaPlatformInitiator.JTA_PLATFORM, BatchModeJtaPlatform.class.getName() );
cfg.setProperty(Environment.CACHE_REGION_FACTORY, regionFactory.getName());
cfg.setProperty(Environment.CACHE_REGION_PREFIX, regionPrefix);
@@ -72,11 +74,11 @@ public class CacheTestUtil {
return cfg;
}
- public static InfinispanRegionFactory startRegionFactory(JdbcServices jdbcServices,
- Configuration cfg)
- throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ public static InfinispanRegionFactory startRegionFactory(
+ ServiceRegistry serviceRegistry,
+ Configuration cfg) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
- Settings settings = cfg.buildSettings( jdbcServices );
+ Settings settings = cfg.buildSettings( serviceRegistry );
Properties properties = cfg.getProperties();
String factoryType = cfg.getProperty(Environment.CACHE_REGION_FACTORY);
@@ -88,11 +90,11 @@ public class CacheTestUtil {
return regionFactory;
}
- public static InfinispanRegionFactory startRegionFactory(JdbcServices jdbcServices,
- Configuration cfg,
- CacheTestSupport testSupport)
- throws ClassNotFoundException, InstantiationException, IllegalAccessException {
- InfinispanRegionFactory factory = startRegionFactory(jdbcServices, cfg);
+ public static InfinispanRegionFactory startRegionFactory(
+ ServiceRegistry serviceRegistry,
+ Configuration cfg,
+ CacheTestSupport testSupport) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ InfinispanRegionFactory factory = startRegionFactory( serviceRegistry, cfg );
testSupport.registerFactory(factory);
return factory;
}