- 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 org.jboss.logging.Logger;
|
||||||
|
|
||||||
import static org.hibernate.cfg.AvailableSettings.ACQUIRE_CONNECTIONS;
|
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_CLOSE_SESSION;
|
||||||
import static org.hibernate.cfg.AvailableSettings.AUTO_EVICT_COLLECTION_CACHE;
|
import static org.hibernate.cfg.AvailableSettings.AUTO_EVICT_COLLECTION_CACHE;
|
||||||
import static org.hibernate.cfg.AvailableSettings.AUTO_SESSION_EVENTS_LISTENER;
|
import static org.hibernate.cfg.AvailableSettings.AUTO_SESSION_EVENTS_LISTENER;
|
||||||
|
@ -480,6 +481,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
||||||
this.options.jpaBootstrap = true;
|
this.options.jpaBootstrap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disableJtaTransactionAccess() {
|
||||||
|
this.options.jtaTransactionAccessEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SessionFactoryOptions buildSessionFactoryOptions() {
|
public SessionFactoryOptions buildSessionFactoryOptions() {
|
||||||
return new SessionFactoryOptionsImpl( this );
|
return new SessionFactoryOptionsImpl( this );
|
||||||
|
@ -504,6 +510,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
||||||
// Session behavior
|
// Session behavior
|
||||||
private boolean flushBeforeCompletionEnabled;
|
private boolean flushBeforeCompletionEnabled;
|
||||||
private boolean autoCloseSessionEnabled;
|
private boolean autoCloseSessionEnabled;
|
||||||
|
private boolean jtaTransactionAccessEnabled;
|
||||||
|
|
||||||
// (JTA) transaction handling
|
// (JTA) transaction handling
|
||||||
private boolean jtaTrackByThread;
|
private boolean jtaTrackByThread;
|
||||||
|
@ -594,6 +601,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
||||||
BOOLEAN,
|
BOOLEAN,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
this.jtaTransactionAccessEnabled = cfgService.getSetting(
|
||||||
|
ALLOW_JTA_TRANSACTION_ACCESS,
|
||||||
|
BOOLEAN,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
this.flushBeforeCompletionEnabled = cfgService.getSetting( FLUSH_BEFORE_COMPLETION, BOOLEAN, true );
|
this.flushBeforeCompletionEnabled = cfgService.getSetting( FLUSH_BEFORE_COMPLETION, BOOLEAN, true );
|
||||||
this.autoCloseSessionEnabled = cfgService.getSetting( AUTO_CLOSE_SESSION, BOOLEAN, false );
|
this.autoCloseSessionEnabled = cfgService.getSetting( AUTO_CLOSE_SESSION, BOOLEAN, false );
|
||||||
|
@ -848,6 +860,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
||||||
return jpaBootstrap;
|
return jpaBootstrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isJtaTransactionAccessEnabled() {
|
||||||
|
return jtaTransactionAccessEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getBeanManagerReference() {
|
public Object getBeanManagerReference() {
|
||||||
return beanManagerReference;
|
return beanManagerReference;
|
||||||
|
@ -1134,6 +1151,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
||||||
return options.isJpaBootstrap();
|
return options.isJpaBootstrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isJtaTransactionAccessEnabled() {
|
||||||
|
return options.isJtaTransactionAccessEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getBeanManagerReference() {
|
public Object getBeanManagerReference() {
|
||||||
return options.getBeanManagerReference();
|
return options.getBeanManagerReference();
|
||||||
|
|
|
@ -51,6 +51,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
||||||
// Session behavior
|
// Session behavior
|
||||||
private final boolean flushBeforeCompletionEnabled;
|
private final boolean flushBeforeCompletionEnabled;
|
||||||
private final boolean autoCloseSessionEnabled;
|
private final boolean autoCloseSessionEnabled;
|
||||||
|
private boolean jtaTransactionAccessEnabled;
|
||||||
|
|
||||||
// transaction handling
|
// transaction handling
|
||||||
private final boolean jtaTrackByThread;
|
private final boolean jtaTrackByThread;
|
||||||
|
@ -124,6 +125,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
||||||
this.validatorFactoryReference = state.getValidatorFactoryReference();
|
this.validatorFactoryReference = state.getValidatorFactoryReference();
|
||||||
|
|
||||||
this.jpaBootstrap = state.isJpaBootstrap();
|
this.jpaBootstrap = state.isJpaBootstrap();
|
||||||
|
this.jtaTransactionAccessEnabled = state.isJtaTransactionAccessEnabled();
|
||||||
this.sessionFactoryName = state.getSessionFactoryName();
|
this.sessionFactoryName = state.getSessionFactoryName();
|
||||||
this.sessionFactoryNameAlsoJndiName = state.isSessionFactoryNameAlsoJndiName();
|
this.sessionFactoryNameAlsoJndiName = state.isSessionFactoryNameAlsoJndiName();
|
||||||
|
|
||||||
|
@ -197,6 +199,11 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
||||||
return jpaBootstrap;
|
return jpaBootstrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isJtaTransactionAccessEnabled() {
|
||||||
|
return jtaTransactionAccessEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getBeanManagerReference() {
|
public Object getBeanManagerReference() {
|
||||||
return beanManagerReference;
|
return beanManagerReference;
|
||||||
|
|
|
@ -46,6 +46,8 @@ public interface SessionFactoryOptionsState {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
boolean isJpaBootstrap();
|
boolean isJpaBootstrap();
|
||||||
|
|
||||||
|
boolean isJtaTransactionAccessEnabled();
|
||||||
|
|
||||||
Object getBeanManagerReference();
|
Object getBeanManagerReference();
|
||||||
|
|
||||||
Object getValidatorFactoryReference();
|
Object getValidatorFactoryReference();
|
||||||
|
|
|
@ -53,6 +53,11 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
|
||||||
return delegate.isJpaBootstrap();
|
return delegate.isJpaBootstrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isJtaTransactionAccessEnabled() {
|
||||||
|
return delegate.isJtaTransactionAccessEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getBeanManagerReference() {
|
public Object getBeanManagerReference() {
|
||||||
return delegate.getBeanManagerReference();
|
return delegate.getBeanManagerReference();
|
||||||
|
|
|
@ -28,6 +28,8 @@ public interface SessionFactoryBuilderImplementor extends SessionFactoryBuilder
|
||||||
@Deprecated
|
@Deprecated
|
||||||
void markAsJpaBootstrap();
|
void markAsJpaBootstrap();
|
||||||
|
|
||||||
|
void disableJtaTransactionAccess();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the SessionFactoryOptions that will ultimately be passed to SessionFactoryImpl constructor.
|
* Build the SessionFactoryOptions that will ultimately be passed to SessionFactoryImpl constructor.
|
||||||
*
|
*
|
||||||
|
|
|
@ -58,6 +58,8 @@ public interface SessionFactoryOptions {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
boolean isJpaBootstrap();
|
boolean isJpaBootstrap();
|
||||||
|
|
||||||
|
boolean isJtaTransactionAccessEnabled();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name to be used for the SessionFactory. This is use both in:<ul>
|
* The name to be used for the SessionFactory. This is use both in:<ul>
|
||||||
* <li>in-VM serialization</li>
|
* <li>in-VM serialization</li>
|
||||||
|
|
|
@ -1463,4 +1463,15 @@ public interface AvailableSettings {
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
String CREATE_EMPTY_COMPOSITES_ENABLED = "hibernate.create_empty_composites.enabled";
|
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();
|
return delegate.getEventListenerManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Transaction accessTransaction() {
|
||||||
|
return delegate.accessTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transaction beginTransaction() {
|
public Transaction beginTransaction() {
|
||||||
return delegate.beginTransaction();
|
return delegate.beginTransaction();
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.Interceptor;
|
||||||
import org.hibernate.ScrollMode;
|
import org.hibernate.ScrollMode;
|
||||||
import org.hibernate.ScrollableResults;
|
import org.hibernate.ScrollableResults;
|
||||||
import org.hibernate.SharedSessionContract;
|
import org.hibernate.SharedSessionContract;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||||
|
@ -150,6 +151,15 @@ public interface SharedSessionContractImplementor
|
||||||
*/
|
*/
|
||||||
boolean isTransactionInProgress();
|
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
|
* Hide the changing requirements of entity key creation
|
||||||
*
|
*
|
||||||
|
|
|
@ -352,37 +352,29 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
if ( getFactory().getSessionFactoryOptions().isJpaBootstrap() ) {
|
if ( getFactory().getSessionFactoryOptions().isJpaBootstrap() ) {
|
||||||
// JPA requires that we throw IllegalStateException if this is called
|
// JPA requires that we throw IllegalStateException if this is called
|
||||||
// on a JTA EntityManager
|
// 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() ) {
|
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 {
|
return accessTransaction();
|
||||||
// Historically Hibernate would not allow access to the Transaction after the Session is closed
|
}
|
||||||
checkOpen();
|
|
||||||
|
|
||||||
if ( this.currentHibernateTransaction == null || this.currentHibernateTransaction.getStatus() != TransactionStatus.ACTIVE ) {
|
@Override
|
||||||
this.currentHibernateTransaction = new TransactionImpl(
|
public Transaction accessTransaction() {
|
||||||
getTransactionCoordinator(),
|
checkOpen();
|
||||||
getExceptionConverter()
|
if ( this.currentHibernateTransaction == null || this.currentHibernateTransaction.getStatus() != TransactionStatus.ACTIVE ) {
|
||||||
);
|
this.currentHibernateTransaction = new TransactionImpl(
|
||||||
}
|
getTransactionCoordinator(),
|
||||||
|
getExceptionConverter()
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
if ( !isClosed() ) {
|
||||||
getTransactionCoordinator().pulse();
|
getTransactionCoordinator().pulse();
|
||||||
return currentHibernateTransaction;
|
|
||||||
}
|
}
|
||||||
|
return this.currentHibernateTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -346,4 +346,14 @@ public interface AvailableSettings {
|
||||||
* @since 5.0.8
|
* @since 5.0.8
|
||||||
*/
|
*/
|
||||||
String DELAY_CDI_ACCESS = "hibernate.delay_cdi_access";
|
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 );
|
// 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
|
// Locate and apply any requested SessionFactoryObserver
|
||||||
final Object sessionFactoryObserverSetting = configurationValues.remove( AvailableSettings.SESSION_FACTORY_OBSERVER );
|
final Object sessionFactoryObserverSetting = configurationValues.remove( AvailableSettings.SESSION_FACTORY_OBSERVER );
|
||||||
if ( sessionFactoryObserverSetting != null ) {
|
if ( sessionFactoryObserverSetting != null ) {
|
||||||
|
|
Loading…
Reference in New Issue