Skip to content

Commit 453f0ff

Browse files
committed
improve exception messages and logging related to tx management
along with some minor aesthetic code cleanups
1 parent 47f1a12 commit 453f0ff

File tree

11 files changed

+160
-195
lines changed

11 files changed

+160
-195
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,13 @@ public interface Transaction extends EntityTransaction {
6969

7070
/**
7171
* Attempt to mark the underlying transaction for rollback only.
72+
* <p>
73+
* Unlike {@link #setRollbackOnly()}, which is specified by JPA
74+
* to throw when the transaction is inactive, this operation may
75+
* be called on an inactive transaction, in which case it has no
76+
* effect.
77+
*
78+
* @see #setRollbackOnly()
7279
*/
73-
default void markRollbackOnly() {
74-
setRollbackOnly();
75-
}
76-
80+
void markRollbackOnly();
7781
}

hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionImpl.java

Lines changed: 58 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import org.hibernate.engine.transaction.spi.TransactionImplementor;
1313
import org.hibernate.internal.AbstractSharedSessionContract;
1414
import org.hibernate.internal.CoreLogging;
15-
import org.hibernate.jpa.spi.JpaCompliance;
1615
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
1716
import org.hibernate.resource.transaction.spi.TransactionStatus;
1817

@@ -28,7 +27,7 @@ public class TransactionImpl implements TransactionImplementor {
2827
private static final Logger LOG = CoreLogging.logger( TransactionImpl.class );
2928

3029
private final TransactionCoordinator transactionCoordinator;
31-
private final JpaCompliance jpaCompliance;
30+
private final boolean jpaCompliance;
3231
private final AbstractSharedSessionContract session;
3332

3433
private TransactionDriver transactionDriverControl;
@@ -37,7 +36,9 @@ public TransactionImpl(
3736
TransactionCoordinator transactionCoordinator,
3837
AbstractSharedSessionContract session) {
3938
this.transactionCoordinator = transactionCoordinator;
40-
this.jpaCompliance = session.getFactory().getSessionFactoryOptions().getJpaCompliance();
39+
this.jpaCompliance =
40+
session.getFactory().getSessionFactoryOptions().getJpaCompliance()
41+
.isJpaTransactionComplianceEnabled();
4142
this.session = session;
4243

4344
if ( session.isOpen() && transactionCoordinator.isActive() ) {
@@ -47,11 +48,8 @@ public TransactionImpl(
4748
LOG.debug( "TransactionImpl created on closed Session/EntityManager" );
4849
}
4950

50-
if ( LOG.isDebugEnabled() ) {
51-
LOG.debugf(
52-
"On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == %s",
53-
jpaCompliance.isJpaTransactionComplianceEnabled()
54-
);
51+
if ( LOG.isDebugEnabled() && jpaCompliance ) {
52+
LOG.debugf( "TransactionImpl created in JPA compliant mode" );
5553
}
5654
}
5755

@@ -65,78 +63,66 @@ public void begin() {
6563
transactionDriverControl = transactionCoordinator.getTransactionDriverControl();
6664
}
6765

68-
// per-JPA
6966
if ( isActive() ) {
70-
if ( jpaCompliance.isJpaTransactionComplianceEnabled()
71-
|| !transactionCoordinator.getTransactionCoordinatorBuilder().isJta() ) {
72-
throw new IllegalStateException( "Transaction already active" );
67+
if ( jpaCompliance ) {
68+
throw new IllegalStateException( "Transaction already active (in JPA compliant mode)" );
7369
}
74-
else {
75-
return;
70+
else if ( !transactionCoordinator.getTransactionCoordinatorBuilder().isJta() ) {
71+
throw new IllegalStateException( "Resource-local transaction already active" );
7672
}
7773
}
78-
79-
LOG.debug( "begin" );
80-
81-
this.transactionDriverControl.begin();
74+
else {
75+
LOG.debug( "begin transaction" );
76+
transactionDriverControl.begin();
77+
}
8278
}
8379

8480
@Override
8581
public void commit() {
82+
// allow MARKED_ROLLBACK to propagate through to transactionDriverControl
83+
// the boolean passed to isActive indicates whether MARKED_ROLLBACK should
84+
// be considered active
8685
if ( !isActive( true ) ) {
87-
// allow MARKED_ROLLBACK to propagate through to transactionDriverControl
88-
// the boolean passed to isActive indicates whether MARKED_ROLLBACK should be
89-
// considered active
90-
//
91-
// essentially here we have a transaction that is not active and
92-
// has not been marked for rollback only
86+
// we have a transaction that is inactive and has not been marked for rollback only
9387
throw new IllegalStateException( "Transaction not successfully started" );
9488
}
95-
96-
LOG.debug( "committing" );
97-
98-
try {
99-
internalGetTransactionDriverControl().commit();
100-
}
101-
catch (RuntimeException e) {
102-
throw session.getExceptionConverter().convertCommitException( e );
89+
else {
90+
LOG.debug( "committing transaction" );
91+
try {
92+
internalGetTransactionDriverControl().commit();
93+
}
94+
catch (RuntimeException e) {
95+
throw session.getExceptionConverter().convertCommitException( e );
96+
}
10397
}
10498
}
10599

106100
public TransactionDriver internalGetTransactionDriverControl() {
107101
// NOTE here to help be a more descriptive NullPointerException
108-
if ( this.transactionDriverControl == null ) {
102+
if ( transactionDriverControl == null ) {
109103
throw new IllegalStateException( "Transaction was not properly begun/started" );
110104
}
111-
return this.transactionDriverControl;
105+
else {
106+
return transactionDriverControl;
107+
}
112108
}
113109

114110
@Override
115111
public void rollback() {
116-
if ( !isActive() ) {
117-
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
118-
119-
throw new IllegalStateException(
120-
"JPA compliance dictates throwing IllegalStateException when #rollback " +
121-
"is called on non-active transaction"
122-
);
123-
}
112+
if ( !isActive() && jpaCompliance ) {
113+
throw new IllegalStateException( "rollback() called on inactive transaction (in JPA compliant mode)" );
124114
}
125115

126-
TransactionStatus status = getStatus();
116+
final TransactionStatus status = getStatus();
127117
if ( status == TransactionStatus.ROLLED_BACK || status == TransactionStatus.NOT_ACTIVE ) {
128-
// Allow rollback() calls on completed transactions, just no-op.
118+
// allow rollback() on completed transaction as noop
129119
LOG.debug( "rollback() called on an inactive transaction" );
130-
return;
131120
}
132-
133-
if ( !status.canRollback() ) {
134-
throw new TransactionException( "Cannot rollback transaction in current status [" + status.name() + "]" );
121+
else if ( !status.canRollback() ) {
122+
throw new TransactionException( "Cannot roll back transaction in current status [" + status.name() + "]" );
135123
}
136-
137-
LOG.debug( "rolling back" );
138-
139-
if ( status != TransactionStatus.FAILED_COMMIT || allowFailedCommitToPhysicallyRollback() ) {
124+
else if ( status != TransactionStatus.FAILED_COMMIT || allowFailedCommitToPhysicallyRollback() ) {
125+
LOG.debug( "rolling back transaction" );
140126
internalGetTransactionDriverControl().rollback();
141127
}
142128
}
@@ -176,55 +162,50 @@ public TransactionStatus getStatus() {
176162

177163
@Override
178164
public void registerSynchronization(Synchronization synchronization) throws HibernateException {
179-
this.transactionCoordinator.getLocalSynchronizations().registerSynchronization( synchronization );
165+
transactionCoordinator.getLocalSynchronizations().registerSynchronization( synchronization );
180166
}
181167

182168
@Override
183169
public void setTimeout(int seconds) {
184-
this.transactionCoordinator.setTimeOut( seconds );
170+
transactionCoordinator.setTimeOut( seconds );
185171
}
186172

187173
@Override
188174
public void setTimeout(@Nullable Integer seconds) {
189-
this.transactionCoordinator.setTimeOut( seconds == null ? -1 : seconds );
175+
transactionCoordinator.setTimeOut( seconds == null ? -1 : seconds );
190176
}
191177

192178
@Override
193179
public @Nullable Integer getTimeout() {
194-
final int timeOut = this.transactionCoordinator.getTimeOut();
195-
if ( timeOut == -1 ) {
196-
return null;
197-
}
198-
return timeOut;
180+
final int timeout = transactionCoordinator.getTimeOut();
181+
return timeout == -1 ? null : timeout;
199182
}
200183

201184
@Override
202185
public void markRollbackOnly() {
203-
// this is the Hibernate-specific API, whereas #setRollbackOnly is the
204-
// JPA-defined API. In our opinion it is much more user-friendly to
186+
// this is the Hibernate-specific API, whereas setRollbackOnly is the
187+
// JPA-defined API. In our opinion it is much more user-friendly to
205188
// always allow user/integration to indicate that the transaction
206189
// should not be allowed to commit.
207190
//
208-
// However.. should only "do something" on an active transaction
209191
if ( isActive() ) {
210192
internalGetTransactionDriverControl().markRollbackOnly();
211193
}
194+
// else noop for an inactive transaction
212195
}
213196

214197
@Override
215198
public void setRollbackOnly() {
216199
if ( !isActive() ) {
217-
// Since this is the JPA-defined one, we make sure the txn is active first
218-
// so long as compliance (JpaCompliance) has not been defined to disable
219-
// that check - making this active more like Hibernate's #markRollbackOnly
220-
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
221-
throw new IllegalStateException(
222-
"JPA compliance dictates throwing IllegalStateException when #setRollbackOnly " +
223-
"is called on non-active transaction"
224-
);
200+
if ( jpaCompliance ) {
201+
// This is the JPA-defined version of this operation,
202+
// so we must check that the transaction is active
203+
throw new IllegalStateException( "setRollbackOnly() called on inactive transaction (in JPA compliant mode)" );
225204
}
226205
else {
227-
LOG.debug( "#setRollbackOnly called on a not-active transaction" );
206+
// JpaCompliance disables the check, so this method
207+
// is equivalent our native markRollbackOnly()
208+
LOG.debug( "setRollbackOnly() called on a inactive transaction" );
228209
}
229210
}
230211
else {
@@ -234,16 +215,12 @@ public void setRollbackOnly() {
234215

235216
@Override
236217
public boolean getRollbackOnly() {
237-
if ( !isActive() ) {
238-
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
239-
throw new IllegalStateException(
240-
"JPA compliance dictates throwing IllegalStateException when #getRollbackOnly " +
241-
"is called on non-active transaction"
242-
);
243-
}
218+
if ( jpaCompliance && !isActive() ) {
219+
throw new IllegalStateException( "getRollbackOnly() called on inactive transaction (in JPA compliant mode)" );
220+
}
221+
else {
222+
return getStatus() == TransactionStatus.MARKED_ROLLBACK;
244223
}
245-
246-
return getStatus() == TransactionStatus.MARKED_ROLLBACK;
247224
}
248225

249226
protected boolean allowFailedCommitToPhysicallyRollback() {

hibernate-core/src/main/java/org/hibernate/internal/ExceptionConverterImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public RuntimeException convertCommitException(RuntimeException exception) {
6363
catch (Exception re) {
6464
//swallow
6565
}
66-
return new RollbackException( "Error while committing the transaction",
66+
return new RollbackException( "Error while committing the transaction [" + exception.getMessage() + "]",
6767
exception instanceof HibernateException hibernateException
6868
? convert( hibernateException )
6969
: exception );

hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -358,18 +358,16 @@ CacheRetrieveMode getCacheRetrieveMode(Map<String, Object> properties) {
358358

359359
private static CacheRetrieveMode determineCacheRetrieveMode(Map<String, Object> settings) {
360360
final CacheRetrieveMode cacheRetrieveMode = (CacheRetrieveMode) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE );
361-
if ( cacheRetrieveMode == null ) {
362-
return (CacheRetrieveMode) settings.get( JAKARTA_SHARED_CACHE_RETRIEVE_MODE );
363-
}
364-
return cacheRetrieveMode;
361+
return cacheRetrieveMode == null
362+
? (CacheRetrieveMode) settings.get( JAKARTA_SHARED_CACHE_RETRIEVE_MODE )
363+
: cacheRetrieveMode;
365364
}
366365

367366
private static CacheStoreMode determineCacheStoreMode(Map<String, Object> settings) {
368367
final CacheStoreMode cacheStoreMode = (CacheStoreMode) settings.get( JPA_SHARED_CACHE_STORE_MODE );
369-
if ( cacheStoreMode == null ) {
370-
return ( CacheStoreMode ) settings.get( JAKARTA_SHARED_CACHE_STORE_MODE );
371-
}
372-
return cacheStoreMode;
368+
return cacheStoreMode == null
369+
? (CacheStoreMode) settings.get( JAKARTA_SHARED_CACHE_STORE_MODE )
370+
: cacheStoreMode;
373371
}
374372

375373
public JdbcValuesMappingProducerProvider getJdbcValuesMappingProducerProvider() {

hibernate-core/src/main/java/org/hibernate/jpa/internal/MutableJpaComplianceImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,15 @@ public void setLoadByIdCompliance(boolean enabled) {
169169

170170
@Override
171171
public JpaCompliance immutableCopy() {
172-
JpaComplianceImpl.JpaComplianceBuilder builder = new JpaComplianceImpl.JpaComplianceBuilder();
173-
builder = builder.setProxyCompliance( proxyCompliance )
172+
return new JpaComplianceImpl.JpaComplianceBuilder()
173+
.setProxyCompliance( proxyCompliance )
174174
.setOrderByMappingCompliance( orderByMappingCompliance )
175175
.setGlobalGeneratorNameCompliance( generatorNameScopeCompliance )
176176
.setQueryCompliance( queryCompliance )
177177
.setTransactionCompliance( transactionCompliance )
178178
.setClosedCompliance( closedCompliance )
179179
.setCachingCompliance( cachingCompliance )
180-
.setLoadByIdCompliance( loadByIdCompliance );
181-
return builder.createJpaCompliance();
180+
.setLoadByIdCompliance( loadByIdCompliance )
181+
.createJpaCompliance();
182182
}
183183
}

0 commit comments

Comments
 (0)