- Add new configuration setting ALLOW_JTA_TRANSACTION_ACCESS. Uses can use this setting to
override default JPA behavior for transaction access if needed. - Added new SPI method accessTransaction() which bypasses checks and returns the current or new transaction.
This commit is contained in:
parent
f826b7d5e8
commit
0f2ced4668
|
@ -60,6 +60,7 @@ import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
|||
import org.jboss.logging.Logger;
|
||||
|
||||
import static org.hibernate.cfg.AvailableSettings.ACQUIRE_CONNECTIONS;
|
||||
import static org.hibernate.cfg.AvailableSettings.ALLOW_JTA_TRANSACTION_ACCESS;
|
||||
import static org.hibernate.cfg.AvailableSettings.AUTO_CLOSE_SESSION;
|
||||
import static org.hibernate.cfg.AvailableSettings.AUTO_EVICT_COLLECTION_CACHE;
|
||||
import static org.hibernate.cfg.AvailableSettings.AUTO_SESSION_EVENTS_LISTENER;
|
||||
|
@ -480,6 +481,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
|||
this.options.jpaBootstrap = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableJtaTransactionAccess() {
|
||||
this.options.jtaTransactionAccessEnabled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryOptions buildSessionFactoryOptions() {
|
||||
return new SessionFactoryOptionsImpl( this );
|
||||
|
@ -504,6 +510,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
|||
// Session behavior
|
||||
private boolean flushBeforeCompletionEnabled;
|
||||
private boolean autoCloseSessionEnabled;
|
||||
private boolean jtaTransactionAccessEnabled;
|
||||
|
||||
// (JTA) transaction handling
|
||||
private boolean jtaTrackByThread;
|
||||
|
@ -594,6 +601,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
|||
BOOLEAN,
|
||||
true
|
||||
);
|
||||
this.jtaTransactionAccessEnabled = cfgService.getSetting(
|
||||
ALLOW_JTA_TRANSACTION_ACCESS,
|
||||
BOOLEAN,
|
||||
true
|
||||
);
|
||||
|
||||
this.flushBeforeCompletionEnabled = cfgService.getSetting( FLUSH_BEFORE_COMPLETION, BOOLEAN, true );
|
||||
this.autoCloseSessionEnabled = cfgService.getSetting( AUTO_CLOSE_SESSION, BOOLEAN, false );
|
||||
|
@ -848,6 +860,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
|||
return jpaBootstrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJtaTransactionAccessEnabled() {
|
||||
return jtaTransactionAccessEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBeanManagerReference() {
|
||||
return beanManagerReference;
|
||||
|
@ -1134,6 +1151,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
|||
return options.isJpaBootstrap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJtaTransactionAccessEnabled() {
|
||||
return options.isJtaTransactionAccessEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBeanManagerReference() {
|
||||
return options.getBeanManagerReference();
|
||||
|
|
|
@ -51,6 +51,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
|||
// Session behavior
|
||||
private final boolean flushBeforeCompletionEnabled;
|
||||
private final boolean autoCloseSessionEnabled;
|
||||
private boolean jtaTransactionAccessEnabled;
|
||||
|
||||
// transaction handling
|
||||
private final boolean jtaTrackByThread;
|
||||
|
@ -124,6 +125,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
|||
this.validatorFactoryReference = state.getValidatorFactoryReference();
|
||||
|
||||
this.jpaBootstrap = state.isJpaBootstrap();
|
||||
this.jtaTransactionAccessEnabled = state.isJtaTransactionAccessEnabled();
|
||||
this.sessionFactoryName = state.getSessionFactoryName();
|
||||
this.sessionFactoryNameAlsoJndiName = state.isSessionFactoryNameAlsoJndiName();
|
||||
|
||||
|
@ -197,6 +199,11 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
|||
return jpaBootstrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJtaTransactionAccessEnabled() {
|
||||
return jtaTransactionAccessEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBeanManagerReference() {
|
||||
return beanManagerReference;
|
||||
|
|
|
@ -46,6 +46,8 @@ public interface SessionFactoryOptionsState {
|
|||
@Deprecated
|
||||
boolean isJpaBootstrap();
|
||||
|
||||
boolean isJtaTransactionAccessEnabled();
|
||||
|
||||
Object getBeanManagerReference();
|
||||
|
||||
Object getValidatorFactoryReference();
|
||||
|
|
|
@ -53,6 +53,11 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
|
|||
return delegate.isJpaBootstrap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJtaTransactionAccessEnabled() {
|
||||
return delegate.isJtaTransactionAccessEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBeanManagerReference() {
|
||||
return delegate.getBeanManagerReference();
|
||||
|
|
|
@ -28,6 +28,8 @@ public interface SessionFactoryBuilderImplementor extends SessionFactoryBuilder
|
|||
@Deprecated
|
||||
void markAsJpaBootstrap();
|
||||
|
||||
void disableJtaTransactionAccess();
|
||||
|
||||
/**
|
||||
* Build the SessionFactoryOptions that will ultimately be passed to SessionFactoryImpl constructor.
|
||||
*
|
||||
|
|
|
@ -58,6 +58,8 @@ public interface SessionFactoryOptions {
|
|||
@Deprecated
|
||||
boolean isJpaBootstrap();
|
||||
|
||||
boolean isJtaTransactionAccessEnabled();
|
||||
|
||||
/**
|
||||
* The name to be used for the SessionFactory. This is use both in:<ul>
|
||||
* <li>in-VM serialization</li>
|
||||
|
|
|
@ -1463,4 +1463,15 @@ public interface AvailableSettings {
|
|||
* @since 5.1
|
||||
*/
|
||||
String CREATE_EMPTY_COMPOSITES_ENABLED = "hibernate.create_empty_composites.enabled";
|
||||
|
||||
/**
|
||||
* Setting that allows access to the underlying {@link org.hibernate.Transaction}, even
|
||||
* when using a JTA since normal JPA operations prohibit this behavior.
|
||||
* <p/>
|
||||
* Values are {@code true} grants access, {@code false} does not.
|
||||
* <p/>
|
||||
* The default behavior is to allow access unless the session is bootstrapped via JPA.
|
||||
*/
|
||||
String ALLOW_JTA_TRANSACTION_ACCESS = "hibernate.jta.allowTransactionAccess";
|
||||
|
||||
}
|
||||
|
|
|
@ -433,6 +433,11 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
|
|||
return delegate.getEventListenerManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction accessTransaction() {
|
||||
return delegate.accessTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction beginTransaction() {
|
||||
return delegate.beginTransaction();
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.Interceptor;
|
|||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.SharedSessionContract;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||
|
@ -150,6 +151,15 @@ public interface SharedSessionContractImplementor
|
|||
*/
|
||||
boolean isTransactionInProgress();
|
||||
|
||||
/**
|
||||
* Provides access to the underlying transaction or creates a new transaction if
|
||||
* one does not already exist or is active. This is primarily for internal or
|
||||
* integrator use.
|
||||
*
|
||||
* @return the transaction
|
||||
*/
|
||||
Transaction accessTransaction();
|
||||
|
||||
/**
|
||||
* Hide the changing requirements of entity key creation
|
||||
*
|
||||
|
|
|
@ -352,37 +352,29 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
if ( getFactory().getSessionFactoryOptions().isJpaBootstrap() ) {
|
||||
// JPA requires that we throw IllegalStateException if this is called
|
||||
// on a JTA EntityManager
|
||||
//
|
||||
// todo : ultimately add an option for allowing users to access the Transaction in JTA cases too like classic Hibernate
|
||||
|
||||
if ( getTransactionCoordinator().getTransactionCoordinatorBuilder().isJta() ) {
|
||||
throw new IllegalStateException( "A JTA EntityManager cannot use getTransaction()" );
|
||||
if ( !getFactory().getSessionFactoryOptions().isJtaTransactionAccessEnabled() ) {
|
||||
throw new IllegalStateException( "A JTA EntityManager cannot use getTransaction()" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( this.currentHibernateTransaction == null ) {
|
||||
this.currentHibernateTransaction = new TransactionImpl(
|
||||
getTransactionCoordinator(),
|
||||
getExceptionConverter()
|
||||
);
|
||||
}
|
||||
if ( !isClosed() ) {
|
||||
getTransactionCoordinator().pulse();
|
||||
}
|
||||
return currentHibernateTransaction;
|
||||
}
|
||||
else {
|
||||
// Historically Hibernate would not allow access to the Transaction after the Session is closed
|
||||
checkOpen();
|
||||
return accessTransaction();
|
||||
}
|
||||
|
||||
if ( this.currentHibernateTransaction == null || this.currentHibernateTransaction.getStatus() != TransactionStatus.ACTIVE ) {
|
||||
this.currentHibernateTransaction = new TransactionImpl(
|
||||
getTransactionCoordinator(),
|
||||
getExceptionConverter()
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public Transaction accessTransaction() {
|
||||
checkOpen();
|
||||
if ( this.currentHibernateTransaction == null || this.currentHibernateTransaction.getStatus() != TransactionStatus.ACTIVE ) {
|
||||
this.currentHibernateTransaction = new TransactionImpl(
|
||||
getTransactionCoordinator(),
|
||||
getExceptionConverter()
|
||||
);
|
||||
|
||||
}
|
||||
if ( !isClosed() ) {
|
||||
getTransactionCoordinator().pulse();
|
||||
return currentHibernateTransaction;
|
||||
}
|
||||
return this.currentHibernateTransaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -346,4 +346,14 @@ public interface AvailableSettings {
|
|||
* @since 5.0.8
|
||||
*/
|
||||
String DELAY_CDI_ACCESS = "hibernate.delay_cdi_access";
|
||||
|
||||
/**
|
||||
* Setting that allows access to the underlying {@link org.hibernate.Transaction}, even
|
||||
* when using a JTA since normal JPA operations prohibit this behavior.
|
||||
* <p/>
|
||||
* Values are {@code true} grants access, {@code false} does not.
|
||||
* <p/>
|
||||
* The default behavior is to allow access unless the session is bootstrapped via JPA.
|
||||
*/
|
||||
String ALLOW_JTA_TRANSACTION_ACCESS = "hibernate.jta.allowTransactionAccess";
|
||||
}
|
||||
|
|
|
@ -881,6 +881,12 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
// sfBuilder.applyInterceptor( sessionFactoryInterceptor );
|
||||
// }
|
||||
|
||||
// will use user override value or default to false if not supplied to follow JPA spec.
|
||||
final boolean jtaTransactionAccessEnabled = readBooleanConfigurationValue( AvailableSettings.ALLOW_JTA_TRANSACTION_ACCESS );
|
||||
if ( !jtaTransactionAccessEnabled ) {
|
||||
( ( SessionFactoryBuilderImplementor ) sfBuilder ).disableJtaTransactionAccess();
|
||||
}
|
||||
|
||||
// Locate and apply any requested SessionFactoryObserver
|
||||
final Object sessionFactoryObserverSetting = configurationValues.remove( AvailableSettings.SESSION_FACTORY_OBSERVER );
|
||||
if ( sessionFactoryObserverSetting != null ) {
|
||||
|
|
Loading…
Reference in New Issue