코딩공작소

JPA 프로그래밍 학습 정리 (1) - JPA소개 및 영속성관리 본문

어플리케이션개발/JPA

JPA 프로그래밍 학습 정리 (1) - JPA소개 및 영속성관리

안잡아모찌 2024. 1. 6. 15:53
JPA사용법과 엔티티 매니저

JPA는 persistence.xml 파일을 통해 필요한 설정 정보를 관리한다.

<persistence-unit name="jpabook">

...

 

JPA에서는 객체지향적인 개발을 할 수 있도록 도와준다. 그래서 각 객체를 엔티티로 매핑하여 사용한다.

 

JPA를 사용하기 위해서는 먼저 앞서 말한 persistence.xml를 통해 설정 값을 세팅해줘야한다.

그후, 설정정보를 사용해 엔티티 매니저 팩토리라는 공장을 만들어야 한다. 이 공장은 비용이 많이 발생하는 작업이기 때문에 애플리케이션 전체에 딱 한번만 생성하고 공유해서 사용해야 한다.

엔티티 매니저 팩토리라는 공장을 만들면, 그 공장에서는 여러 개의 엔티티 매니저들을 만들 수 있다. 우리는 이 엔티티 매니저를 통해 CRUD를 사용할 수 있으며, 엔티티 매니저를 가상의 데이터 베이스라고 생각하면 된다.

그리고 이 엔티티 매니저는 데이터베이스 커넥션과 밀접관 관련이 있으므로 스레드간 공유 혹은 재사용을 해서는 절대 안된다.

사용이 끝난 엔티티 매니저는 반드시 종료해야한다. 그리고 애플리케이션을 종료할 때 엔티티 매니저 팩토리도 종료해야한다.

JPA는 항상 트랜잭션 안에서 데이터를 변경해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package jpabook.start;
 
import javax.persistence.*;
import java.util.List;
 
public class JpaMain {
    public static void main(String[] args){
    
        //[엔티티 매니저 팩토리] -- 생성
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
 
        //[엔티티 매니저] -- 생성
        EntutyManager em = emf.createEntityManager();
 
        //[트랜잭션] - 획득
        EntityTransaction tx = em.getTransaction();
 
        try{
            tx.begin(); //[트랜잭션] -- 시작
            logic(em); //비지니스 로직 실행
            tx.commit(); //[트랜잭션] -- 커밋
        }catch(Exception e){
            tx.rollback(); //[트랜잭션] -- 롤백
        }finally{
            em.close(); //[엔티티 매니저] -- 종료
        }
        emf.close(); //[엔티티 매니저 팩토리] -- 종료
        }
        
        public static void logic(EntityManager em){
            ...
        }
}
cs

 

엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전하므로 서로 다른 스레드간 공유가 가능하지만 엔티티 매니저는 동시에 접근하면 동시성 문제가 발생하므로 스레드 간에 절대 공유하면 안된다. 엔티티 매니저와 DB간의 커넥션풀은 보통 트랜잭션을 시작할 때 획득한다.

 

 

JPQL

CRUD를 편하게 할 수 있도록 지원하며, JPQL(Java Persistence Query Language)라는 쿼리를 지원한다. SQL문법과 거의 유사하게 사용되만 엔티티 객체를 대상으로 쿼리한다. 즉 From 뒤에 나오는 것은 테이블이 아니라 객체다. JPQL은 DB를 전혀 알지못한다.

SELECT M.ID, M.NAME, M.AGE FROM MEMBER M

 

영속성 관리

영속성 컨텍스트란 엔티티를 영구 저장하는 환경이다. 엔티티 매니저를 사용해서 회원 엔티티를 영속성 컨텍스트에 저장한다.

이러한 엔티티에는 4가지 상태가 존재한다.

  • 비영속(new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 상태
  • 영속(manager) : 영속성 컨텍스트에 저장된 상태
  • 준영속(detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 삭제(removed) : 삭제된 상태

영속 상태는 식별자 값이 반드시 있어야한다.

보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영하는 데 이것을 플러시(Flush)라고 한다.

플러시는 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영한다. 그리고 플러시가 일어나는 방법은 3가지이다.

  1. em.flush() 직접호출
  2. 트랜잭션 커밋 시
  3. JPQL 쿼리 실행 시

영속성 컨텍스트는 다음과 같은 이점을 가지고 있다.

  • 1차 캐시
  • 동일성보장
  • 트랜잭션을 지원하는 쓰기 지연
  • 변경 감지
  • 지연 로딩

이러한 요소들은 영속 상태의 엔티티에만 적용된다. 그리고 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장하는 데 그것을 스냅샷이라 부르고 트랜잭션 시점에 스냅샷과 현재의 엔티티를 비교해 변경이 되었다면 변경감지가 일어난다.