Skip to content

Commit d9e8d3b

Browse files
committed
Custom "jdbcExceptionTranslator" on HibernateJpaDialect
Also available on LocalSessionFactoryBean through HibernateExceptionTranslator, as with our former Hibernate 3 support. Issue: SPR-17015
1 parent 39d4550 commit d9e8d3b

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateExceptionTranslator.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
import javax.persistence.PersistenceException;
2020

2121
import org.hibernate.HibernateException;
22+
import org.hibernate.JDBCException;
2223

2324
import org.springframework.dao.DataAccessException;
2425
import org.springframework.dao.support.PersistenceExceptionTranslator;
26+
import org.springframework.jdbc.support.SQLExceptionTranslator;
2527
import org.springframework.lang.Nullable;
2628
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
2729

@@ -44,6 +46,26 @@
4446
*/
4547
public class HibernateExceptionTranslator implements PersistenceExceptionTranslator {
4648

49+
@Nullable
50+
private SQLExceptionTranslator jdbcExceptionTranslator;
51+
52+
53+
/**
54+
* Set the JDBC exception translator for Hibernate exception translation purposes.
55+
* <p>Applied to any detected {@link java.sql.SQLException} root cause of a Hibernate
56+
* {@link JDBCException}, overriding Hibernate's own {@code SQLException} translation
57+
* (which is based on a Hibernate Dialect for a specific target database).
58+
* @since 5.1
59+
* @see java.sql.SQLException
60+
* @see org.hibernate.JDBCException
61+
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
62+
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
63+
*/
64+
public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) {
65+
this.jdbcExceptionTranslator = jdbcExceptionTranslator;
66+
}
67+
68+
4769
@Override
4870
@Nullable
4971
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
@@ -62,11 +84,21 @@ public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
6284
/**
6385
* Convert the given HibernateException to an appropriate exception from the
6486
* {@code org.springframework.dao} hierarchy.
87+
* <p>Will automatically apply a specified SQLExceptionTranslator to a
88+
* Hibernate JDBCException, otherwise rely on Hibernate's default translation.
6589
* @param ex the HibernateException that occurred
6690
* @return a corresponding DataAccessException
6791
* @see SessionFactoryUtils#convertHibernateAccessException
6892
*/
6993
protected DataAccessException convertHibernateAccessException(HibernateException ex) {
94+
if (this.jdbcExceptionTranslator != null && ex instanceof JDBCException) {
95+
JDBCException jdbcEx = (JDBCException) ex;
96+
DataAccessException dae = this.jdbcExceptionTranslator.translate(
97+
"Hibernate operation: " + jdbcEx.getMessage(), jdbcEx.getSQL(), jdbcEx.getSQLException());
98+
if (dae != null) {
99+
throw dae;
100+
}
101+
}
70102
return SessionFactoryUtils.convertHibernateAccessException(ex);
71103
}
72104

spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.commons.logging.LogFactory;
2626
import org.hibernate.FlushMode;
2727
import org.hibernate.HibernateException;
28+
import org.hibernate.JDBCException;
2829
import org.hibernate.NonUniqueObjectException;
2930
import org.hibernate.NonUniqueResultException;
3031
import org.hibernate.ObjectDeletedException;
@@ -58,6 +59,7 @@
5859
import org.springframework.dao.PessimisticLockingFailureException;
5960
import org.springframework.jdbc.datasource.ConnectionHandle;
6061
import org.springframework.jdbc.datasource.DataSourceUtils;
62+
import org.springframework.jdbc.support.SQLExceptionTranslator;
6163
import org.springframework.lang.Nullable;
6264
import org.springframework.orm.ObjectOptimisticLockingFailureException;
6365
import org.springframework.orm.ObjectRetrievalFailureException;
@@ -108,6 +110,9 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
108110

109111
boolean prepareConnection = true;
110112

113+
@Nullable
114+
private SQLExceptionTranslator jdbcExceptionTranslator;
115+
111116

112117
/**
113118
* Set whether to prepare the underlying JDBC Connection of a transactional
@@ -135,6 +140,21 @@ public void setPrepareConnection(boolean prepareConnection) {
135140
this.prepareConnection = prepareConnection;
136141
}
137142

143+
/**
144+
* Set the JDBC exception translator for Hibernate exception translation purposes.
145+
* <p>Applied to any detected {@link java.sql.SQLException} root cause of a Hibernate
146+
* {@link JDBCException}, overriding Hibernate's own {@code SQLException} translation
147+
* (which is based on a Hibernate Dialect for a specific target database).
148+
* @since 5.1
149+
* @see java.sql.SQLException
150+
* @see org.hibernate.JDBCException
151+
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
152+
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
153+
*/
154+
public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) {
155+
this.jdbcExceptionTranslator = jdbcExceptionTranslator;
156+
}
157+
138158

139159
@Override
140160
public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition)
@@ -244,6 +264,15 @@ public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
244264
* @return the corresponding DataAccessException instance
245265
*/
246266
protected DataAccessException convertHibernateAccessException(HibernateException ex) {
267+
if (this.jdbcExceptionTranslator != null && ex instanceof JDBCException) {
268+
JDBCException jdbcEx = (JDBCException) ex;
269+
DataAccessException dae = this.jdbcExceptionTranslator.translate(
270+
"Hibernate operation: " + jdbcEx.getMessage(), jdbcEx.getSQL(), jdbcEx.getSQLException());
271+
if (dae != null) {
272+
throw dae;
273+
}
274+
}
275+
247276
if (ex instanceof JDBCConnectionException) {
248277
return new DataAccessResourceFailureException(ex.getMessage(), ex);
249278
}

0 commit comments

Comments
 (0)