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.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ