Translate Hibernate TransactionException through SQLException cause
Closes gh-31274
This commit is contained in:
parent
eafbcfd385
commit
e76b453685
|
|
@ -589,6 +589,10 @@ public class JpaTransactionManager extends AbstractPlatformTransactionManager
|
|||
}
|
||||
}
|
||||
catch (PersistenceException ex) {
|
||||
DataAccessException dae = getJpaDialect().translateExceptionIfPossible(ex);
|
||||
if (dae != null) {
|
||||
throw dae;
|
||||
}
|
||||
throw new TransactionSystemException("Could not roll back JPA transaction", ex);
|
||||
}
|
||||
finally {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
|||
import org.springframework.dao.PessimisticLockingFailureException;
|
||||
import org.springframework.jdbc.datasource.ConnectionHandle;
|
||||
import org.springframework.jdbc.datasource.DataSourceUtils;
|
||||
import org.springframework.jdbc.support.SQLExceptionSubclassTranslator;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.orm.ObjectOptimisticLockingFailureException;
|
||||
|
|
@ -74,7 +75,7 @@ import org.springframework.util.ReflectionUtils;
|
|||
|
||||
/**
|
||||
* {@link org.springframework.orm.jpa.JpaDialect} implementation for Hibernate.
|
||||
* Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1/6.2.
|
||||
* Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1/6.2/6.3.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Costin Leau
|
||||
|
|
@ -91,6 +92,9 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
|||
@Nullable
|
||||
private SQLExceptionTranslator jdbcExceptionTranslator;
|
||||
|
||||
@Nullable
|
||||
private SQLExceptionTranslator transactionExceptionTranslator = new SQLExceptionSubclassTranslator();
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to prepare the underlying JDBC Connection of a transactional
|
||||
|
|
@ -121,14 +125,22 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
|||
* <p>Applied to any detected {@link java.sql.SQLException} root cause of a Hibernate
|
||||
* {@link JDBCException}, overriding Hibernate's own {@code SQLException} translation
|
||||
* (which is based on a Hibernate Dialect for a specific target database).
|
||||
* <p>As of 6.1, also applied to {@link org.hibernate.TransactionException} translation
|
||||
* with a {@link SQLException} root cause (where Hibernate does not translate itself
|
||||
* at all), overriding Spring's default {@link SQLExceptionSubclassTranslator} there.
|
||||
* @param exceptionTranslator the {@link SQLExceptionTranslator} to delegate to, or
|
||||
* {@code null} for none. By default, a {@link SQLExceptionSubclassTranslator} will
|
||||
* be used for {@link org.hibernate.TransactionException} translation as of 6.1;
|
||||
* this can be reverted to pre-6.1 behavior through setting {@code null} here.
|
||||
* @since 5.1
|
||||
* @see java.sql.SQLException
|
||||
* @see org.hibernate.JDBCException
|
||||
* @see org.springframework.jdbc.support.SQLExceptionSubclassTranslator
|
||||
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
|
||||
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
|
||||
*/
|
||||
public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) {
|
||||
this.jdbcExceptionTranslator = jdbcExceptionTranslator;
|
||||
public void setJdbcExceptionTranslator(@Nullable SQLExceptionTranslator exceptionTranslator) {
|
||||
this.jdbcExceptionTranslator = exceptionTranslator;
|
||||
this.transactionExceptionTranslator = exceptionTranslator;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -245,7 +257,16 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
|||
DataAccessException dae = this.jdbcExceptionTranslator.translate(
|
||||
"Hibernate operation: " + jdbcEx.getMessage(), jdbcEx.getSQL(), jdbcEx.getSQLException());
|
||||
if (dae != null) {
|
||||
throw dae;
|
||||
return dae;
|
||||
}
|
||||
}
|
||||
if (this.transactionExceptionTranslator != null && ex instanceof org.hibernate.TransactionException) {
|
||||
if (ex.getCause() instanceof SQLException sqlEx) {
|
||||
DataAccessException dae = this.transactionExceptionTranslator.translate(
|
||||
"Hibernate transaction: " + ex.getMessage(), null, sqlEx);
|
||||
if (dae != null) {
|
||||
return dae;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import org.springframework.util.ClassUtils;
|
|||
|
||||
/**
|
||||
* {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate.
|
||||
* Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1/6.2.
|
||||
* Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1/6.2/6.3.
|
||||
*
|
||||
* <p>Exposes Hibernate's persistence provider and Hibernate's Session as extended
|
||||
* EntityManager interface, and adapts {@link AbstractJpaVendorAdapter}'s common
|
||||
|
|
|
|||
Loading…
Reference in New Issue