JDBC
API는 SQLException
이라는 체크 예외를 반환한다. 따라서 다른 클래스들이 JDBC에 종속적이 되는 문제가 있다. SQLException
은 에러를 구분하기 위해 에러 코드를 이용하는데, 데이터베이스마다 이 에러 코드가 다 다르다.
Spring
에서는 이 문제를 해결하기 위해 예외 추상화 계층과 예외 번역기를 제공한다. 예외 번역기는 SQLException
을 런타임 예외인 DataAccessException
으로 바꿔준다. 덕분에 클래스는 SQLException
이 아닌 추상화된 스프링 데이터 접근 예외에 의존할 수 있게 된다.
DataAccessException
flowchart BT
re[RuntimeException]
da[DataAccessException]
nt[NonTransient\nDataAccessException]
di[Data\nIntegrity\nViolation\nException]
bs[BadSql\nGrammar\nException\n]
dk[DuplicateKey\nException\n]
td[Transient\nDataAccessException]
qt[Query\nTimeout\nException\n]
ol[Optimistic\nLocking\nFailure\nException\n]
pl[Pessimistic\nLocking\nFailure\nException\n]
da --> re
nt --> da
di --> nt
dk --> di
bs --> nt
td --> da
qt --> td
ol --> td
pl --> td
예외는 크게 두 종류로 NonTransientDataAccessException
과 TransientDataAccessException
이 있다. 전자는 다시 수행해도 성공할 가능성이 없는 예외들로, 잘못된 SQL을 썼을 때, 중복 키를 사용했을때 등의 상황에 발생한다. 후자는 일시적으로 발생할 수 있는 예외들로, 타임아웃 예외와 락 실패 예외가 해당된다.
SQLExceptionTranslator
SQLException
을 DataAccessException
으로 변환하려면 SQLExceptionTranlator
구현체를 사용하면 된다. 에러 코드로 예외가 구분되는 경우라면 SQLErrorCodeSQLExceptionTranlator
를 사용하면 된다.
SQLExceptionTranslator.translate()
메소드는 인자로 task, sql, exception을 받아 DataAccessException
으로 변환해준다.
catch (SQLException e) {
SQLExceptionTranslator exTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource);
DataAccessException ex = exTranslator.tranlsate("select", sql, e);
}