기본 콘텐츠로 건너뛰기

[Spinrg] 데이터 접근(JDBC, Tx)에 대해 알아보자

 이번 시간에는 애플리케이션을 개발 할 때 빠질 수 없응 데이터 접근 기능에 대해 알아보겠다.

 스프링이 제공하는 JDBC, 트랜잭션 관리, 데이터 접근 예외 처리 기능을 다뤄보려 한다.

 이번 장에선 ORM과 관련 내용은 배제 하였다.

스프링 프레임워크와 데이터 소스

데이터 소스 개요
데이터 소스는 애플리케이션에서 데이터 베이스에 접근하기 위한 커넥션을 제공한다.
스프링에서 제공하는 데이터 소스는 다음 3가지가 있다.

애플리케이션 모듈이 제공하는 데이터 소스
데이터 베이스에 접속하기 위한 사용자 ID, PW, 접속대상 URL같은 데이터베이스 접속 정보를
애플리케이션이 직접 관리하고 데이터 소스에 설정해야 한다.

애플리케이션 서버가 제공하는 데이터 소스
애플리케이션 서버가 정의한 데이터 소스를 JNDI(Java Naming and Directory Interface)를 가져와 사용하는
방식이다. 데이터베이스에 접속하기 위한 정보를 애플리케이션 서버에서 관리한다.

내장형 데이터베이스를 사용하는 데이터 소스
H2, Apache Derby 같은 내장 데이터베이스에 접속하기 위한 데이터 소스를 말한다.
사전 준비 없이 애플리케이션 가동할 때 데이터 소스의 설정과 생성이 자동으로 이뤄진다.

스프링 JDBC

스프링 JDBC 개요
SQL의 실제 내용과는 상관 없이 공통적이면서 반복적으로 수행되는 JDBC 처리를 개발자가 직접 구현하는 대신
프레임워크가 대행하는 기능을 제공한다.
공통적인 일에는 커넥션 연결/종료, SQL문 실행, SQL 문 실행결과 반복처리, 예외처리등이 있다.

JdbcTemplate 클래스를 활용한 CRUD
SQL만 가지고도 데이터베이스를 쉽게 다룰 수 있게 도와 주는 클래스를 제공한다. 특히 NamedParameterJdbcTemplate 클래스는 사실상 데이를 조작하는 처리를 JdbcTemplate 클래스에 위임한다.
개발자는 JdbcTemplate 클래스를 사용할때 DI로 받는게 일반적이다.
>> @Autowired JdbcTemplate jdbcTemplate;

JdbcTemplate 클래스가 제공해주는 주요 메서드
  • queryForObject : 하나의 결과 레코드 중 하나의 컬럼 값을 가져올 떄 사용.
  • queryForMap : 하나의 결과 레코드 정보를 Map 형태로 매핑
  • queryForList : 여르 개의 결과 레코드를 다룰 수 있음
  • query : 조회할 때 사용
  • update : upate에 사용.

칼럼 조회 할 때 네임드 파리미터 사용
동적인 쿼리문 시 바인드 변수 ‘?’를 사용할 수 있지만, 바인딩 순서가 틀리면 에러를 보이는 경우가 있다.
이럴 때 보완하려 ‘네임드 파라미터'가 나왔다. NamedParameterJdbcTemplate를 주입받아 사용한다.
NamedPramterJdbcTemplate 메서드에 바인드할 변수의 이름을 Map으로 받을 수 있지만, MapSqlParameterSource로 받으면 파라미터 설정이 쉬워진다.

바인드 변수 사용
String sql = “select room_name from room where room_id = ?”;

네임드 파라미터 사용
String sql = “select room_name from room where room_id = :roomId;

스프링 JDBC는 처리 결과 값을 자바가 기본적으로 제공하는 데이터 타입이나 Map, List 같은 컬렉션 타입으로
변환한다.

트랜잭션 관리

트랜잭션 관리자
관계형 데이터베이스에 데이터에 접근할 때는 트랜잭션의 경계가 어디까지고, 어떻게 관리되는지 이해하고
있어야 한다. 스프링에선 이러한 처리를 쉽게 구현하도록 도와주는 기능이 있다.
스프링 트랜잭션 처리의 중심이 되는 인터페이스는 PlatformTransactionManager다.

로컬 트랜잭션을 이용하는 경우
JDBC API를 호출하고 트랜잭션 제어를 수행하는 DataSourceTransactionManager를 사용한다.
단일 데이터 저장소에 대한 여러 조작을 하나의 논리적 단위로 처리하고 싶을 때 사용한다.
트랜잭션 관리자 빈 ID는 ‘transactionManger’를 쓰도록 하자.

글로벌 트랜잭션을 이용하는 경우
여러 데이터 저장소에 걸쳐서 적용되는 트랜잭션이다. JTA(Java Transaction API)라는 Java EE 사용으로
표준화 돼 있고 애플리케이션 서버가 JTA의 구현 클래스를 제공한다. JtaTransactionManater를 선택해
사용하면 된다. 다만 애플리케이션 서버 제품마다 JTA 동작 방식이 달라서 JtaTransactionManater의 서브
클래스가 제공되기도 한다.

선언적 트랜잭션
미리 선언된 룰에 따라 트랜잭션을 제어하는 방법이다. 정해진 룰을 준수함 으로써 트랜잭션의 시작과 커밋, 롤백
등의 일반적 처리를 비즈니스 로직 안에 기술할 필요가 없다는 장점이 있다.
스프링에선 @Transactional 또는 XML 설정을 이용하는 두 가지 방법이 있다.

@Transactional을 이용하는 방법
@Transactional 애너테이션을 빈의 public 메서드에 추가하면 된다. 기본 동작 방식을 변경하려면 속성을
이용해 변경하면 된다.
  • @Transactional : 기본적인 트랜잭션 설정.
  • @Transactional(readOnly = true, timeout=60) : 읽기 전용 트랜잭션, 제한시간 60초
  • @Transactional(“txt1”) : txt1 트랜잭션 관리자를 이용.

기본 사용법
애너테이션은 클래스와 메서드에 부여할 수 있다. 차이는 애너테이션이 적용되는 범위이다.
@Transactional
@Service
public class BoardServiceImpl implements BoardService {

  BoardRepository repository;

  public BoardServiceImpl(BoardRepository repository) {
      this.repository = repository;
  }

  @Override
  @Transactional(readOnly = true)
  public Board getBoard(Long id) {
      return repository.findBoardById(id);
  }

  @Override
  @Transactional
  public Board addBoard(Board board) {
      return repository.save(board);
  }

  @Override
  @Transactional(readOnly = true)
  public List<Board> getBoards() {
      return repository.findAll();
  }
}

설정 클래스
@EnableTransactionManagement 애너테이션을 컴피규레이션 클래스에 부여하면 된다.
@Configuration
@EnableTransactionManagement
public class TransactionManagerConfig {
  @Autowired
  DataSource dataSource;
 
  @Bean
  public PlatformTransactionManager transactionManager() {
      return new DataSourceTransactionManager(dataSource);
  }
}

XML 설정을 이용한 선언적 트랜잭션
<tx:advice> 요소와 같은 tx로 시작하는 트랜색션 전용 XML 스키마를 사용한다. 서드파티에서 제공되는 클래스를 사용하는 경우와 같이 개발자가 직접 코드에 애너테이션을 부여하지 못하는 경우 xml 기반을 사용해 설정한다.

명시적 트랜잭션
트랜잭션 코드를 소스코드에 직접 명시적으로 기술하는 방법이다. 메서드 단위 보다 더 작은 단위로 제어하거나,
선언적 트랜잭션으로는 표현하기 어려운 섬세한 트랜잭션 제어가 필요할 때 이 방법을 사용한다. 스프링에션
PlatformTransactionManger와 TransactionTemplate를 사용하는 두 가지 방법을 제공한다.

태랜잭션 격리 수준과 전파방식
트랜색션 격리 수준
트랜잭션 격리 수준은 참조하는 데이터나 변경한 데이터를 다른 트랜젝션으로부터 어떻게 격리 할 것인지 결정
한다. 트랜잭션의 동시 실행과 데이터의 일관성과 깊이 관련있다. 기본 설정을 변경하고 싶다면,
@Transactionaml의 isolation 속성, TransactionDefinition과 TransactionTemplate의 setIsolationLevel
메서드에서 지정할 수 있다.

트랜잭션 전파방식
트랜잭션 경계에서 트랜잭션에 참여하는 방법을 결정한다.
 1. 트랜잭션 경계화 전파 방식
  • 트랜잭션 전파 방식을 의식해야 하는 경우는 트랜잭션 경계가 중첩됐을 때다.
  • 두 메서드가 각각 독립적인 트랜잭션으로 관리될지, 같은 트랜잭션 범위안에 들어갈지 트랜잭션 전파 방식에 따라 좌우된다.
 2. 스프링 프레임워크에서 이용 가능한 트랜잭션 전파방식
  • 기본값인 REQUIRED에서 다른 방식으로 변경하고 싶은 경우 @Transactional의 propafation 속성이나 TransactionDefinition과 TransactionTemplate의 setPropafationBehavior 메서드에서 지정할 수 있다.

데이터 접근 시 예외 처리

데이터 접근 관련 예외 처리

데이터 접근 예외는 비검사 예외로 구현돼 있다 예외 처리가 필요하다면 외예가 발생한 곳에 try-catch 문을 사용해 원하는 예외를 잡아 처리해야 한다.

댓글

이 블로그의 인기 게시물

[자바 웹 프로그래밍]2장 문자열 계산기 구현을 통한 테스트와 리펙토링

이번엔 2장에 나와 있는 내용 정리와 느낀점을 정리 해 보겠다. 1. main() 메소드를 활용한 테스트의 문제점.   - 소스코드 구현 후 정상적으로 동작하는지 확인 위해 일반적인 방법은 main()메소드를 활용하는 것이다.   - 실제 서비스를 담당하는 프로덕션 코드와 이 프로덕션 코드가 정상 동작 하는지 확인을 위한 main() 으로 나뉜다.   - 이 방법의 첫번째 문제점은 프로덕션코드와 main() 메서드가 함께 있다는 것이다.   - 프로덕션 코드와 테스트코드(main)을 분리할 수 있다.   - 두 번째 문제는 내가 구현하고 있는 메서드만 집중 할 수 없고, 클래스가 가지고 있는 모든 메서드를 테스트 할 수 밖에 없다.   - 다른 문제는 항상 콘솔로 확인을 할 수 밖에 없다는 것이다.   - 이를 위해 등장한 라이브러리가 JUnit 이다. 내 관심을 가지는 메서드에 대해 테스트 가능하다. 2. JUnit을 활용해 main() 메서드 문제 극복 2.1 한 번에 메서드 하나에만 집중.   - JUnit관련 라이브러리 추가 후  테스트 메서드에 @Test를 붙이면 된다.   - test 관련 코드 작성 후 Run > Run as> JunitTest를 실행해 보자.   - 각각 테스트 메서드를 독립적으로 실행할 수 있기 때문에 현재 내가 구현하고 있는 프로덕션 코드의 메서드에 집중할 수 있다. import org.junit.Test; public class CalculatorTest { @Test public void add() { Calculator cal = new Calculator(); System.out.println(cal.add(1,2)); } } 2.2 결과 값을 눈이 아닌 프로그램을 통해 자동화 import org.junit.Test; import static org.junit.Assert.assertEquals;

[고량주] 라오왕 연태고량주 플러스

나에게 처음 고량주란 이런것이다 라는걸 알려준 녀석이다. 부모님이 중국집을 하다 보니 가끔 초록색병 고량주를 먹었을때  역한 공업용 알콜 맛에 고량주는 나랑 안맞는다 생각했다가 우연히 양고기에 이녀석을 접한 뒤로 고량주의 맛을 알아버렸다... 제품명 : 라오왕 연태고량주플러스 제품유형 : 일반증류주 도수 : 34.2% 가격 : 9000원(홈플러스 익스프레스 기준) 재구매 의사 : 있다 시음평 : 역시 고량주 특유의 향인데, 열대과일 향도나고, 배향, 살짝 달달한 향이 난다.            목넘김은 34.2%에도 불구하고 그리 힘들지 않았다(주당이 된걸수도..)             중국요리나 양꼬치집에서 맛있는 술이 땡긴다면 강력추천한다.