Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ public boolean isTransactionInProgress() {
return delegate.isTransactionInProgress();
}

@Override
public void checkTransactionNeededForUpdateOperation(String exceptionMessage) {
delegate.checkTransactionNeededForUpdateOperation( exceptionMessage );
}

@Override
public LockOptions getLockRequest(LockModeType lockModeType, Map<String, Object> properties) {
return delegate.getLockRequest( lockModeType, properties );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.List;
import java.util.UUID;
import javax.persistence.FlushModeType;
import javax.persistence.TransactionRequiredException;

import org.hibernate.CacheMode;
import org.hibernate.Criteria;
Expand Down Expand Up @@ -180,6 +181,18 @@ default long getTimestamp() {
*/
boolean isTransactionInProgress();

/**
* Check if an active Transaction is necessary for the update operation to be executed.
* If an active Transaction is necessary but it is not then a TransactionRequiredException is raised.
*
* @param exceptionMessage, the message to use for the TransactionRequiredException
*/
default void checkTransactionNeededForUpdateOperation(String exceptionMessage) {
if ( !isTransactionInProgress() ) {
throw new TransactionRequiredException( exceptionMessage );
}
}

/**
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.TimeZone;
import java.util.UUID;
import javax.persistence.FlushModeType;
import javax.persistence.TransactionRequiredException;
import javax.persistence.Tuple;

import org.hibernate.AssertionFailure;
Expand Down Expand Up @@ -128,6 +129,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont

protected boolean closed;
protected boolean waitingForAutoClose;
private transient boolean disallowOutOfTransactionUpdateOperations;

// transient & non-final for Serialization purposes - ugh
private transient SessionEventListenerManagerImpl sessionEventsManager = new SessionEventListenerManagerImpl();
Expand All @@ -141,6 +143,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
public AbstractSharedSessionContract(SessionFactoryImpl factory, SessionCreationOptions options) {
this.factory = factory;
this.cacheTransactionSync = factory.getCache().getRegionFactory().createTransactionContext( this );
this.disallowOutOfTransactionUpdateOperations = !factory.getSessionFactoryOptions().isAllowOutOfTransactionUpdateOperations();

this.flushMode = options.getInitialSessionFlushMode();

Expand Down Expand Up @@ -389,6 +392,13 @@ public boolean isTransactionInProgress() {
return !isClosed() && transactionCoordinator.isTransactionActive();
}

@Override
public void checkTransactionNeededForUpdateOperation(String exceptionMessage) {
if ( disallowOutOfTransactionUpdateOperations && !isTransactionInProgress() ) {
throw new TransactionRequiredException( exceptionMessage );
}
}

@Override
public Transaction getTransaction() throws HibernateException {
if ( getFactory().getSessionFactoryOptions().getJpaCompliance().isJpaTransactionComplianceEnabled() ) {
Expand Down Expand Up @@ -1133,5 +1143,7 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFound

entityNameResolver = new CoordinatingEntityNameResolver( factory, interceptor );
exceptionConverter = new ExceptionConverterImpl( this );
this.disallowOutOfTransactionUpdateOperations = !getFactory().getSessionFactoryOptions().isAllowOutOfTransactionUpdateOperations();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,6 @@ public final class SessionImpl

private transient int dontFlushFromFind;

private transient boolean disallowOutOfTransactionUpdateOperations;
private transient ExceptionMapper exceptionMapper;
private transient ManagedFlushChecker managedFlushChecker;

Expand All @@ -262,7 +261,7 @@ public SessionImpl(SessionFactoryImpl factory, SessionCreationOptions options) {
this.autoClear = options.shouldAutoClear();
this.autoClose = options.shouldAutoClose();
this.queryParametersValidationEnabled = options.isQueryParametersValidationEnabled();
this.disallowOutOfTransactionUpdateOperations = !factory.getSessionFactoryOptions().isAllowOutOfTransactionUpdateOperations();

this.discardOnClose = getFactory().getSessionFactoryOptions().isReleaseResourcesOnCloseEnabled();

if ( options instanceof SharedSessionCreationOptions && ( (SharedSessionCreationOptions) options ).isTransactionCoordinatorShared() ) {
Expand Down Expand Up @@ -1441,7 +1440,7 @@ public void flush() throws HibernateException {
}

private void doFlush() {
checkTransactionNeeded();
checkTransactionNeededForUpdateOperation();
checkTransactionSynchStatus();

try {
Expand Down Expand Up @@ -3474,7 +3473,7 @@ public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode

if ( lockModeType != null ) {
if ( !LockModeType.NONE.equals( lockModeType) ) {
checkTransactionNeeded();
checkTransactionNeededForUpdateOperation();
}
lockOptions = buildLockOptions( lockModeType, properties );
loadAccess.with( lockOptions );
Expand Down Expand Up @@ -3547,10 +3546,8 @@ private CacheStoreMode determineCacheStoreMode(Map<String, Object> settings) {
return ( CacheStoreMode ) settings.get( JPA_SHARED_CACHE_STORE_MODE );
}

private void checkTransactionNeeded() {
if ( disallowOutOfTransactionUpdateOperations && !isTransactionInProgress() ) {
throw new TransactionRequiredException( "no transaction is in progress" );
}
private void checkTransactionNeededForUpdateOperation() {
checkTransactionNeededForUpdateOperation( "no transaction is in progress" );
}

@Override
Expand All @@ -3576,7 +3573,7 @@ public void lock(Object entity, LockModeType lockModeType) {
@Override
public void lock(Object entity, LockModeType lockModeType, Map<String, Object> properties) {
checkOpen();
checkTransactionNeeded();
checkTransactionNeededForUpdateOperation();

if ( !contains( entity ) ) {
throw new IllegalArgumentException( "entity not in the persistence context" );
Expand Down Expand Up @@ -3618,7 +3615,7 @@ public void refresh(Object entity, LockModeType lockModeType, Map<String, Object

if ( lockModeType != null ) {
if ( !LockModeType.NONE.equals( lockModeType) ) {
checkTransactionNeeded();
checkTransactionNeededForUpdateOperation();
}

lockOptions = buildLockOptions( lockModeType, properties );
Expand Down Expand Up @@ -3996,7 +3993,6 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFound

initializeFromSessionOwner( null );

this.disallowOutOfTransactionUpdateOperations = !getFactory().getSessionFactoryOptions().isAllowOutOfTransactionUpdateOperations();
this.discardOnClose = getFactory().getSessionFactoryOptions().isReleaseResourcesOnCloseEnabled();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import javax.persistence.Parameter;
import javax.persistence.ParameterMode;
import javax.persistence.TemporalType;
import javax.persistence.TransactionRequiredException;

import org.hibernate.HibernateException;
import org.hibernate.engine.ResultSetMappingDefinition;
Expand Down Expand Up @@ -636,9 +635,8 @@ protected ProcedureOutputs outputs() {

@Override
public int executeUpdate() {
if ( ! getProducer().isTransactionInProgress() ) {
throw new TransactionRequiredException( "javax.persistence.Query.executeUpdate requires active transaction" );
}
getProducer().checkTransactionNeededForUpdateOperation(
"javax.persistence.Query.executeUpdate requires active transaction" );

// the expectation is that there is just one Output, of type UpdateCountOutput
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1582,13 +1582,8 @@ public static <R> R uniqueElement(List<R> list) throws NonUniqueResultException

@Override
public int executeUpdate() throws HibernateException {
if ( ! getProducer().isTransactionInProgress() ) {
throw getProducer().getExceptionConverter().convert(
new TransactionRequiredException(
"Executing an update/delete query"
)
);
}
getProducer().checkTransactionNeededForUpdateOperation( "Executing an update/delete query" );

beforeQuery();
try {
return doExecuteUpdate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,18 @@

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.TransactionRequiredException;
import java.io.Serializable;

import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.resource.transaction.spi.TransactionStatus;

import org.junit.Test;

import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Test;

import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsNull.nullValue;
Expand Down Expand Up @@ -50,21 +48,21 @@ protected void configure(Configuration configuration) {

@Override
protected void prepareTest() throws Exception {
try (Session s = openSession()) {
final MyEntity entity = new MyEntity( "entity" );
s.getTransaction().begin();
try {
s.save( entity );

s.getTransaction().commit();
}
catch (Exception e) {
if ( s.getTransaction().getStatus() == TransactionStatus.ACTIVE ) {
s.getTransaction().rollback();
final MyEntity entity = new MyEntity( "entity" );
inTransaction(
session -> {
session.save( entity );
}
throw e;
}
}
);
}

@After
public void tearDown() {
inTransaction(
session -> {
session.createQuery( "delete from MyEntity" ).executeUpdate();
}
);
}

@Test
Expand All @@ -82,6 +80,26 @@ public void testFlushAllowingOutOfTransactionUpdateOperations() throws Exception
}
}

@Test
public void testNativeQueryAllowingOutOfTransactionUpdateOperations() throws Exception {
allowUpdateOperationOutsideTransaction = "true";
rebuildSessionFactory();
prepareTest();
try (Session s = openSession()) {
s.createSQLQuery( "delete from MY_ENTITY" ).executeUpdate();
}
}

@Test(expected = TransactionRequiredException.class)
public void testNativeQueryDisallowingOutOfTransactionUpdateOperations() throws Exception {
allowUpdateOperationOutsideTransaction = "false";
rebuildSessionFactory();
prepareTest();
try (Session s = openSession()) {
s.createSQLQuery( "delete from MY_ENTITY" ).executeUpdate();
}
}

@Test(expected = TransactionRequiredException.class)
public void testFlushDisallowingOutOfTransactionUpdateOperations() throws Exception {
allowUpdateOperationOutsideTransaction = "false";
Expand Down Expand Up @@ -113,6 +131,7 @@ public void testFlushOutOfTransaction() throws Exception {
}

@Entity(name = "MyEntity")
@Table(name = "MY_ENTITY")
public static class MyEntity {
@Id
@GeneratedValue
Expand All @@ -135,20 +154,4 @@ public void setName(String name) {
this.name = name;
}
}

public final Serializable doInsideTransaction(Session s, java.util.function.Supplier<Serializable> sp) {
s.getTransaction().begin();
try {
final Serializable result = sp.get();

s.getTransaction().commit();
return result;
}
catch (Exception e) {
if ( s.getTransaction().getStatus() == TransactionStatus.ACTIVE ) {
s.getTransaction().rollback();
}
throw e;
}
}
}