JPA
- Java Persistence API : 자바 ORM 기술에 대한 표준 API.
ORM?
> Object Relation Mapping의 약자
> 자바 객체와 관계형 데이터베이스 테이블 간에 매핑해주는 기술.
- 대표 구현체 : Hibernate(하이버네이트), EclipseLink ...
🌕사용 배경
- 개발자가 SQL을 매핑하는 역할을 반복하며, 직접 쿼리문을 작성하게 되므로 오타로 인한 오류 발생 확률이 높아지게 된다.
- 자바 객체와 관계형 데이터베이스 간의 패러다임 불일치.
🌖장점
- 특정 데이터베이스에 종속되지 않음.
- 관계형 데이터베이스 설계 중심의 패러다임에서 객체 지향 프로그래밍이 가능.
- 생산성 향상
🌗동작 방식
- 엔티티(Entity) : 관계형 데이터베이스 테이블에 대응하는 클래스 또는 생성된 객체. @Entity가 붙은 클래스를 엔티티라고 한다.
- 엔티티 매니저 : 영속성 컨텍스트에 접근하여 엔티티에 대한 데이터 베이스 작업을 제공. 내부적으로 데이터 베이스 커넥션을 사용해서 데이터베이스에 접근한다.
- 엔티티 매니저 팩토리 : 엔티티 매니저 객체 관리, 애플리케이션 실행 시 하나만 생성되며 사용자로부터 요청이 오면 매니저를 생성함.
EntityManager
- find() : 영속성 컨텍스트 내에서 엔티티를 검색.
- 해당 엔티티가 영속성 컨텍스트에 없는 경우, DB에서 데이터를 찾아 영속성 컨텍스트에 저장 후 반환.
- 있는 경우, 해당 엔티티를 반환.
- 내부적으로 flush()가 수행되므로 별도로 flush()를 호출할 필요가 없다.
- persist() : 엔티티를 영속성 컨텍스트에 저장.
- remove() : 엔티티를 영속성 컨텍스트에서 삭제.
- flush() : 영속성 컨텍스트에 저장된 내용을 DB에 반영.
- detach() : 영속성 컨텍스트에 저장된 엔티티를 준영속 영역으로 분리함.
- merge() : 준영속 영역에 있는 엔티티를 다시 영속성 컨텍스트로 불러드림.
🌘Persistence Context
영속성 컨텍스트란?
- 엔티티를 영구 저장 및 관리하는 환경으로 엔티티 매니저를 통해 영속성 컨텍스트에 접근이 가능하다.
- 내부적으로 영속성 컨텍스트 내부에서 관리하는 엔티티의 변화를 감지하여 트랜잭션 커밋 시 이를 DB에 반영한다.
엔티티의 생명주기
- 생명 주기
- 비영속(New) : 생성된 상태로 영속성 컨텍스트와 무관한 상태.
- 영속(Managed) : 영속성 컨텍스트에 저장 및 관리되는 상태.
- 영속 상태에서는 DB에 반영되지 않으며, 트랜잭션 커밋시점에 반영됨.
- 준영속(Detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태.
- 삭제(Removed) : 영속성 컨텍스트와 DB에서 삭제된 상태.
장점
- 데이터 베이스와 자바 애플리케이션 간의 중간계층을 만들어 캐싱, 버퍼링 등이 가능하여 엔티티 조회 시 동일한 엔티티의 조회를 보장.
- 트랜잭션 단위로 관리 가능.
- 변화 감지.
1차 캐시
- 영속성 컨텍스트에는 1차 캐시가 존재하며,MAP<KEY,VALUE>로 저장됨.
- EntityManager.find() 호출 시 1차 캐시에서 엔티티 조회 후 없으면 DB에서 조회 및 1차 캐시에 저장 및 반환함.
- 하나의 트랜잭션에서 같은 키값으로 영속성 컨텍스트에 저장된 엔티티 조회 시 같은 엔티티의 조회를 보장한다.(동일성 보장)
쓰기 지연 SQL 저장소
- EntityManager.persist() 호출 시 DB에 전송할 SQL문을 저장소에 저장.
- 저장소에 저장된 SQL문은 트랜잭션 커밋 시점에 flush()되어 데이터베이스에 반영된다.
변화 감지
- 영속성 컨텍스트에는 DB에서 처음 불러온 엔티티의 스냅샷을 1차 캐시에 저장하고 있다.
- 1차 캐시에 저장된 엔티티와 스냅샷을 비교 후 변경 내용이 있으면, UPDATE 쿼리를 쓰기 지연 SQL 저장소에 추가한다.
- 데이터베이스 커밋 시점에 변경 내용이 자동으로 반영된다.
🌚JPA 사용 설정
- application.properties 설정
# MySql 연결 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db명
spring.datasource.username=계정
spring.datasource.password=비밀번호
# 실행되는 쿼리 콘솔 출력
spring.jpa.properties.hibernate.show_sql=true
# 콘솔 창에 출력되는 쿼리를 가독성 좋게 포맷팅
spring.jpa.properties.hibernate.format_sql=true
# 쿼리에 물음표로 출력되는 바인드 파라미터 출력
logging.level.org.hibernate.type.descriptor.sql=trace
spring.jpa.hibernate.ddl-auto=create
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
데이터베이스 초기화 전략 : DDL AUTO 옵션
- spring.jpa.hibernate.ddl-auto 옵션을 통해 자바 애플리케이션 프로그램 실행 시 JPA의 데이터베이스 초기화 전략 설정가능.
- 옵션 5가지
- create : 실행 시 기존 DB 테이블 삭제 후 재생성
- update : 실행 시 테이블 삭제하지 않고 변경 사항만 반영
- validate : 실행 시 엔티티와 테이블간의 변화 감지 시 에러발생.
- none : 초기화 시 아무것도 안함.
- 개발 초기에 create 또는 update 옵션을 이용하고, 추후 none으로 옵션을 설정해주는 것이 일반적이다.
- 운영환경에서는 절대로 create, update를 사용해서는 안된다. 실제 서비스 시 서버에서는 테이블 생성 및 컬럼 추가, 삭제, 변경은 데이터베이스에서 직접하며, none을 사용하거나 validate를 이용하여 정상적인 매핑 관계 확인만 한다.(서비스는 끊김없이 계속 제공되어야 하므로)