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
.