[Spring] 스프링의 데이터 접근 예외 추상화와 JdbcTemplate

2025. 4. 7. 22:42·Spring
728x90
반응형

JDBC 체크 예외 문제와 인터페이스

서비스 계층은 특정 기술에 종속되지 않고 순수성을 유지하는 것이 좋다. 하지만 JDBC를 사용할 때 SQLException이라는 체크 예외가 발생하여 인터페이스가 특정 기술에 종속되는 문제가 생긴다. 이를 해결하려면 체크 예외를 런타임 예외로 전환하여 처리하는 방법을 사용한다.

런타임 예외로 전환하는 이유

  • 체크 예외(SQLException)를 사용하면 인터페이스에도 이 예외를 명시해야 해서 특정 기술(JDBC)에 종속된다.
  • 런타임 예외를 사용하면 인터페이스에 별도 선언 없이 예외를 던질 수 있어 서비스 계층이 특정 기술에 종속되지 않게 된다.

직접 만든 런타임 예외 적용법

  1. MyDbException이라는 런타임 예외를 만들어 SQLException을 감싼다.
public class MyDbException extends RuntimeException {
    public MyDbException(Throwable cause) {
        super(cause);
    }
}
  1. 데이터 접근 기술(JDBC)에서 발생하는 체크 예외(SQLException)를 런타임 예외(MyDbException)로 변환하여 서비스 계층으로 전달한다.
catch (SQLException e) {
    throw new MyDbException(e);
}

이로 인해 서비스 계층은 JDBC라는 구체적인 구현 기술에 종속되지 않고 인터페이스만을 통해서 리포지토리를 사용할 수 있게 된다.

예외를 구분해 처리하는 방법

데이터베이스에서 특정 예외를 복구할 필요가 있을 때, 예외를 구분할 수 있도록 직접 예외를 만든다. 예를 들어 중복 키 예외(MyDuplicateKeyException)를 만들고, 이를 별도의 예외로 던져서 서비스 계층에서 복구 로직을 수행할 수 있다.

if (e.getErrorCode() == 23505) {
    throw new MyDuplicateKeyException(e);
}

스프링의 데이터 접근 예외 추상화

스프링은 JDBC와 같은 특정 기술에 종속되지 않도록 데이터 접근 예외를 추상화하여 제공한다. 이를 통해 JDBC를 사용하든 JPA를 사용하든 서비스 계층은 스프링의 예외만을 사용하여 예외 처리를 할 수 있다.

  • 스프링은 데이터베이스에서 나오는 다양한 오류 코드를 일관된 예외로 변환하는 SQLExceptionTranslator를 제공한다.
SQLExceptionTranslator exTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource);
DataAccessException translatedException = exTranslator.translate("query", sql, e);
  • 각각의 DB마다 SQL 에러코드가 다른데 스프링은 어떻게 각각의 DB가 제공하는 SQL 에러코드까지 고려해서 예외를 변환할 수 있을까?
    • org.springframework.jdbc.support.sql-error-codes.xml 파일에서 에러코드와 예외를 매핑한다.
    • 스프링 SQL 예외 변환기(SQLExceptionTranslator)는 이 파일에 대입해서 어떤 스프링 데이터 접근 예외로 전환해야 할지 찾아낸다
  • 스프링의 데이터 접근 예외는 모두 런타임 예외이므로 인터페이스를 오염시키지 않고 순수성을 유지한다.

스프링의 JdbcTemplate 활용

스프링은 JDBC를 사용할 때 반복되는 다음과 같은 문제들을 해결하는 JdbcTemplate을 제공한다.

  • 커넥션 획득 및 동기화
  • PreparedStatement 처리
  • SQL 쿼리 실행
  • 예외 처리 및 변환
  • 리소스 자동 관리

다음은 JdbcTemplate을 사용한 간단한 예시이다.

JdbcTemplate template = new JdbcTemplate(dataSource);

String sql = "insert into member(member_id, money) values(?, ?)";
template.update(sql, member.getMemberId(), member.getMoney());

JdbcTemplate의 추가 기능과 활용

NamedParameterJdbcTemplate

JdbcTemplate의 기본적인 순서 기반 파라미터 바인딩은 유지보수가 어렵다. 이를 해결하기 위해 스프링은 이름을 기준으로 파라미터를 바인딩하는 NamedParameterJdbcTemplate을 제공한다.

NamedParameterJdbcTemplate namedTemplate = new NamedParameterJdbcTemplate(dataSource);
String sql = "insert into item (item_name, price) values (:itemName, :price)";
SqlParameterSource params = new MapSqlParameterSource()
    .addValue("itemName", "Item1")
    .addValue("price", 10000);
namedTemplate.update(sql, params);

BeanPropertySqlParameterSource

객체의 프로퍼티를 자동으로 파라미터로 매핑하여 전달하는 데 사용된다.

SqlParameterSource params = new BeanPropertySqlParameterSource(item);
namedTemplate.update(sql, params);

SimpleJdbcInsert

SimpleJdbcInsert를 사용하면 간단한 Insert 작업을 더욱 쉽게 처리할 수 있다.

SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(dataSource)
    .withTableName("item")
    .usingGeneratedKeyColumns("id");

SqlParameterSource params = new BeanPropertySqlParameterSource(item);
Number key = jdbcInsert.executeAndReturnKey(params);
item.setId(key.longValue());

BeanPropertyRowMapper

데이터베이스 조회 결과(ResultSet)를 자동으로 객체로 매핑한다. 컬럼명과 객체의 프로퍼티 이름이 다를 경우 별칭(alias)을 사용하면 된다.

private RowMapper<Item> itemRowMapper() {
    return BeanPropertyRowMapper.newInstance(Item.class);
}

List<Item> items = namedTemplate.query("select id, item_name as itemName from item", itemRowMapper());

자바빈(JavaBean) 규약

자바빈(JavaBean) 규약이란 객체의 속성에 접근할 때 getter와 setter라는 메서드를 사용하는 규약을 말한다.

  • 프로퍼티가 itemName이라면 메서드는 getItemName(), setItemName() 형태로 작성해야 한다.
  • BeanPropertySqlParameterSource와 BeanPropertyRowMapper는 이 규약을 기반으로 객체와 데이터베이스의 결과를 자동으로 매핑한다.

정리

  • 체크 예외를 런타임 예외로 변환하면 인터페이스가 특정 기술에 종속되지 않는다.
  • 스프링이 제공하는 데이터 접근 예외 추상화와 예외 변환기 덕분에 서비스 계층은 데이터 접근 기술의 변경에도 영향을 받지 않고 유지할 수 있다.
  • JdbcTemplate과 관련된 기능들은 JDBC의 반복 작업을 효과적으로 줄이고, 코드를 더 깔끔하고 유지보수하기 쉽게 만들어준다.
728x90
반응형

'Spring' 카테고리의 다른 글

[Spring] Spring Transaction 핵심 요약  (0) 2025.04.10
[Spring Core] Spring Core 핵심 개념  (0) 2025.02.15
[Spring Core] 스프링을 사용하는 이유?  (0) 2025.02.15
'Spring' 카테고리의 다른 글
  • [Spring] Spring Transaction 핵심 요약
  • [Spring Core] Spring Core 핵심 개념
  • [Spring Core] 스프링을 사용하는 이유?
mxruhxn
mxruhxn
소소하게 개발 공부 기록하기
    반응형
    250x250
  • mxruhxn
    maruhxn
    mxruhxn
  • 전체
    오늘
    어제
    • 분류 전체보기 (150)
      • Java (21)
      • Spring (4)
      • Database (13)
      • Operating Syste.. (1)
      • Computer Archit.. (0)
      • Network (24)
      • Data Structure (6)
      • Algorithm (11)
      • Data Infra (7)
      • DevOps (12)
      • ETC (27)
      • Project (21)
      • Book (1)
      • Look Back (1)
  • 블로그 메뉴

    • 링크

      • Github
    • 공지사항

    • 인기 글

    • 태그

    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.0
    mxruhxn
    [Spring] 스프링의 데이터 접근 예외 추상화와 JdbcTemplate
    상단으로

    티스토리툴바