HHH-12487 - Calling getTransaction() on a closed EntityManager
This commit is contained in:
parent
19f78bbd3d
commit
291d4a3eea
|
@ -12,6 +12,7 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.TransactionException;
|
import org.hibernate.TransactionException;
|
||||||
import org.hibernate.engine.spi.ExceptionConverter;
|
import org.hibernate.engine.spi.ExceptionConverter;
|
||||||
import org.hibernate.engine.transaction.spi.TransactionImplementor;
|
import org.hibernate.engine.transaction.spi.TransactionImplementor;
|
||||||
|
import org.hibernate.internal.AbstractSharedSessionContract;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.jpa.spi.JpaCompliance;
|
import org.hibernate.jpa.spi.JpaCompliance;
|
||||||
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
|
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
|
||||||
|
@ -31,29 +32,38 @@ public class TransactionImpl implements TransactionImplementor {
|
||||||
private final TransactionCoordinator transactionCoordinator;
|
private final TransactionCoordinator transactionCoordinator;
|
||||||
private final ExceptionConverter exceptionConverter;
|
private final ExceptionConverter exceptionConverter;
|
||||||
private final JpaCompliance jpaCompliance;
|
private final JpaCompliance jpaCompliance;
|
||||||
|
private final AbstractSharedSessionContract session;
|
||||||
|
|
||||||
private TransactionDriver transactionDriverControl;
|
private TransactionDriver transactionDriverControl;
|
||||||
|
|
||||||
public TransactionImpl(
|
public TransactionImpl(
|
||||||
TransactionCoordinator transactionCoordinator,
|
TransactionCoordinator transactionCoordinator,
|
||||||
ExceptionConverter exceptionConverter,
|
ExceptionConverter exceptionConverter,
|
||||||
JpaCompliance jpaCompliance) {
|
AbstractSharedSessionContract session) {
|
||||||
this.transactionCoordinator = transactionCoordinator;
|
this.transactionCoordinator = transactionCoordinator;
|
||||||
this.exceptionConverter = exceptionConverter;
|
this.exceptionConverter = exceptionConverter;
|
||||||
this.jpaCompliance = jpaCompliance;
|
this.jpaCompliance = session.getFactory().getSessionFactoryOptions().getJpaCompliance();
|
||||||
|
this.session = session;
|
||||||
|
|
||||||
this.transactionDriverControl = transactionCoordinator.getTransactionDriverControl();
|
if ( session.isOpen() && transactionCoordinator.isActive() ) {
|
||||||
|
this.transactionDriverControl = transactionCoordinator.getTransactionDriverControl();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG.debug( "TransactionImpl created on closed Session/EntityManager" );
|
||||||
|
}
|
||||||
|
|
||||||
LOG.debugf(
|
if ( LOG.isDebugEnabled() ) {
|
||||||
"On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == %s",
|
LOG.debugf(
|
||||||
jpaCompliance.isJpaTransactionComplianceEnabled()
|
"On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == %s",
|
||||||
);
|
jpaCompliance.isJpaTransactionComplianceEnabled()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void begin() {
|
public void begin() {
|
||||||
if ( !transactionCoordinator.isActive() ) {
|
if ( !session.isOpen() ) {
|
||||||
throw new TransactionException( "Cannot begin Transaction on closed Session/EntityManager" );
|
throw new IllegalStateException( "Cannot begin Transaction on closed Session/EntityManager" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( transactionDriverControl == null ) {
|
if ( transactionDriverControl == null ) {
|
||||||
|
@ -66,6 +76,7 @@ public class TransactionImpl implements TransactionImplementor {
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug( "begin" );
|
LOG.debug( "begin" );
|
||||||
|
|
||||||
this.transactionDriverControl.begin();
|
this.transactionDriverControl.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +93,7 @@ public class TransactionImpl implements TransactionImplementor {
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug( "committing" );
|
LOG.debug( "committing" );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
internalGetTransactionDriverControl().commit();
|
internalGetTransactionDriverControl().commit();
|
||||||
}
|
}
|
||||||
|
@ -100,8 +112,9 @@ public class TransactionImpl implements TransactionImplementor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void rollback() {
|
public void rollback() {
|
||||||
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
|
if ( !isActive() ) {
|
||||||
if ( !isActive() ) {
|
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
|
||||||
|
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"JPA compliance dictates throwing IllegalStateException when #rollback " +
|
"JPA compliance dictates throwing IllegalStateException when #rollback " +
|
||||||
"is called on non-active transaction"
|
"is called on non-active transaction"
|
||||||
|
@ -121,6 +134,7 @@ public class TransactionImpl implements TransactionImplementor {
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug( "rolling back" );
|
LOG.debug( "rolling back" );
|
||||||
|
|
||||||
if ( status != TransactionStatus.FAILED_COMMIT || allowFailedCommitToPhysicallyRollback() ) {
|
if ( status != TransactionStatus.FAILED_COMMIT || allowFailedCommitToPhysicallyRollback() ) {
|
||||||
internalGetTransactionDriverControl().rollback();
|
internalGetTransactionDriverControl().rollback();
|
||||||
}
|
}
|
||||||
|
@ -136,7 +150,12 @@ public class TransactionImpl implements TransactionImplementor {
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive(boolean isMarkedForRollbackConsideredActive) {
|
public boolean isActive(boolean isMarkedForRollbackConsideredActive) {
|
||||||
if ( transactionDriverControl == null ) {
|
if ( transactionDriverControl == null ) {
|
||||||
transactionDriverControl = transactionCoordinator.getTransactionDriverControl();
|
if ( session.isOpen() ) {
|
||||||
|
transactionDriverControl = transactionCoordinator.getTransactionDriverControl();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return transactionDriverControl.isActive( isMarkedForRollbackConsideredActive );
|
return transactionDriverControl.isActive( isMarkedForRollbackConsideredActive );
|
||||||
}
|
}
|
||||||
|
@ -144,7 +163,12 @@ public class TransactionImpl implements TransactionImplementor {
|
||||||
@Override
|
@Override
|
||||||
public TransactionStatus getStatus() {
|
public TransactionStatus getStatus() {
|
||||||
if ( transactionDriverControl == null ) {
|
if ( transactionDriverControl == null ) {
|
||||||
transactionDriverControl = transactionCoordinator.getTransactionDriverControl();
|
if ( session.isOpen() ) {
|
||||||
|
transactionDriverControl = transactionCoordinator.getTransactionDriverControl();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return TransactionStatus.NOT_ACTIVE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return transactionDriverControl.getStatus();
|
return transactionDriverControl.getStatus();
|
||||||
}
|
}
|
||||||
|
@ -175,25 +199,29 @@ public class TransactionImpl implements TransactionImplementor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRollbackOnly() {
|
public void setRollbackOnly() {
|
||||||
// Since this is the JPA-defined one, we make sure the txn is active first
|
if ( !isActive() ) {
|
||||||
// so long as compliance (JpaCompliance) has not been defined to disable
|
// Since this is the JPA-defined one, we make sure the txn is active first
|
||||||
// that check - making this active more like Hibernate's #markRollbackOnly
|
// so long as compliance (JpaCompliance) has not been defined to disable
|
||||||
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
|
// that check - making this active more like Hibernate's #markRollbackOnly
|
||||||
if ( !isActive() ) {
|
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"JPA compliance dictates throwing IllegalStateException when #setRollbackOnly " +
|
"JPA compliance dictates throwing IllegalStateException when #setRollbackOnly " +
|
||||||
"is called on non-active transaction"
|
"is called on non-active transaction"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
LOG.debug( "#setRollbackOnly called on a not-active transaction" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
markRollbackOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
markRollbackOnly();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getRollbackOnly() {
|
public boolean getRollbackOnly() {
|
||||||
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
|
if ( !isActive() ) {
|
||||||
if ( !isActive() ) {
|
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"JPA compliance dictates throwing IllegalStateException when #getRollbackOnly " +
|
"JPA compliance dictates throwing IllegalStateException when #getRollbackOnly " +
|
||||||
"is called on non-active transaction"
|
"is called on non-active transaction"
|
||||||
|
|
|
@ -80,7 +80,6 @@ import org.hibernate.resource.jdbc.spi.StatementInspector;
|
||||||
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl;
|
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl;
|
||||||
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
|
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
|
||||||
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
|
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
|
||||||
import org.hibernate.resource.transaction.spi.TransactionStatus;
|
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
|
|
||||||
|
@ -404,13 +403,12 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transaction accessTransaction() {
|
public Transaction accessTransaction() {
|
||||||
if ( this.currentHibernateTransaction == null || this.currentHibernateTransaction.getStatus() != TransactionStatus.ACTIVE ) {
|
if ( this.currentHibernateTransaction == null ) {
|
||||||
this.currentHibernateTransaction = new TransactionImpl(
|
this.currentHibernateTransaction = new TransactionImpl(
|
||||||
getTransactionCoordinator(),
|
getTransactionCoordinator(),
|
||||||
getExceptionConverter(),
|
getExceptionConverter(),
|
||||||
getFactory().getSessionFactoryOptions().getJpaCompliance()
|
this
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
if ( !isClosed() || (waitingForAutoClose && factory.isOpen()) ) {
|
if ( !isClosed() || (waitingForAutoClose && factory.isOpen()) ) {
|
||||||
getTransactionCoordinator().pulse();
|
getTransactionCoordinator().pulse();
|
||||||
|
|
Loading…
Reference in New Issue