Embedded Database
-
Java Spring으로 만든 프로그램을 실행할 때 항상 같은 조건에서 실행시키기란 쉬운 일이 아니다. 외부 환경에 영향을 받는다면 자동화가 되기 어렵고, 때로 DB가 없는 환경에서 실행하거나 테스트 해야할 수 있을수도 있다.
-
스프링에서는 DB와의 테스트를 위해서 Embedded Database를 제공한다.
별도의 DB를 구동시키지 않아도, 테스트가 시작된 시점에 특정 버전에 맞는 MySQL 임베디드 데이터베이스가 구동되어 MySQL의 기능을 사용한 쿼리도 정상적으로 작동하게 된다.
-
임베디드 데이터베이스를 사용하는 것이 일반적이다.
공식 문서
-
pom.xml에 dependency를 추가해 준다.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
EmbeddedDatabase db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScript("schema.sql")
.build();
- pom.xml에 wix-embedded-mysql을 디펜던시에 추가해준다.
<dependency>
<groupId>com.wix</groupId>
<artifactId>wix-embedded-mysql</artifactId>
<version>x.y.z</version>
<scope>test</scope>
</dependency>
Embedded MySQL
- MySQL을 구현해주면 외부 데이터베이스를 사용하는 것처럼 테스트를 할 수 있다.
NamedParameterJdbcTemplate
- 기존 JdbcTemplate은 인덱스 기반에서 이름 기반의 파라미터를 설정할 수 있게 해주는 jdbc템플릿.
- 데이터를 넣을 부분에 '?'을 이용하여 처리를 했으나 이러한 방식은 인자 위치에 대한 순서가 강제하고 이는 가독성을 떨어뜨릴 수 있다.
- NamedParameterJdbcTemplate은 '?' 대신 ':변수명'을 이용함으로 순서를 강제받지 않을 수 있게 되었다.
- Map을 설정해 전달할 수 있다.
- 파라미터를 따로 넣어줄수도, HashMap에 넣을수도 있다.
- 키로 설정한 변수는 맵에도 들어가 있어야 한다. 키가 추후에 파라미터로 치환되기 때문.
DataAccessException
DataAccessException
- 보편적으로 발생하는 예외들을 추상화해 놓은 클래스이다.
SQLException
- JDBC는 모든 Exception을 SQLException 에 하나에 모두 담는다. 대부분의 SQLException은 복구가 가능한 예외가 아닌, 복구가 불가능한 시스템의 예외이다.
쉽게 말해 프로그램의 오류, 개발자의 부주의 때문에 발생하는 경우나 통제할 수 없는 외부상황 때문베 발생해 코드 레벨에서는 복구할 방법이 없다는 것이다.
- SQL 문법이 틀린 경우
- 제약 조건을 위반한 경우
- DB 서버가 다운된 경우
- 네트워크 불안정 등..
- 따라서 개발자가 빨리 인식할 수 있도록 가능한 한 빨리 언체크/런타임 예외로 전환해줘야 한다.
DataAccessException
- 스프링에서는 데이터 엑세스 익셉션이라는 sql익센셥 예외를 타입화 시킨다.
- SQLException에 대해 애플리케이션 레벨에서 신경을 쓰지 않도록 해주고, SQLException에 담긴 다루기 힘든 상세한 예외 정보를 의미 있는 예외로 전환시켜준다.
- DataAccessException은 또한 앞서 말했듯이 자바 데이터 액세스 기술에 상관없이 발생하는 예외에도 적용된다.
DB Transaction
트랜잭션
- 데이터베이스 트랜잭션 (Database Transaction)은 데이터베이스 관리 시스템 또는 유사한 시스템에서 상호작용의 단위이다. 여기서 유사한 시스템이란 트랜잭션의 성공과 실패가 분명하고 상호 독립적이며 일관되고 믿을 수 있는시스템을 의미한다.
- 단일 트랜잭션은 데이터베이스 내에 읽거나 쓰는 여러개의 쿼리를 요구하며 이때 중요한 것은 데이터베이스가 수행된 일부 쿼리가 남지 않는 것이다.
트랜잭션은 서로 간섭하지 않아야한다.
- '거래'라는 뜻으로 작업을 수행하기 위해 필요한 데이터베이스 연산들을 모아놓은 것으로 논리적인 작업의 한 단위.
- 여러 단계의 처리를 하나의 처리처럼 다루는 기능이다.
- 트랜잭션은 여러 명령어의 집합이 정상적으로 처리되면 정상 종료되나, 하나의 명령이라도 잘못되면 전체 취소된다.
- 데이터의 일관성을 유지하면서 안정적으로 데이터를 복구할 수 있다.
- 문제가 발생할 시 ~~을 하겠다, 하는 구조의 시스템을 보상 트랜잭션이라 하는데, 이는 만들기가 번거롭고 복잡하며, 때로 더 큰 문제를 만들 수 있다.
따라서 무언가 오류가 생기면 발생한 모든 작업을 없었던 것으로 되돌린다.
- 트랜잭션은 이와 같은 방법으로 작업의 안정성을 확보할 수 있다.
DML을 묶어서 처리하는 것을 트랜잭션이라 부르며 묶어져 있는 것 중간에 문제가 발생하면 모두 롤백시킴으로써 작업의 안정성을 확보한다.
오류가 발생한다면 모든 작업을 리셋하고 초기로 돌아간다.
트랜잭션의 특징.
- 원자성
트랜잭션의 작업은 데이터 베이스에 모두 반영되던가, 전혀 반영되지 않아야 한다.
- 일관성
트랜잭션의 작업 처리 결과는 항상 일관성이 있어야 한다.
- 독립성
둘 이상의 트랜잭션이 동시에 병행 실행되고 있을 때 어느 하나의 트랜잭션이라도 다른 트랜잭션의 연산에 끼어들 수 없다.
- 지속성
트랜잭션이 성공적으로 완료되었을 경우, 결과는 영구적으로 반영되어야 한다.
- 정상적인 트랜잭션의 작업들이 성공했을 때 이를 데이터베이스에 하는 것을 commit이라 한다.
- commit을 수행하면 하나의 트랜잭션 과정을 종료하며, 이전 데이터가 완전히 update된다.
- 트랜잭션 내 작업들이 실패했을 때 원상복구하는 것을 rollBack이라 한다.
- 트랜잭션이 시작되기 이전, 즉 마지막으로 commit을 완료한 지점으로 다시 돌아간다.
- 트랜잭션은 ALL-OR-Nothing(모두 하든지, 아무것도 하지 말든지) 방식이며, 커밋과 롤백에 의해서 안전을 보장받을 수 있다.