개요#

4.1. 사라진 SQLException#

public void deleteAll() throws SQLException {
	this.jdbcContext.executeSql("delete from users");
}
public void deleteAll() {
	this.jdbcTemplate.update("delete from users");
}

4.1.1. 초난감 예외처리#

예외블랙홀#

  • 초난감 예외처리 코드 1
try{
...
} catch( SQLEXception e ) {
}
  • 초난감 예외처리 코드 2
} catch( SQLEXception e ) {
	System.out.println(e);
}

  • 초난감 예외처리 코드 3
} catch( SQLEXception e ) {
	e.printStackTrace();
}
  • 모든 예외는 적절하게 복구되든지 아니면 작업을 중단시키고 운영자 또는 개발자에게 분명하게 통보돼야 한다.

4.1.2. 예외의 종류와 특징#

Error#

Exception 과 체크예외#

RuntimeException과 언체크/런타임 예외#

4.1.3. 예외처리 방법#

예외복구#

  • 예외상황을 파악하고 문제를 해결해서 정상상태로 돌려놓는다.
    • 재시도?
int maxretry = MAX_RETRY;
while(maxretry -- > 0 ) {
	try {
		...
		return;
	} catch( SomeException e ) {
		// 로그출력, 정해진 시간만큼 대기
	} finally {
		// 리소스 반납, 정리작업
	}	
}

throw new RetryFailedException();

예외처리 회피#

  • 예외처리를 자신이 담당하지 않고 자신을 호출한 쪽으로 던져버린다.
  • 예외처리 회피1
public void add() throws SQLException {
	// JDBC API
}
  • 예외처리 회피2
public void add() throws SQLException {
	try {
		// JDBC API
	} catch ( SQLException e ) {
		// 로그출력
		throw e;
	}
}

4.1.4. 예외처리 전략#

런타임 예외의 보편화#

add() 메소드의 예외처리#

public class DuplicateUserIdException extends RuntimeException {
	public DuplicateUserIdException(Throwable cause) {
		super(cause);
	}
}
public void add() throws DuplicateUserIdException {
	try {
		
	} catch (SQLException e) {
		if( e.getErrorCode() == MysqlErrorNumbers.ER_DUP_ENTRY )
			throw new DuplicateUserIdException(e);
		else 
			throw new RuntimeException(e);
	}
}

애플리케이션 예외#

  • 런타임 예외 중심의 전략은 낙관적인 예외처리 기법이라고 할 수 있다.
  • 시스템 또는 외부의 예외상황이 원인이 아니라 애플리케이션 자체의 로직에 의해 의도적으로 발생시키고 반드시 catch해서 무엇인가 조치를 취하도록 요구하는 예외를 애플리케이션 예외라고 한다.

4.1.5. SQLException은 어떻게 됐나?#

  • SQLException 은 과연 복구가 가능한 예외인가?
    • 코드레벨에서는 복구할 방법이 없다.
    • 프로그램 오류 또는 개발자의 부주의 때문에 발생하거나 통제할 수 없는 외부상황 때문에 발생한다.
    • 즉 관리자나 개발자에게 빨리 예외가 발생했다는 사실이 알려지도록 전달하는 방법밖에 없다.
    • 따라서 예외처리 전략을 사용해야 한다. 즉 가능한한 빨리 언체크/런타임 예외로 전환해줘야 한다.
    • JdbcTemplate은 템플릿과 콜백에서 발생하는 모든 SQLException을 런타임 예외인 DataAccessException 으로 포장해서 던져준다.

4.2. 예외전환#

  • 예외전환의 목적
    • 런타임 예외로 포장해서 굳이 필요하지 않은 catch/throws 를 줄여준다.
    • 로우레벨의 예외를 좀더 의미있고 추상화된 예외로 바꿔준다.

4.2.1. JDBC의 한계#

  • JDBC는 자바 표준 JDK에서 가장 많이 사용하는 기능이다.
  • JDBC라는 추상화를 통해 개발자는 DB제품에 상관없이 일관적으로 개발을 할 수 있다.
  • 하지만 DB마다 자유롭게 변경해서 사용할 수 있는 유연한 코드를 보장해주지는 못한다.

비표준 SQL#

  • SQL 은 어느정도 표준화된 언어이다.
  • 대부분의 DB는 표준을 따르지 않는 비표준 문법과 기능을 제공한다.
  • DB의 변경가능성을 고려해서 유연하게 만드려면 SQL이 가장 큰 걸림돌이다.
    • DB변경시 SQL을 변경해야 한다.

호환성 없는 SQLException의 DB에러 정보#

  • DB를 사용하다보면 발생할 수 있는 예외의 원인은 다양하다.
  • 문제는 SQL만 다른게 아니라 에러의 종류와 원인도 제각각이라는 점이다.
  • JDBC는 다양한 에러를 SQLException 하나에 모두 담아버린다.
  • 예외가 발생한 원인은 SQLException에 담긴 에러코드와 SQL상태정보를 참조해야 한다.
  • SQLException의 getErrorCode()의 결과는 DB마다 다르다.
  • 에러코드가 에러 상황을 정확히 반영하지도 않는다.

4.2.2. DB에러 코드 매핑을 통한 전환#

  • SQLException의 비표준 에러코드와 SQL 상태정보에 대한 해결책은?
  • 해결방법은 DB별 에러코드를 참고해서 발생한 예외의 원인이 무엇인지 해석해주는 기능을 만드는 것이다.
  • 스프링은 DataAccessException 의 서브클래스로 세분화된 예외클래스를 제공한다.
    • SQL 문법오류 : BadSqlGrammarException
    • DB커넥션을 가져오지 못하는 경우 : CannotGetJdbcConnectionException
    • 데이터 제약조건을 위배하거나 일관성을 지키지 않는 작업을 수행할때 : DataIntegrityViolationException
    • 중복키 오류 : DuplicateKeyException
  • JdbcTemplate은 SQLException을 단지 런타임 예외인 DataAccessException으로 포장하는 것이 아니라 DB의 에러코드를 DataAccessException 계층구조 클래스 중 하나로 매핑해준다.
  • JDK 1.6에 포함된 JDBC 4.0부터는 조금더 세분화해서 제공하고 있다.

4.2.3. DAO 인터페이스와 DataAccessException 계층구조#

  • DataAccessException 은 SQLException을 전환한다.
  • JDBC외 하이버네이트와 같은 ORM, JPA, 아이바티스 등이 사용하는 모든 예외를 처리해서 데이터 엑세스 기술에 상관없이 일관된 예외가 발생하도록 해준다.

DAO 인터페이스와 구현의 분리#

  • DAO를 분리해서 사용하는 이유는 데이터 엑세스 로직은 담은 코드를 다른 코드와 분리하기 위함이다.
  • 하지만 다음처럼 메소드가 선언될 경우 SQLException으로 인해 DAO를 명확히 분리할수가 없다.
public void add(User user) throws SQLException;

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-10) was last changed on 08-Nov-2014 11:45 by DongGukLee