Skip to content

Commit b476094

Browse files
dreab8sebersole
authored andcommitted
HHH-9747 - Import initial reworking of transaction handling (based on JdbcSession work)
1 parent 82b312d commit b476094

File tree

192 files changed

+5718
-5460
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

192 files changed

+5718
-5460
lines changed

hibernate-core/src/main/java/org/hibernate/EmptyInterceptor.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,9 @@ public void onCollectionRecreate(Object collection, Serializable key) throws Cal
148148
@Override
149149
public void onCollectionUpdate(Object collection, Serializable key) throws CallbackException {
150150
}
151-
151+
152+
@Override
153+
public String inspect(String sql) {
154+
return this.onPrepareStatement( sql );
155+
}
152156
}

hibernate-core/src/main/java/org/hibernate/Interceptor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.io.Serializable;
2727
import java.util.Iterator;
2828

29+
import org.hibernate.resource.jdbc.spi.StatementInspector;
2930
import org.hibernate.type.Type;
3031

3132
/**
@@ -52,7 +53,7 @@
5253
*
5354
* @author Gavin King
5455
*/
55-
public interface Interceptor {
56+
public interface Interceptor extends StatementInspector {
5657
/**
5758
* Called just before an object is initialized. The interceptor may change the <tt>state</tt>, which will
5859
* be propagated to the persistent object. Note that when this method is called, <tt>entity</tt> will be

hibernate-core/src/main/java/org/hibernate/Transaction.java

Lines changed: 9 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525

2626
import javax.transaction.Synchronization;
2727

28+
import org.hibernate.engine.transaction.spi.IsolationDelegate;
2829
import org.hibernate.engine.transaction.spi.LocalStatus;
30+
import org.hibernate.resource.transaction.spi.TransactionStatus;
2931

3032
/**
3133
* Defines the contract for abstracting applications from the configured underlying means of transaction management.
@@ -44,12 +46,6 @@
4446
* @author Steve Ebersole
4547
*/
4648
public interface Transaction {
47-
/**
48-
* Is this transaction the initiator of any underlying transaction?
49-
*
50-
* @return {@code true} if this transaction initiated the underlying transaction; {@code false} otherwise.
51-
*/
52-
public boolean isInitiator();
5349

5450
/**
5551
* Begin this transaction. No-op if the transaction has already been begun. Note that this is not necessarily
@@ -93,58 +89,7 @@ public interface Transaction {
9389
*
9490
* @return The current local status.
9591
*/
96-
public LocalStatus getLocalStatus();
97-
98-
/**
99-
* Is this transaction still active?
100-
* <p/>
101-
* Answers on a best effort basis. For example, in the case of JDBC based transactions we cannot know that a
102-
* transaction is active when it is initiated directly through the JDBC {@link java.sql.Connection}, only when
103-
* it is initiated from here.
104-
*
105-
* @return {@code true} if the transaction is still active; {@code false} otherwise.
106-
*
107-
* @throws HibernateException Indicates a problem checking the transaction status.
108-
*/
109-
public boolean isActive();
110-
111-
/**
112-
* Is Hibernate participating in the underlying transaction?
113-
* <p/>
114-
* Generally speaking this will be the same as {@link #isActive()}.
115-
*
116-
* @return {@code true} if Hibernate is known to be participating in the underlying transaction; {@code false}
117-
* otherwise.
118-
*/
119-
public boolean isParticipating();
120-
121-
/**
122-
* Was this transaction committed?
123-
* <p/>
124-
* Answers on a best effort basis. For example, in the case of JDBC based transactions we cannot know that a
125-
* transaction was committed when the commit was performed directly through the JDBC {@link java.sql.Connection},
126-
* only when the commit was done from this.
127-
*
128-
* @return {@code true} if the transaction is rolled back; {@code false} otherwise.
129-
*
130-
* @throws HibernateException Indicates a problem checking the transaction status.
131-
*/
132-
@SuppressWarnings( {"UnusedDeclaration"})
133-
public boolean wasCommitted();
134-
135-
/**
136-
* Was this transaction rolled back or set to rollback only?
137-
* <p/>
138-
* Answers on a best effort basis. For example, in the case of JDBC based transactions we cannot know that a
139-
* transaction was rolled back when rollback was performed directly through the JDBC {@link java.sql.Connection},
140-
* only when it was rolled back from here.
141-
*
142-
* @return {@literal true} if the transaction is rolled back; {@literal false} otherwise.
143-
*
144-
* @throws HibernateException Indicates a problem checking the transaction status.
145-
*/
146-
@SuppressWarnings( {"UnusedDeclaration"})
147-
public boolean wasRolledBack();
92+
public TransactionStatus getStatus();
14893

14994
/**
15095
* Register a user synchronization callback for this transaction.
@@ -168,4 +113,10 @@ public interface Transaction {
168113
* @return The timeout, in seconds.
169114
*/
170115
public int getTimeout();
116+
117+
/**
118+
* Make a best effort to mark the underlying transaction for rollback only.
119+
*/
120+
public void markRollbackOnly();
121+
171122
}

hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@
6060
import org.hibernate.engine.config.spi.ConfigurationService;
6161
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
6262
import org.hibernate.engine.jdbc.spi.JdbcServices;
63-
import org.hibernate.engine.transaction.spi.TransactionFactory;
6463
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
6564
import org.hibernate.internal.SessionFactoryImpl;
6665
import org.hibernate.internal.util.config.ConfigurationHelper;
6766
import org.hibernate.loader.BatchFetchStyle;
6867
import org.hibernate.proxy.EntityNotFoundDelegate;
68+
import org.hibernate.resource.transaction.TransactionCoordinatorBuilder;
6969
import org.hibernate.service.spi.ServiceRegistryImplementor;
7070
import org.hibernate.tuple.entity.EntityTuplizer;
7171
import org.hibernate.tuple.entity.EntityTuplizerFactory;
@@ -113,6 +113,7 @@
113113
import static org.hibernate.cfg.AvailableSettings.USE_STRUCTURED_CACHE;
114114
import static org.hibernate.cfg.AvailableSettings.WRAP_RESULT_SETS;
115115
import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN;
116+
import static org.hibernate.cfg.AvailableSettings.PREFER_USER_TRANSACTION;
116117

117118
/**
118119
* @author Gail Badner
@@ -532,6 +533,7 @@ public static class SessionFactoryOptionsStateStandardImpl implements SessionFac
532533
private boolean wrapResultSetsEnabled;
533534

534535
private Map<String, SQLFunction> sqlFunctions;
536+
private boolean preferUserTransaction;
535537

536538
public SessionFactoryOptionsStateStandardImpl(StandardServiceRegistry serviceRegistry) {
537539
this.serviceRegistry = serviceRegistry;
@@ -683,13 +685,16 @@ public SessionFactoryOptionsStateStandardImpl(StandardServiceRegistry serviceReg
683685

684686
final String releaseModeName = ConfigurationHelper.getString( RELEASE_CONNECTIONS, configurationSettings, "auto" );
685687
if ( "auto".equals( releaseModeName ) ) {
686-
this.connectionReleaseMode = serviceRegistry.getService( TransactionFactory.class ).getDefaultReleaseMode();
688+
this.connectionReleaseMode = serviceRegistry.getService( TransactionCoordinatorBuilder.class )
689+
.getDefaultConnectionReleaseMode();
687690
}
688691
else {
689692
connectionReleaseMode = ConnectionReleaseMode.parse( releaseModeName );
690693
}
691694

692695
this.commentsEnabled = ConfigurationHelper.getBoolean( USE_SQL_COMMENTS, configurationSettings );
696+
697+
this.preferUserTransaction = ConfigurationHelper.getBoolean( PREFER_USER_TRANSACTION, configurationSettings, false );
693698
}
694699

695700
@Override
@@ -947,6 +952,10 @@ public Map<String, SQLFunction> getCustomSqlFunctionMap() {
947952
return sqlFunctions == null ? Collections.<String, SQLFunction>emptyMap() : sqlFunctions;
948953
}
949954

955+
@Override
956+
public boolean isPreferUserTransaction() {
957+
return this.preferUserTransaction;
958+
}
950959
}
951960

952961
@Override

hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorBuilder.java

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,6 @@
7474
import org.hibernate.dialect.SybaseAnywhereDialect;
7575
import org.hibernate.dialect.TeradataDialect;
7676
import org.hibernate.dialect.TimesTenDialect;
77-
import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory;
78-
import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
79-
import org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory;
8077
import org.hibernate.engine.transaction.jta.platform.internal.BitronixJtaPlatform;
8178
import org.hibernate.engine.transaction.jta.platform.internal.BorlandEnterpriseServerJtaPlatform;
8279
import org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform;
@@ -92,7 +89,6 @@
9289
import org.hibernate.engine.transaction.jta.platform.internal.WebSphereJtaPlatform;
9390
import org.hibernate.engine.transaction.jta.platform.internal.WeblogicJtaPlatform;
9491
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
95-
import org.hibernate.engine.transaction.spi.TransactionFactory;
9692
import org.hibernate.event.internal.EntityCopyAllowedLoggedObserver;
9793
import org.hibernate.event.internal.EntityCopyAllowedObserver;
9894
import org.hibernate.event.internal.EntityCopyNotAllowedObserver;
@@ -165,7 +161,7 @@ public StrategySelector buildSelector(ClassLoaderService classLoaderService) {
165161
// build the baseline...
166162
addDialects( strategySelector );
167163
addJtaPlatforms( strategySelector );
168-
addTransactionFactories( strategySelector );
164+
// addTransactionFactories( strategySelector );
169165
addMultiTableBulkIdStrategies( strategySelector );
170166
addEntityCopyObserverStrategies( strategySelector );
171167

@@ -355,16 +351,16 @@ private void addJtaPlatforms(StrategySelectorImpl strategySelector, Class<? exte
355351
}
356352
}
357353

358-
private void addTransactionFactories(StrategySelectorImpl strategySelector) {
359-
strategySelector.registerStrategyImplementor( TransactionFactory.class, JdbcTransactionFactory.SHORT_NAME, JdbcTransactionFactory.class );
360-
strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.JDBCTransactionFactory", JdbcTransactionFactory.class );
361-
362-
strategySelector.registerStrategyImplementor( TransactionFactory.class, JtaTransactionFactory.SHORT_NAME, JtaTransactionFactory.class );
363-
strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.JTATransactionFactory", JtaTransactionFactory.class );
364-
365-
strategySelector.registerStrategyImplementor( TransactionFactory.class, CMTTransactionFactory.SHORT_NAME, CMTTransactionFactory.class );
366-
strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.CMTTransactionFactory", CMTTransactionFactory.class );
367-
}
354+
// private void addTransactionFactories(StrategySelectorImpl strategySelector) {
355+
// strategySelector.registerStrategyImplementor( TransactionFactory.class, JdbcTransactionFactory.SHORT_NAME, JdbcTransactionFactory.class );
356+
// strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.JDBCTransactionFactory", JdbcTransactionFactory.class );
357+
//
358+
// strategySelector.registerStrategyImplementor( TransactionFactory.class, JtaTransactionFactory.SHORT_NAME, JtaTransactionFactory.class );
359+
// strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.JTATransactionFactory", JtaTransactionFactory.class );
360+
//
361+
// strategySelector.registerStrategyImplementor( TransactionFactory.class, CMTTransactionFactory.SHORT_NAME, CMTTransactionFactory.class );
362+
// strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.CMTTransactionFactory", CMTTransactionFactory.class );
363+
// }
368364

369365
private void addMultiTableBulkIdStrategies(StrategySelectorImpl strategySelector) {
370366
strategySelector.registerStrategyImplementor(

hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,6 @@ public interface SessionFactoryOptions {
183183
public Map<String, SQLFunction> getCustomSqlFunctionMap();
184184

185185
void setCheckNullability(boolean enabled);
186+
187+
public boolean isPreferUserTransaction();
186188
}

hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,10 @@ public interface AvailableSettings {
282282
String CURRENT_SESSION_CONTEXT_CLASS = "hibernate.current_session_context_class";
283283

284284
/**
285-
* Names the implementation of {@link org.hibernate.engine.transaction.spi.TransactionFactory} to use for
286-
* creating {@link org.hibernate.Transaction} instances
285+
* Names the implementation of {@link org.hibernate.resource.transaction.TransactionCoordinatorBuilder} to use for
286+
* creating {@link org.hibernate.resource.transaction.TransactionCoordinator} instances
287287
*/
288-
String TRANSACTION_STRATEGY = "hibernate.transaction.factory_class";
288+
String TRANSACTION_COORDINATOR_STRATEGY = "hibernate.transaction.coordinator_class";
289289

290290
/**
291291
* Names the {@link org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform} implementation to use for integrating
@@ -807,4 +807,13 @@ public interface AvailableSettings {
807807
* annotations (combined with {@code orm.xml} mappings).
808808
*/
809809
String ARTIFACT_PROCESSING_ORDER = "hibernate.mapping.precedence";
810+
811+
/**
812+
* Used to specify if using {@link javax.transaction.UserTransaction} class to use for JTA transaction management.
813+
*
814+
* Default is <code>false</code>
815+
*
816+
* @since 5.0
817+
*/
818+
String PREFER_USER_TRANSACTION = "hibernate.jta.prefer_user_transaction";
810819
}

hibernate-core/src/main/java/org/hibernate/cfg/Settings.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,4 +329,8 @@ public void setCheckNullability(boolean enabled) {
329329
// ugh, used by org.hibernate.cfg.beanvalidation.TypeSafeActivator as part of the BV integrator
330330
sessionFactoryOptions.setCheckNullability( enabled );
331331
}
332+
333+
public boolean isPreferUserTransaction() {
334+
return sessionFactoryOptions.isPreferUserTransaction();
335+
}
332336
}

hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,7 @@ else if ( !session.isConnected() ) {
242242
}
243243

244244
if ( isTempSession ) {
245-
isJTA = session.getTransactionCoordinator()
246-
.getTransactionContext().getTransactionEnvironment()
247-
.getTransactionFactory()
248-
.compatibleWithJtaSynchronization();
245+
isJTA = session.getTransactionCoordinator().getTransactionCoordinatorBuilder().isJta();
249246

250247
if ( !isJTA ) {
251248
// Explicitly handle the transactions only if we're not in

hibernate-core/src/main/java/org/hibernate/context/internal/ThreadLocalSessionContext.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@
4343
import org.hibernate.engine.jdbc.LobCreationContext;
4444
import org.hibernate.engine.spi.SessionFactoryImplementor;
4545
import org.hibernate.engine.spi.SessionImplementor;
46-
import org.hibernate.engine.transaction.spi.TransactionContext;
4746
import org.hibernate.event.spi.EventSource;
4847
import org.hibernate.internal.CoreMessageLogger;
48+
import org.hibernate.resource.transaction.spi.TransactionStatus;
4949

5050
import org.jboss.logging.Logger;
5151

@@ -81,7 +81,6 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
8181
Session.class,
8282
SessionImplementor.class,
8383
EventSource.class,
84-
TransactionContext.class,
8584
LobCreationContext.class
8685
};
8786

@@ -220,7 +219,7 @@ private static void cleanupAnyOrphanedSession(SessionFactory factory) {
220219
if ( orphan != null ) {
221220
LOG.alreadySessionBound();
222221
try {
223-
if ( orphan.getTransaction() != null && orphan.getTransaction().isActive() ) {
222+
if ( orphan.getTransaction() != null && orphan.getTransaction().getStatus() == TransactionStatus.ACTIVE ) {
224223
try {
225224
orphan.getTransaction().rollback();
226225
}
@@ -333,7 +332,7 @@ else if ( !realSession.isOpen() ) {
333332
// but we capture that there simply to doAfterTransactionCompletion the unbind...
334333
LOG.tracef( "Allowing invocation [%s] to proceed to real (closed) session", methodName );
335334
}
336-
else if ( !realSession.getTransaction().isActive() ) {
335+
else if ( realSession.getTransaction().getStatus() != TransactionStatus.ACTIVE ) {
337336
// limit the methods available if no transaction is active
338337
if ( "beginTransaction".equals( methodName )
339338
|| "getTransaction".equals( methodName )

hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
7373
final SessionFactoryImplementor factory = session.getFactory();
7474
try {
7575
try {
76-
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
76+
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
7777
try {
7878
getLockable().getIdentifierType().nullSafeSet( st, id, 1, session );
7979
if ( getLockable().isVersioned() ) {
@@ -85,7 +85,7 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
8585
);
8686
}
8787

88-
final ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
88+
final ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
8989
try {
9090
if ( !rs.next() ) {
9191
if ( factory.getStatistics().isStatisticsEnabled() ) {
@@ -96,11 +96,12 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
9696
}
9797
}
9898
finally {
99-
session.getTransactionCoordinator().getJdbcCoordinator().release( rs, st );
99+
session.getJdbcCoordinator().getResourceRegistry().release( rs, st );
100100
}
101101
}
102102
finally {
103-
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
103+
session.getJdbcCoordinator().getResourceRegistry().release( st );
104+
session.getJdbcCoordinator().afterStatementExecution();
104105
}
105106

106107
}

hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
9292
final SessionFactoryImplementor factory = session.getFactory();
9393
try {
9494
try {
95-
final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
95+
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
9696
try {
9797
lockable.getVersionType().nullSafeSet( st, version, 1, session );
9898
int offset = 2;
@@ -104,7 +104,7 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
104104
lockable.getVersionType().nullSafeSet( st, version, offset, session );
105105
}
106106

107-
final int affected = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
107+
final int affected = session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
108108
// todo: should this instead check for exactly one row modified?
109109
if ( affected < 0 ) {
110110
if (factory.getStatistics().isStatisticsEnabled()) {
@@ -115,7 +115,8 @@ public void lock(Serializable id, Object version, Object object, int timeout, Se
115115

116116
}
117117
finally {
118-
session.getTransactionCoordinator().getJdbcCoordinator().release( st );
118+
session.getJdbcCoordinator().getResourceRegistry().release( st );
119+
session.getJdbcCoordinator().afterStatementExecution();
119120
}
120121

121122
}

0 commit comments

Comments
 (0)