JPA와 모던 자바 데이터 저장 기술
SQL 중심적인 개발의 문제점
- 반복적인 CRUD 쿼리 작성
- 객체를 관계형 데이터베이스에 저장한다.
- 개발자가 SQL 매퍼의 역할을 한다.

- 변경에 취약하다.
- 하나의 필드만 추가되더라도 관련된 엔티티의 모든 CRUD 쿼리를 수정해야 한다.
- 패러타임의 불일치, 객체 vs 관계형 데이터베이스
- 객체지향 프로그래밍은 추상화, 캡슐화, 정보은닉, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공한다.
- 객체를 저장하는 영구 보관소 → RDB or NoSQL or File
객체와 관계형 데이터베이스의 차이
- 상속
관계형 데이터 베이스는 객체의 “상속”의 개념이 없다.
대신에, 슈퍼 타입 & 서브 타입 기법으로 상속을 구현할 수 있다. (필요시에 조인해서 가져오는)

자바 컬렉션에 저장한다면?
// 저장
list.add(album);
// 꺼내기
Album album = list.get(albumId);
- 연관관계
객체는 참조로 연관관계를 맺는다.
member.getTeam()
테이블은 외래 키를 사용 JOIN ON M.TEAM_ID = T.TEAM_ID
객체 그래프 탐색
객체는 자유롭게 그래프를 탐색할 수 있어야 한다.
일반적인 쿼리 매퍼 방식으로는 객체 그래프 탐색을 위해서는 엄청난 쿼리가 필요하다
- 데이터 타입
- 데이터 식별 방법
JPA의 등장
객체를 자바 컬렉션에 저장하듯이 DB에 저장할 수 없을까? 의 아이디어로 등장
JPA 소개
Java Persistence API, Java 진영의 ORM 표준
ORM
- 객체 관계 매핑
- 객체는 객체대로 설계
- 관계형 데이터베이스는 관계형 데이터베이스대로 설계
- ORM 프레임워크가 중간에서 매핑하는 역할을 담당 (기존에는 개발자가 담당하였던)
- 대중적인 언어에는 대부분 ORM 기술이 존재한다.
JPA 동작
JPA는 애플리케이션과 JDBC 사이에서 동작한다.

개발자가 직접 JDBC API를 사용했다면, JPA는 개발자 대신 JDBC API를 이용해서 DB와 통신한다.
JPA 동작 - 저장

패러다임의 불일치를 해결해준다.
JDBC 동작 - 조회

Entity Object를 만들어서 반환해준다.
JPA 소개
EJB
- 엔티티 빈 (자바 표준)
- 성능에 비해 너무 복잡해서 사용하는 사람이 적었다.
하이버네이트
- 오픈 소스
JPA
- 자바 표준
- JPA는 표준 명세 = JPA는 인터페이스의 모음이다.
- JPA 2.1 표준 명세를 구현한 3가지의 구현체
- 하이버네이트, EclipseLink, DataNucleus

⭐️⭐️ JPA를 왜 사용해야 하는가?
- SQL 중심적인 개발에서 객체 중심으로 개발
- 높은 생산성 - JPA와 CRUD
- 저장
jpa.persist(member)
- 조회
Member member = jpa.find(memberId)
- 수정
member.setName(”변경할 이름”) // 더티 체킹
- 삭제
jpa.remove(member)
- 유지보수의 용이성
- 기존 : 필드 변경시 모든 SQL을 수정해야 함
INSERT
,UPDATE
,DELETE
- JPA : 필드만 추가하면 된다. → SQL은 JPA가 처리
- 패러다임의 불일치 해결 (⭐️)
- JPA와 상속
- 개발자가 할일
jpa.persist(album);
- 나머진 JPA가 처리
INSERT INTO ITEM~, INSERT INTO ALBUM~
- JPA와 연관관계
- JPA와 객체 그래프 탐색
- JPA와 비교하기
저장
연관관계 저장
member.setTeam(team);
jpa.persist(member);
신뢰할 수 있는 엔티티, 계층 → 자유로운 객체 그래프 탐색 (지연로딩 같은 기술을 이용)
동일한 트랜잭션에서 조회한 엔티티는 같음을 JPA는 보장
- JPA의 성능 최적화 기능
- 1차 캐시와 동일성 (identity) 보장
- 같은 트랜잭션 안에서는 같은 엔티티를 반환 - 약간의 조회성능 향상
- DB Isolation Level이
Read Committed
이어도 애플리케이션에서Repeatable Read
보장 - 트랜잭션을 지원하는 쓰기 지연 (Transactional Write-behind)
- 트랜잭션을 커밋할 때 까지 INSERT SQL을 (버퍼에) 모음
JDBC BATCH SQL
기능을 사용해서 한번에 SQL 전송- 트랜잭션이 커밋되는 순간 데이터 베이스에 INSERT SQL을 모아서 보낸다.
- 장점 - 네트워크 통신 비용이 줄어든다.
UPDATE, DELETE
로 인한 로우(ROW)락 시간 최소화- 트랜잭션 커밋 시
UPDATE, DELETE SQL
실행하고 바로 커밋 - 비지니스 로직 수행 동안 DB 로우 락이 걸리지 않는다.
- 커밋하는 순간 데이터 베이스에 UPDATE, DELETE SQL이 전송된다.
- 지연 로딩 (Lazy Loading)과 즉시 로딩
- 지연 로딩 : 객체가 실제 사용될 때 로딩
- 즉시 로딩 : JOIN SQL로 한번에 연관된 객체까지 미리 조회
- 반드시 사용하는 엔티티라면, 한번에 가져옴으로서 네트워크 비용을 줄일 수 있다.
JPA가 애플리케이션과 데이터베이스 사이에서 존재함으로서 얻는 이점
1. 모아서 한번에 보내기
2. Buffer Writing = 캐싱 기능
DB 격리 수준
REPEATABLE READ (격리수준 높음)
- MVCC(다중 버전 동시성 제어)를 이용해 한 트랜잭션 내에서 동일한 결과를 보장한다.
- MySQL은 트랜잭션 마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것만 읽게 된다.
- Undo 공간에 백업해두고 실제 레코드 값을 변경한다.
- PANTOM READ가 존재할 수 있다. (추가가 발생한 경우)
READ COMMITTED (격리수준 낮음)
- 커밋된 데이터만 조회할 수 있고, 하나의 트랜잭션 안에서 서로 다른 조회 결과가 나올 수 있다.
- 나중에 시작한 트랜잭션에서 먼저 읽은 레코드의 데이터를 변경 후 커밋한 경우
다중 버전 동시성 제어란?
RDBMS는 변경 전의 레코드를 Undo 공간에 백업해둔다. 따라서 동일한 레코드에 대해 변경 여러 버전이 존재하기 때문에 다중 버전 동시성 제어라 부른다.
INSERT
UPDATE
- 데이터 접근 추상화와 벤더 독립성
- 표준
ORM은 객체와 RDB 두 기둥위에 있는 기술
Share article