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.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||||
import org.hibernate.id.uuid.LocalObjectUuidHelper;
|
import org.hibernate.id.uuid.LocalObjectUuidHelper;
|
||||||
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.log.DeprecationLogger;
|
import org.hibernate.internal.log.DeprecationLogger;
|
||||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||||
import org.hibernate.jpa.spi.JpaCompliance;
|
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.LOG_SESSION_METRICS;
|
||||||
import static org.hibernate.cfg.AvailableSettings.MAX_FETCH_DEPTH;
|
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.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_INSERTS;
|
||||||
import static org.hibernate.cfg.AvailableSettings.ORDER_UPDATES;
|
import static org.hibernate.cfg.AvailableSettings.ORDER_UPDATES;
|
||||||
import static org.hibernate.cfg.AvailableSettings.PREFER_USER_TRANSACTION;
|
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.VALIDATE_QUERY_PARAMETERS;
|
||||||
import static org.hibernate.cfg.AvailableSettings.WRAP_RESULT_SETS;
|
import static org.hibernate.cfg.AvailableSettings.WRAP_RESULT_SETS;
|
||||||
import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN;
|
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;
|
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")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
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 String uuid = LocalObjectUuidHelper.generateLocalObjectUuid();
|
||||||
private final StandardServiceRegistry serviceRegistry;
|
private final StandardServiceRegistry serviceRegistry;
|
||||||
|
@ -239,6 +242,8 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||||
private boolean failOnPaginationOverCollectionFetchEnabled;
|
private boolean failOnPaginationOverCollectionFetchEnabled;
|
||||||
private boolean inClauseParameterPaddingEnabled;
|
private boolean inClauseParameterPaddingEnabled;
|
||||||
|
|
||||||
|
private boolean nativeExceptionHandling51Compliance;
|
||||||
|
|
||||||
@SuppressWarnings({"WeakerAccess", "deprecation"})
|
@SuppressWarnings({"WeakerAccess", "deprecation"})
|
||||||
public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, BootstrapContext context) {
|
public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, BootstrapContext context) {
|
||||||
this.serviceRegistry = serviceRegistry;
|
this.serviceRegistry = serviceRegistry;
|
||||||
|
@ -490,7 +495,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||||
);
|
);
|
||||||
|
|
||||||
this.immutableEntityUpdateQueryHandlingMode = ImmutableEntityUpdateQueryHandlingMode.interpret(
|
this.immutableEntityUpdateQueryHandlingMode = ImmutableEntityUpdateQueryHandlingMode.interpret(
|
||||||
configurationSettings.get( IMMUTABLE_ENTITY_UPDATE_QUERY_HANDLING_MODE )
|
configurationSettings.get( IMMUTABLE_ENTITY_UPDATE_QUERY_HANDLING_MODE )
|
||||||
);
|
);
|
||||||
|
|
||||||
this.inClauseParameterPaddingEnabled = ConfigurationHelper.getBoolean(
|
this.inClauseParameterPaddingEnabled = ConfigurationHelper.getBoolean(
|
||||||
|
@ -498,6 +503,16 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||||
configurationSettings,
|
configurationSettings,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.nativeExceptionHandling51Compliance = ConfigurationHelper.getBoolean(
|
||||||
|
NATIVE_EXCEPTION_HANDLING_51_COMPLIANCE,
|
||||||
|
configurationSettings,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
if ( context.isJpaBootstrap() && nativeExceptionHandling51Compliance ) {
|
||||||
|
log.nativeExceptionHandling51ComplianceJpaBootstrapping();
|
||||||
|
this.nativeExceptionHandling51Compliance = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
@ -1011,6 +1026,11 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||||
return jpaCompliance;
|
return jpaCompliance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean nativeExceptionHandling51Compliance() {
|
||||||
|
return nativeExceptionHandling51Compliance;
|
||||||
|
}
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// In-flight mutation access
|
// In-flight mutation access
|
||||||
|
|
||||||
|
|
|
@ -427,4 +427,9 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
|
||||||
public boolean inClauseParameterPaddingEnabled() {
|
public boolean inClauseParameterPaddingEnabled() {
|
||||||
return delegate.inClauseParameterPaddingEnabled();
|
return delegate.inClauseParameterPaddingEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean nativeExceptionHandling51Compliance() {
|
||||||
|
return delegate.nativeExceptionHandling51Compliance();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,4 +286,8 @@ public interface SessionFactoryOptions {
|
||||||
default boolean inClauseParameterPaddingEnabled() {
|
default boolean inClauseParameterPaddingEnabled() {
|
||||||
return false;
|
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";
|
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
|
* 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)
|
+ "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);
|
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 static final EntityManagerMessageLogger log = HEMLogging.messageLogger( ExceptionConverterImpl.class );
|
||||||
|
|
||||||
private final SharedSessionContractImplementor sharedSessionContract;
|
private final SharedSessionContractImplementor sharedSessionContract;
|
||||||
|
private final boolean isJpaBootstrap;
|
||||||
|
private final boolean nativeExceptionHandling51Compliance;
|
||||||
|
|
||||||
public ExceptionConverterImpl(SharedSessionContractImplementor sharedSessionContract) {
|
public ExceptionConverterImpl(SharedSessionContractImplementor sharedSessionContract) {
|
||||||
this.sharedSessionContract = sharedSessionContract;
|
this.sharedSessionContract = sharedSessionContract;
|
||||||
|
isJpaBootstrap = sharedSessionContract.getFactory().getSessionFactoryOptions().isJpaBootstrap();
|
||||||
|
nativeExceptionHandling51Compliance = sharedSessionContract.getFactory().getSessionFactoryOptions().nativeExceptionHandling51Compliance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RuntimeException convertCommitException(RuntimeException e) {
|
public RuntimeException convertCommitException(RuntimeException e) {
|
||||||
if ( sharedSessionContract.getFactory().getSessionFactoryOptions().isJpaBootstrap() ) {
|
if ( isJpaBootstrap ) {
|
||||||
Throwable wrappedException;
|
Throwable wrappedException;
|
||||||
if ( e instanceof HibernateException ) {
|
if ( e instanceof HibernateException ) {
|
||||||
wrappedException = convert( (HibernateException) e );
|
wrappedException = convert( (HibernateException) e );
|
||||||
|
@ -83,72 +87,92 @@ public class ExceptionConverterImpl implements ExceptionConverter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RuntimeException convert(HibernateException e, LockOptions lockOptions) {
|
public RuntimeException convert(HibernateException e, LockOptions lockOptions) {
|
||||||
Throwable cause = e;
|
if ( !nativeExceptionHandling51Compliance ) {
|
||||||
if ( cause instanceof StaleStateException ) {
|
Throwable cause = e;
|
||||||
final PersistenceException converted = wrapStaleStateException( (StaleStateException) cause );
|
if ( cause instanceof StaleStateException ) {
|
||||||
handlePersistenceException( converted );
|
final PersistenceException converted = wrapStaleStateException( (StaleStateException) cause );
|
||||||
return converted;
|
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();
|
|
||||||
}
|
}
|
||||||
catch (Exception ne) {
|
else if ( cause instanceof LockAcquisitionException ) {
|
||||||
//we do not want the subsequent exception to swallow the original one
|
final PersistenceException converted = wrapLockException( (HibernateException) cause, lockOptions );
|
||||||
log.unableToMarkForRollbackOnTransientObjectException( ne );
|
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 {
|
else {
|
||||||
final PersistenceException converted = new PersistenceException( cause );
|
if ( e instanceof QueryException ) {
|
||||||
handlePersistenceException( converted );
|
return e;
|
||||||
return converted;
|
}
|
||||||
|
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