HHH-12666 : Add an option for restoring 5.1 native exception handling
This commit is contained in:
parent
9286f9147b
commit
8ef0ca9a13
|
@ -47,6 +47,7 @@ import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
|
|||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.id.uuid.LocalObjectUuidHelper;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.log.DeprecationLogger;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.jpa.spi.JpaCompliance;
|
||||
|
@ -97,6 +98,7 @@ import static org.hibernate.cfg.AvailableSettings.JTA_TRACK_BY_THREAD;
|
|||
import static org.hibernate.cfg.AvailableSettings.LOG_SESSION_METRICS;
|
||||
import static org.hibernate.cfg.AvailableSettings.MAX_FETCH_DEPTH;
|
||||
import static org.hibernate.cfg.AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER;
|
||||
import static org.hibernate.cfg.AvailableSettings.NATIVE_EXCEPTION_HANDLING_51_COMPLIANCE;
|
||||
import static org.hibernate.cfg.AvailableSettings.ORDER_INSERTS;
|
||||
import static org.hibernate.cfg.AvailableSettings.ORDER_UPDATES;
|
||||
import static org.hibernate.cfg.AvailableSettings.PREFER_USER_TRANSACTION;
|
||||
|
@ -123,6 +125,7 @@ import static org.hibernate.cfg.AvailableSettings.USE_STRUCTURED_CACHE;
|
|||
import static org.hibernate.cfg.AvailableSettings.VALIDATE_QUERY_PARAMETERS;
|
||||
import static org.hibernate.cfg.AvailableSettings.WRAP_RESULT_SETS;
|
||||
import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN;
|
||||
import static org.hibernate.internal.CoreLogging.messageLogger;
|
||||
import static org.hibernate.jpa.AvailableSettings.DISCARD_PC_ON_CLOSE;
|
||||
|
||||
/**
|
||||
|
@ -137,7 +140,7 @@ import static org.hibernate.jpa.AvailableSettings.DISCARD_PC_ON_CLOSE;
|
|||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||
private static final Logger log = Logger.getLogger( SessionFactoryOptionsBuilder.class );
|
||||
private static final CoreMessageLogger log = messageLogger( SessionFactoryOptionsBuilder.class );
|
||||
|
||||
private final String uuid = LocalObjectUuidHelper.generateLocalObjectUuid();
|
||||
private final StandardServiceRegistry serviceRegistry;
|
||||
|
@ -239,6 +242,8 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
|||
private boolean failOnPaginationOverCollectionFetchEnabled;
|
||||
private boolean inClauseParameterPaddingEnabled;
|
||||
|
||||
private boolean nativeExceptionHandling51Compliance;
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "deprecation"})
|
||||
public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, BootstrapContext context) {
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
|
@ -490,7 +495,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
|||
);
|
||||
|
||||
this.immutableEntityUpdateQueryHandlingMode = ImmutableEntityUpdateQueryHandlingMode.interpret(
|
||||
configurationSettings.get( IMMUTABLE_ENTITY_UPDATE_QUERY_HANDLING_MODE )
|
||||
configurationSettings.get( IMMUTABLE_ENTITY_UPDATE_QUERY_HANDLING_MODE )
|
||||
);
|
||||
|
||||
this.inClauseParameterPaddingEnabled = ConfigurationHelper.getBoolean(
|
||||
|
@ -498,6 +503,16 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
|||
configurationSettings,
|
||||
false
|
||||
);
|
||||
|
||||
this.nativeExceptionHandling51Compliance = ConfigurationHelper.getBoolean(
|
||||
NATIVE_EXCEPTION_HANDLING_51_COMPLIANCE,
|
||||
configurationSettings,
|
||||
false
|
||||
);
|
||||
if ( context.isJpaBootstrap() && nativeExceptionHandling51Compliance ) {
|
||||
log.nativeExceptionHandling51ComplianceJpaBootstrapping();
|
||||
this.nativeExceptionHandling51Compliance = false;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -1011,6 +1026,11 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
|||
return jpaCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean nativeExceptionHandling51Compliance() {
|
||||
return nativeExceptionHandling51Compliance;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// In-flight mutation access
|
||||
|
||||
|
|
|
@ -427,4 +427,9 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
|
|||
public boolean inClauseParameterPaddingEnabled() {
|
||||
return delegate.inClauseParameterPaddingEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean nativeExceptionHandling51Compliance() {
|
||||
return delegate.nativeExceptionHandling51Compliance();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,4 +286,8 @@ public interface SessionFactoryOptions {
|
|||
default boolean inClauseParameterPaddingEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean nativeExceptionHandling51Compliance() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -901,6 +901,17 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
|
|||
*/
|
||||
String WRAP_RESULT_SETS = "hibernate.jdbc.wrap_result_sets";
|
||||
|
||||
/**
|
||||
* Indicates if exception handling for a SessionFactory built via Hibernate's native bootstrapping
|
||||
* should behave the same as in Hibernate ORM 5.1.
|
||||
* <p/>
|
||||
* This setting will be ignored if the SessionFactory was built via JPA bootstrapping.
|
||||
* <p/>
|
||||
* Values are {@code true} or {@code false}.
|
||||
* Default value is {@code false}
|
||||
*/
|
||||
String NATIVE_EXCEPTION_HANDLING_51_COMPLIANCE = "hibernate.native_exception_handling_51_compliance";
|
||||
|
||||
/**
|
||||
* Enable ordering of update statements by primary key value
|
||||
*/
|
||||
|
|
|
@ -1811,4 +1811,7 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
+ "in the same package as class %1$s. In this case, the class should be opened and exported to Hibernate ORM.", id = 488)
|
||||
String bytecodeEnhancementFailedUnableToGetPrivateLookupFor(String className);
|
||||
|
||||
@LogMessage(level = WARN)
|
||||
@Message(value = "Setting " + AvailableSettings.NATIVE_EXCEPTION_HANDLING_51_COMPLIANCE + "=true is not valid with JPA bootstrapping; setting will be ignored.", id = 489 )
|
||||
void nativeExceptionHandling51ComplianceJpaBootstrapping();
|
||||
}
|
||||
|
|
|
@ -43,14 +43,18 @@ public class ExceptionConverterImpl implements ExceptionConverter {
|
|||
private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( ExceptionConverterImpl.class );
|
||||
|
||||
private final SharedSessionContractImplementor sharedSessionContract;
|
||||
private final boolean isJpaBootstrap;
|
||||
private final boolean nativeExceptionHandling51Compliance;
|
||||
|
||||
public ExceptionConverterImpl(SharedSessionContractImplementor sharedSessionContract) {
|
||||
this.sharedSessionContract = sharedSessionContract;
|
||||
isJpaBootstrap = sharedSessionContract.getFactory().getSessionFactoryOptions().isJpaBootstrap();
|
||||
nativeExceptionHandling51Compliance = sharedSessionContract.getFactory().getSessionFactoryOptions().nativeExceptionHandling51Compliance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuntimeException convertCommitException(RuntimeException e) {
|
||||
if ( sharedSessionContract.getFactory().getSessionFactoryOptions().isJpaBootstrap() ) {
|
||||
if ( isJpaBootstrap ) {
|
||||
Throwable wrappedException;
|
||||
if ( e instanceof HibernateException ) {
|
||||
wrappedException = convert( (HibernateException) e );
|
||||
|
@ -83,72 +87,92 @@ public class ExceptionConverterImpl implements ExceptionConverter {
|
|||
|
||||
@Override
|
||||
public RuntimeException convert(HibernateException e, LockOptions lockOptions) {
|
||||
Throwable cause = e;
|
||||
if ( cause instanceof StaleStateException ) {
|
||||
final PersistenceException converted = wrapStaleStateException( (StaleStateException) cause );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof LockAcquisitionException ) {
|
||||
final PersistenceException converted = wrapLockException( (HibernateException) cause, lockOptions );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof LockingStrategyException ) {
|
||||
final PersistenceException converted = wrapLockException( (HibernateException) cause, lockOptions );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof org.hibernate.PessimisticLockException ) {
|
||||
final PersistenceException converted = wrapLockException( (HibernateException) cause, lockOptions );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof org.hibernate.QueryTimeoutException ) {
|
||||
final QueryTimeoutException converted = new QueryTimeoutException( cause.getMessage(), cause );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof ObjectNotFoundException ) {
|
||||
final EntityNotFoundException converted = new EntityNotFoundException( cause.getMessage() );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof org.hibernate.NonUniqueObjectException ) {
|
||||
final EntityExistsException converted = new EntityExistsException( cause.getMessage() );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof org.hibernate.NonUniqueResultException ) {
|
||||
final NonUniqueResultException converted = new NonUniqueResultException( cause.getMessage() );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof UnresolvableObjectException ) {
|
||||
final EntityNotFoundException converted = new EntityNotFoundException( cause.getMessage() );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof QueryException ) {
|
||||
return new IllegalArgumentException( cause );
|
||||
}
|
||||
else if ( cause instanceof MultipleBagFetchException ) {
|
||||
return new IllegalArgumentException( cause );
|
||||
}
|
||||
else if ( cause instanceof TransientObjectException ) {
|
||||
try {
|
||||
sharedSessionContract.markForRollbackOnly();
|
||||
if ( !nativeExceptionHandling51Compliance ) {
|
||||
Throwable cause = e;
|
||||
if ( cause instanceof StaleStateException ) {
|
||||
final PersistenceException converted = wrapStaleStateException( (StaleStateException) cause );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
catch (Exception ne) {
|
||||
//we do not want the subsequent exception to swallow the original one
|
||||
log.unableToMarkForRollbackOnTransientObjectException( ne );
|
||||
else if ( cause instanceof LockAcquisitionException ) {
|
||||
final PersistenceException converted = wrapLockException( (HibernateException) cause, lockOptions );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof LockingStrategyException ) {
|
||||
final PersistenceException converted = wrapLockException( (HibernateException) cause, lockOptions );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof org.hibernate.PessimisticLockException ) {
|
||||
final PersistenceException converted = wrapLockException( (HibernateException) cause, lockOptions );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof org.hibernate.QueryTimeoutException ) {
|
||||
final QueryTimeoutException converted = new QueryTimeoutException( cause.getMessage(), cause );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof ObjectNotFoundException ) {
|
||||
final EntityNotFoundException converted = new EntityNotFoundException( cause.getMessage() );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof org.hibernate.NonUniqueObjectException ) {
|
||||
final EntityExistsException converted = new EntityExistsException( cause.getMessage() );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof org.hibernate.NonUniqueResultException ) {
|
||||
final NonUniqueResultException converted = new NonUniqueResultException( cause.getMessage() );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof UnresolvableObjectException ) {
|
||||
final EntityNotFoundException converted = new EntityNotFoundException( cause.getMessage() );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
else if ( cause instanceof QueryException ) {
|
||||
return new IllegalArgumentException( cause );
|
||||
}
|
||||
else if ( cause instanceof MultipleBagFetchException ) {
|
||||
return new IllegalArgumentException( cause );
|
||||
}
|
||||
else if ( cause instanceof TransientObjectException ) {
|
||||
try {
|
||||
sharedSessionContract.markForRollbackOnly();
|
||||
}
|
||||
catch (Exception ne) {
|
||||
//we do not want the subsequent exception to swallow the original one
|
||||
log.unableToMarkForRollbackOnTransientObjectException( ne );
|
||||
}
|
||||
return new IllegalStateException( e ); //Spec 3.2.3 Synchronization rules
|
||||
}
|
||||
else {
|
||||
final PersistenceException converted = new PersistenceException( cause );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
}
|
||||
return new IllegalStateException( e ); //Spec 3.2.3 Synchronization rules
|
||||
}
|
||||
else {
|
||||
final PersistenceException converted = new PersistenceException( cause );
|
||||
handlePersistenceException( converted );
|
||||
return converted;
|
||||
if ( e instanceof QueryException ) {
|
||||
return e;
|
||||
}
|
||||
else if ( e instanceof MultipleBagFetchException ) {
|
||||
return e;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
sharedSessionContract.markForRollbackOnly();
|
||||
}
|
||||
catch (Exception ne) {
|
||||
//we do not want the subsequent exception to swallow the original one
|
||||
log.unableToMarkForRollbackOnTransientObjectException( ne );
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue