Java
[Java] SQLException에 대해서 / 무분별한 try-catch절
bkuk
2023. 3. 24. 22:18
무분별한 SQLException에 대한 처리
우선, 아래 코드를 보자.
// 1. 클라이언트가 전달한 userId로 user 객체 가져옴
try {
user = userDao.findByUserId( req.getParameter("userId") );
} catch (SQLException e) {
e.printStackTrace();
}
// 2. user 객체를 수정함
user.updateUser(
req.getParameter("userId"),
req.getParameter("password"),
req.getParameter("name"),
req.getParameter("email"));
// 3. Db에 다시 업데이트함
try {
userDao.update(user);
} catch (SQLException e) {
e.printStackTrace();
}
SQLException은 컴파일타임 Exception이기 때문에 매번 위와 같이 반드시 try-catch절을 통해서 Exception 처리를 해야 한다. 컴파일타임 Exception은 Checked Exception과 같고, 이에 반대되는 개념으로는 UnChecked Exception이라고 불리우는 런타임 Exception이 있다. 아래 표를 보면서 확인해보자.
구분 | Checked Exception | UnChecked Exception |
확인 시점 | 컴파일(Compile) 시점 | 런타임(Runtime) 시점 |
처리 여부 | 반드시 예외 처리해야 함 | 명시적으로 하지 않아도 됨 |
종류 | IOException, ClassNotFoundException 등 | NullPointerException, ClassCastException 등 |
위 코드에서, SQLException이 발생하면 catch절을 통해서
e.printStackTrace();
가 실행된다.
따라서, SQLException을 catch한다고 해서 에러 로그를 남기는 것외에 별달리 다른 작업을 할 부분이 생각나지 않는다. 컴파일타임 Exception으로 설계하지 않아도 되는 곳에서 컴파일타임 Exception을 사용함으로써 불필요하게 try-catch절로 감싸야하며, 이는 소스코드의 가독성을 떨어트리는 주범이 되고 있다.
SQLException을 런타임 Exception으로 변환해 throw하자.
RuntimeException을 상속하는 커스텀 Exception(DataAccessException과 같은 이름)을 추가한 후 SQLException을 새로 추가한 커스텀 Exception을 변환해 throw 하도록 구현 한다.
RuntimeException을 상속하는 커스텀 Exception
public class DataAccessException extends RuntimeException {
private static final long serialVersionUID = 1L;
public DataAccessException() {
super();
}
public DataAccessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public DataAccessException(String message, Throwable cause) {
super(message, cause);
}
public DataAccessException(String message) {
super(message);
}
public DataAccessException(Throwable cause) {
super(cause);
}
}
JdbcTemplate 리팩토링
- SQLException이 발생하면 DataAccessException을 던짐.
public class JdbcTemplate{
public void update(String query, PreparedStatementSetter pss) throws DataAccessException {
[...]
} catch (SQLException e) {
throw new DataAccessException();
}
}
public <T> List<T> query(String query, RowMapper<T> rowMapper,
PreparedStatementSetter pss) throws DataAccessException {
[...]
} catch (SQLException e) {
throw new DataAccessException();
} finally {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
throw new DataAccessException();
}
}
}