SQLExceptionTranslator
– это интерфейс, который должен быть реализован классами, способными выполнять преобразование между SQLExceptions
и собственными org.springframework.dao.DataAccessException
, которые не зависят от стратегии доступа к данным. Реализации могут быть типизированными (например, использование кодов SQLState для JDBC) или проприетарными (например, использование кодов ошибок Oracle) для большей точности.
SQLErrorCodeSQLExceptionTranslator
– это реализация SQLExceptionTranslator
, которая используется по умолчанию. В данной реализации используются определенные коды производителей. Она является более точной, чем реализация SQLState.
Преобразование кодов ошибок основано на кодах, хранящихся в классе типа JavaBean под названием SQLErrorCodes
. Этот класс создается и заполняется SQLErrorCodesFactory
, которая (как следует из названия) является фабрикой для создания SQLErrorCodes
на основе содержимого конфигурационного файла sql-error-codes.xml
. Этот файл заполняется кодами производителей и основывается на DatabaseProductName
, взятом из DatabaseMetaData
. Используются коды для фактической базы данных, которую вы используете.
SQLErrorCodeSQLExceptionTranslator
применяет правила согласования в следующей последовательности:
-
Любое кастомное преобразование, реализованное подклассом. Обычно используется конкретный
SQLErrorCodeSQLExceptionTranslator
, поэтому это правило не применяется. Оно применимо только в том случае, если вы действительно предоставили реализацию подкласса. -
Любая кастомная реализация интерфейса
SQLExceptionTranslator
, которая предоставляется как свойствоcustomSqlExceptionTranslator
классаSQLErrorCodes
. -
В списке экземпляров класса
CustomSQLErrorCodesTranslation
(предоставленных для свойстваcustomTranslations
классаSQLErrorCodes
) выполняется поиск совпадения. -
Применяется сопоставление кодов ошибок.
-
Используется возвратный преобразователь (translator).
SQLExceptionSubclassTranslator
является преобразователем по умолчанию. Если этот перевод недоступен, следующим возвратным преобразователем являетсяSQLStateSQLExceptionTranslator
.
SQLErrorCodesFactory
используется по умолчанию для определения кодов Error
и кастомных преобразований исключений. Они ищутся в файле sql-error-codes.xml
из classpath, а соответствующий экземпляр SQLErrorCodes
находится на основе имени базы данных из метаданных используемой базы данных.Можно расширить SQLErrorCodeSQLExceptionTranslator
, как показано в следующем примере:
public class CustomSQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator {
protected DataAccessException customTranslate(String task, String sql, SQLException sqlEx) {
if (sqlEx.getErrorCode() == -12345) {
return new DeadlockLoserDataAccessException(task, sqlEx);
}
return null;
}
}
class CustomSQLErrorCodesTranslator : SQLErrorCodeSQLExceptionTranslator() {
override fun customTranslate(task: String, sql: String?, sqlEx: SQLException): DataAccessException? {
if (sqlEx.errorCode == -12345) {
return DeadlockLoserDataAccessException(task, sqlEx)
}
return null
}
}
В предыдущем примере преобразовывается конкретный код ошибки (-12345
), а остальные ошибки остаются на усмотрение стандартной реализации преобразователя. Чтобы использовать этот кастомный преобразователь, нужно передать его в JdbcTemplate
через метод setExceptionTranslator
, а затем использовать этот JdbcTemplate
для любой обработки доступа к данным, где этот преобразователь необходим. В следующем примере показано, как можно использовать этот кастомный преобразователь:
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
// создаем шаблон JdbcTemplate и устанавливаем источник данных
this.jdbcTemplate = new JdbcTemplate();
this.jdbcTemplate.setDataSource(dataSource);
// создаем кастомный преобразователь и устанавливаем источник данных для поиска преобразования по умолчанию
CustomSQLErrorCodesTranslator tr = new CustomSQLErrorCodesTranslator();
tr.setDataSource(dataSource);
this.jdbcTemplate.setExceptionTranslator(tr);
}
public void updateShippingCharge(long orderId, long pct) {
// используем подготовленный шаблон JdbcTemplate для этого обновления
this.jdbcTemplate.update("update orders" +
" set shipping_charge = shipping_charge * ? / 100" +
" where id = ?", pct, orderId);
}
// создаем шаблон JdbcTemplate и устанавливаем источник данных
private val jdbcTemplate = JdbcTemplate(dataSource).apply {
// создаем кастомный преобразователь и устанавливаем источник данных для поиска преобразования по умолчанию
exceptionTranslator = CustomSQLErrorCodesTranslator().apply {
this.dataSource = dataSource
}
}
fun updateShippingCharge(orderId: Long, pct: Long) {
// используем подготовленный шаблон JdbcTemplate для этого обновления
this.jdbcTemplate!!.update("update orders" +
" set shipping_charge = shipping_charge * ? / 100" +
" where id = ?", pct, orderId)
}
Кастомному преобразователю передается источник данных для поиска кодов ошибок в sql-error-codes.xml
.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ