본 프로젝트 자료는 김영한님의 스프링 DB 1편 - 데이터 접근 핵심 원리을 참고 제작됐음을 알립니다.
데이터를 담기 위해 만들어진 데이터베이스라 보면 된다.
동작원리
전 DB 와 다른 동작 방식인걸 확인 할 수 있다. 여기서 DB 는 위 2개 말고 더 많은 관계형 데이터베이스가 있다.
이러면 문제점들이 생각보다 일에 대한 효율이 좋지 않아, 여기서 등장한 것이 JDBC 라는 자바 표준이다.
JDBC 표준 인터페이스
이 자바 표준이 어떻게 개발자에게 편리한 기능을 제공하는지 확인해보자.
대표적으로 다음 3가지 기능을 표준 인터페이스로 정의해서 제공해준다.
그렇다고 이 3가지로 DB 가 동작하는게 아니다. 말 그대로 DB 를 좀 더 편리하게 연결 할 수 있게 만들어 주는 기능들이지 핵심인 DB 가 없다.
이 DB 들은 각 DB 벤더에서 라이브러리 형태로 제공이 되는데(JDBC 드라이버) 위 3가지 기능과 드라이버를 사용해 편리하게 DB 를 설계하면 된다.
MySQL 드라이버 사용
Oracle 드라이버 사용
요론 식으로 동작한다. 표준이 등장하면서 편리해진게 눈에 보인다.
정리
JDBC는 1997년에 출시될 정도로 오래된 기술이다 보니 다양한 응용 기술이 존재하는데, 그 중 대표적인게 SQL Mapper 와 ORM 기술이다.
이렇게 진행했을 때의 장점
하지만 개발자가 직접 SQL 문을 작성해야 하는 점이 존재한다.
SQL Mapper 의 대표 기술 : JdbcTemplate, MyBatis
이제 ORM 기술에 대해 알아보도록 하자.
ORM 은 객체를 관계형 데이터베이스 테이블과 매핑해주는 기술을 가지고 있다보니, 개발자들이 직접 SQL 을 작성하지 않고 ORM 기술이 개발자 대신 SQL을 동적으로 만들어 준다.
ORM 기술 의 대표 기술 : JPA, 하이버네이트, 이클립스링크
이 두 기술의 각 장단점을 알아보도록 하자.
SQL Mapper 은 직접 SQL문만 작성하면 나머지 번거로운 일은 SQL Mapper 가 대신 처리해준다. 난이도가 비교적 쉽다.
ORM 기술은 SQL 을 작성하지 않아도 되어서 비교적 쉬워보이지만, 난이도가 있어 사용할꺼면 깊이 있게 배워야 한다.
이제 H2 데이터베이스를 먼저 실행하고 애플리케이션과 연결해보자.
ConnectionConst - 생성
데이터베이스에 접속 할 수 있게 기본 정보를 입력.
DBConnectionUtil - 생성
일단 데이터베이스에 연결하려면 DriverManager.getConnection(..) 사용해야 한다.
이제 학습용 테스트 코드를 작성해서 제대로 연결이 됐는지 확인해보자.
DBConnectionUtilTest - 테스트 코드 생성
H2 데이터베이스가 실행된 상태여야 실행하는제 에러코드가 발생하지 않는다.
결과 로그
내용 중에 class=class org.h2.jdbc.JdbcConnection 를 확인 할 수 있는데, 이 부분이 H2 데이터베이스 전용 커넥션이다.
이 커넥션도 JDBC 표준 커넥션에 구현되어 있다.
지금 실행하면서 어떻게 동작이 되는지 그 원리를 파악해 보자.
가운데 있는 DriverManager 가 라이브러리 에 등록된 DB 드라이버를 관리하고, 커넥션을 획득하는데 도움을 준다.
JDBC 를 사용해서 애플리케이션을 개발해보자.
여기서는 JDBC 를 사용해서 회원(Member) 데이터를 데이터베이스에 관리하는 기능을 개발해보자.
H2 데이터베이스는 항상 실행시켜야 한다! 그리고 Member 를 테스트 하는거니 테이블도 생성해야 한다!
H2 데이터베이스
Member - 생성
테이블과 일치하게 회원의 ID와 해당 회원이 소지한 금액을 표현했다.
MemberRepositoryV0 - 생성
회원 등록해보자.
쿼리를 실행하고 나면 리소스를 정리해야 한다. 여기서는 Connection , PreparedStatement 를 사용했다.
1. 생성할 때는 Connection 을 먼저 획득하고 Connection 을 통해 PreparedStatement 생성.
2. 반환할 때는 PreparedStatement 를 먼저 종료하고, 그 다음에 Connection 을 종료.
주의
리소스 정리는 꼭! 해주어야 한다. 따라서 예외가 발생하든, 하지 않든 항상 수행되어야 하므로 finally
구문에 주의해서 작성해야한다. 만약 이 부분을 놓치게 되면 커넥션이 끊어지지 않고 계속 유지되는 문제가 발생할 수 있다. 이런 것을 리소스 누수라고 하는데, 결과적으로 커넥션 부족으로 장애가 발생할 수 있다.
이제 테스트 코드로 JDBC 회원 등록이 되는지 테스트 해보자.
MemberRepositoryV0Test - 테스트 생성
memberV0 등록
memberV1 등록
성공적으로 등록된걸 확인 할 수 있다.
JDBC 조회하는 기능을 개발해보자.
MemberRepositoryV0 - 추가
회원 조회 추가
findById() 에서는 회원 하나를 조회하는 것이 목적이기에 while 대신 if 를 사용한다.
MemberRepositoryV0Test - 추가 및 실행
회원 조회 추가 및 실행 결과 확인
회원을 등록하고 그 결과를 바로 조회할 수 있다.
참고로 실행 결과에 member 객체의 참조 값이 아니라 실제 데이터가 보이는 이유는 롬복의 @Data 가 toString() 을 적절히 오버라이딩 해서 보여주기 때문이다.
MemberRepositoryV0 - 추가
회원 수정 추가
executeUpdate() 는 쿼리를 실행하고 영향받은 row수를 반환한다. 여기서는 하나의 데이터만 변경하기 때문에 결과로 1이 반환된다. 만약 회원이 100명이고, 모든 회원의 데이터를 한번에 수정하는 update sql 을 실행하면 결과는 100이 된다.
MemberRepositoryV0Test - 추가
회원 수정 추가
이제 회원 데이터가 10000 -> 20000으로 수정됐는지 확인해보자.
실행했을 때 정상적으로 10000 에서 20000으로 수정된 것을 확인 할 수 있다.
다음은 회원 삭제를 해보자.
MemberRepositoryV0 - 추가
회원 삭제 추가
쿼리만 바뀌고 나머지는 별 차이 없다.
MemberRepositoryV0Test - 추가
회원 삭제 추가
회원을 삭제한 다음 findById() 를 통해서 조회한다. 회원이 없기 때문에 NoSuchElementException 이 발생한다. assertThatThrownBy 는 해당 예외가 발생해야 검증에 성공한다.