|
25 | 25 | import org.apache.commons.logging.LogFactory;
|
26 | 26 | import org.hibernate.FlushMode;
|
27 | 27 | import org.hibernate.HibernateException;
|
| 28 | +import org.hibernate.JDBCException; |
28 | 29 | import org.hibernate.NonUniqueObjectException;
|
29 | 30 | import org.hibernate.NonUniqueResultException;
|
30 | 31 | import org.hibernate.ObjectDeletedException;
|
|
58 | 59 | import org.springframework.dao.PessimisticLockingFailureException;
|
59 | 60 | import org.springframework.jdbc.datasource.ConnectionHandle;
|
60 | 61 | import org.springframework.jdbc.datasource.DataSourceUtils;
|
| 62 | +import org.springframework.jdbc.support.SQLExceptionTranslator; |
61 | 63 | import org.springframework.lang.Nullable;
|
62 | 64 | import org.springframework.orm.ObjectOptimisticLockingFailureException;
|
63 | 65 | import org.springframework.orm.ObjectRetrievalFailureException;
|
@@ -108,6 +110,9 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
108 | 110 |
|
109 | 111 | boolean prepareConnection = true;
|
110 | 112 |
|
| 113 | + @Nullable |
| 114 | + private SQLExceptionTranslator jdbcExceptionTranslator; |
| 115 | + |
111 | 116 |
|
112 | 117 | /**
|
113 | 118 | * Set whether to prepare the underlying JDBC Connection of a transactional
|
@@ -135,6 +140,21 @@ public void setPrepareConnection(boolean prepareConnection) {
|
135 | 140 | this.prepareConnection = prepareConnection;
|
136 | 141 | }
|
137 | 142 |
|
| 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 | + |
138 | 158 |
|
139 | 159 | @Override
|
140 | 160 | public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition)
|
@@ -244,6 +264,15 @@ public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
244 | 264 | * @return the corresponding DataAccessException instance
|
245 | 265 | */
|
246 | 266 | 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 | + |
247 | 276 | if (ex instanceof JDBCConnectionException) {
|
248 | 277 | return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
249 | 278 | }
|
|
0 commit comments