59
59
import org .springframework .dao .PessimisticLockingFailureException ;
60
60
import org .springframework .jdbc .datasource .ConnectionHandle ;
61
61
import org .springframework .jdbc .datasource .DataSourceUtils ;
62
+ import org .springframework .jdbc .support .SQLExceptionSubclassTranslator ;
62
63
import org .springframework .jdbc .support .SQLExceptionTranslator ;
63
64
import org .springframework .lang .Nullable ;
64
65
import org .springframework .orm .ObjectOptimisticLockingFailureException ;
74
75
75
76
/**
76
77
* {@link org.springframework.orm.jpa.JpaDialect} implementation for Hibernate.
77
- * Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1/6.2.
78
+ * Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1/6.2/6.3 .
78
79
*
79
80
* @author Juergen Hoeller
80
81
* @author Costin Leau
@@ -91,6 +92,9 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
91
92
@ Nullable
92
93
private SQLExceptionTranslator jdbcExceptionTranslator ;
93
94
95
+ @ Nullable
96
+ private SQLExceptionTranslator transactionExceptionTranslator = new SQLExceptionSubclassTranslator ();
97
+
94
98
95
99
/**
96
100
* Set whether to prepare the underlying JDBC Connection of a transactional
@@ -121,14 +125,22 @@ public void setPrepareConnection(boolean prepareConnection) {
121
125
* <p>Applied to any detected {@link java.sql.SQLException} root cause of a Hibernate
122
126
* {@link JDBCException}, overriding Hibernate's own {@code SQLException} translation
123
127
* (which is based on a Hibernate Dialect for a specific target database).
128
+ * <p>As of 6.1, also applied to {@link org.hibernate.TransactionException} translation
129
+ * with a {@link SQLException} root cause (where Hibernate does not translate itself
130
+ * at all), overriding Spring's default {@link SQLExceptionSubclassTranslator} there.
131
+ * @param exceptionTranslator the {@link SQLExceptionTranslator} to delegate to, or
132
+ * {@code null} for none. By default, a {@link SQLExceptionSubclassTranslator} will
133
+ * be used for {@link org.hibernate.TransactionException} translation as of 6.1;
134
+ * this can be reverted to pre-6.1 behavior through setting {@code null} here.
124
135
* @since 5.1
125
136
* @see java.sql.SQLException
126
137
* @see org.hibernate.JDBCException
138
+ * @see org.springframework.jdbc.support.SQLExceptionSubclassTranslator
127
139
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
128
- * @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
129
140
*/
130
- public void setJdbcExceptionTranslator (SQLExceptionTranslator jdbcExceptionTranslator ) {
131
- this .jdbcExceptionTranslator = jdbcExceptionTranslator ;
141
+ public void setJdbcExceptionTranslator (@ Nullable SQLExceptionTranslator exceptionTranslator ) {
142
+ this .jdbcExceptionTranslator = exceptionTranslator ;
143
+ this .transactionExceptionTranslator = exceptionTranslator ;
132
144
}
133
145
134
146
@@ -245,7 +257,16 @@ protected DataAccessException convertHibernateAccessException(HibernateException
245
257
DataAccessException dae = this .jdbcExceptionTranslator .translate (
246
258
"Hibernate operation: " + jdbcEx .getMessage (), jdbcEx .getSQL (), jdbcEx .getSQLException ());
247
259
if (dae != null ) {
248
- throw dae ;
260
+ return dae ;
261
+ }
262
+ }
263
+ if (this .transactionExceptionTranslator != null && ex instanceof org .hibernate .TransactionException ) {
264
+ if (ex .getCause () instanceof SQLException sqlEx ) {
265
+ DataAccessException dae = this .transactionExceptionTranslator .translate (
266
+ "Hibernate transaction: " + ex .getMessage (), null , sqlEx );
267
+ if (dae != null ) {
268
+ return dae ;
269
+ }
249
270
}
250
271
}
251
272
0 commit comments