[Spring/JPA] 영속성 컨텍스트

2025. 4. 11. 13:45·Spring

✅ 영속성 컨텍스트

♐ 영속성 컨텍스트란?

  • Entity 객체를 영속성 상태로 관리하는 일종의 캐시 역할을 하는 공간으로 여기에 저장된 Entity는 데이터베이스와 자동으로 동기화되며 같은 트랜잭션 내에서는 동일한 객체가 유지된다. 

 

♐ 작동 원리

  1. 눈에 보이지 않는 공간이 생긴다(논리적 개념)
  2. Entity Manager 를 통해서 영속성 컨텍스트에 접근한다. ex) EntityManager.persist(entity)
  3. Entity를 영속성 컨텍스트에 저장한다.

 

✅ Entity 

♐ Entity란?

  • 데이터베이스에서 Entity란 저장할 수 있는 데이터의 집합을 의미한다.
  • JPA 에선 테이블을 나타내는 클래스이다.

 

♐ 생명 주기

 

1. 비영속 (New/Transient): 

 -  영속성 컨텍스트와 전혀 관계가 없는 상태
 -  객체가 처음 생성된 상태로, 데이터베이스와 연결되지 않다.
 -  이 상태에서 persist() 메서드를 호출하면 객체가 관리되는 상태로 전환된다.

// 객체를 생성하고 영속성 컨텍스트에 저장하지 않은 상태
User user = new Tutor(1L, "user1", 100);

 

2. 영속 (Managed):
 -  객체가 데이터베이스와 연결된 상태로, 변경사항이 자동으로 데이터베이스에 반영된다.
 -  예를 들어, 사용자의 정보를 수정하면 그 변경이 즉시 데이터베이스에 저장된다.
 -  remove() 메서드를 호출하면 객체가 삭제 상태로 전환된다. 이때 객체는 여전히 메모리에 존재하지만, 데이터베이스에    서 삭제되도록 예약된다.

    // EntityManagerFactory 생성
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
    // EntityManager 생성
    EntityManager em = emf.createEntityManager();
    // Transaction 생성
    EntityTransaction transaction = em.getTransaction();

    // 트랜잭션 시작
    transaction.begin();

    em.persist(user);

  • persist 후 출력 이후에 SQL이 실행된다.

 

3. 삭제 (Removed):
 -  객체가 영속 상태에서 삭제된 상태로, 데이터베이스에서 실제로 삭제되기 전이다.
 -  이 상태에서 flush() 메서드를 호출하면 데이터베이스에서 객체가 완전히 삭제된다.

// 객체를 삭제한 상태
em.remove(user);

 

4. 준영속 (Detached):
 -  객체가 영속 상태에서 분리된 상태로, 데이터베이스와의 연결이 끊어진 상태이다.
 -  세션이 종료되거나 명시적으로 detach() 메서드를 호출하여 객체가 관리되지 않게 된다.

 -  영속성 컨텍스트가 제공하는 기능을 사용하지 못한다.
 -  이 객체는 여전히 메모리에 존재하지만, 데이터베이스의 변경사항과 동기화되지 않는다. merge() 메서드를 통해 다시 관리 상태로 전환할 수 있다.

  • 준영속 상태로 만드는 방법
        1. em.detach()
            - 특정 Entity만 준영속 상태로 변경한다.
        2. em.clear()
            - 영속성 컨텍스트를 초기화 한다.
        3. em.close()
            - 영속성 컨텍스트를 종료한다.

 

5. DB:
 -  데이터베이스 자체를 나타낸다. find() 메서드를 통해 데이터베이스에서 객체를 검색할 수 있고, flush() 메서드를 통해 변경사항을 반영한다.

 

 

✅ 1차 캐시

♐ 1차 캐시란?

  • 엔티티를 영속성 컨텍스트에 저장할 때 생성되는 메모리 내 캐시이다. 엔티티는 먼저 1차 캐시에 저장되고 이후 같은 엔티티를 요청하면 DB를 조회하지 않고 1차 캐시에서 데이터를 반환하여 성능을 높일 수 있다.

  • 1차 캐시 코드예시
public static void main(String[] args) {
    // EntityManagerFactory 생성
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
    // EntityManager 생성
    EntityManager em = emf.createEntityManager();
    // Transaction 생성
    EntityTransaction transaction = em.getTransaction();

    // 트랜잭션 시작
    transaction.begin();

    try {
        // 비영속
        Tutor tutor = new Tutor(1L, "wonuk", 100);

        // 영속
        System.out.println("persist 전");
        em.persist(tutor);
        System.out.println("persist 후");

        Tutor findTutor = em.find(Tutor.class, 1L);

        System.out.println("findTutor.getId() = " + findTutor.getId());
        System.out.println("findTutor.getName() = " + findTutor.getName());
        System.out.println("findTutor.getAge() = " + findTutor.getAge());

        // transaction이 commit되며 실제 SQL이 실행된다.
        transaction.commit();
    } catch (Exception e) {
        // 실패 -> 롤백
        e.printStackTrace();
        transaction.rollback();
    } finally {
        // 엔티티 매니저 연결 종료
        em.close();
    }
    emf.close();
}

  • 조회 SQL이 실행되지 않는다

 

✅ 동일성 보장

  • 동일한 트랜잭션 안에서 특정 엔티티를 여러 번 조회해도 항상 같은 객체 인스턴스를 반환한다. 
  • 영속성 컨텍스트는 1차 캐시를 사용하여 같은 엔티티를 중복 조회해도 동일한 객체를 참조하게 하여 일관성을 유지한다.

  1.  동일한 트랜잭션 내에서 조회된 Entity는 같은 인스턴스를 반환한다.
  2.  DB에 저장된 데이터를 조회하여 1차 캐시에 저장한다.
  3.  1차 캐시에 저장된 데이터를 조회한다.

 

✅ 쓰기 지연

  • 엔티티 객체의 변경 사항을 DB에 바로 반영하지 않고 트랜잭션이 커밋될 때 한 번에 반영하는 방식으로 이를 통해 성능을 최적화하고 트랜잭션 내에서의 불필요한 DB 쓰기 작업을 최소화한다.

 

♐ 그림으로 이해하기

 

1. `tutor1` 1차 캐시에 저장 

2. 쓰기 지연 저장소에 `tutor1 INSERT SQL` 저장

 

3. `tutor2` 1차 캐시에 저장
4. 쓰기 지연 저장소에 `tutor2 INSERT SQL` 저장

 

 

1. `flush` 되면서 SQL 쿼리 실행
2. 트랜잭션이 `Commit` 되면서 실제 DB에 반영

 

✅ 변경 감지

  • 영속성 컨텍스트가 엔티티의 초기 상태를 저장하고 트랜잭션 커밋 시점에 현재 상태와 비교해 변경 사항이 있는지 확인하는 기능이다.

♐ 그림으로 이해하기

 

1. Entity 가 1차캐시에 저장되면 Snapshot 에도 저장한다.

2.다음 트렌젝션이 들어와 Snapshot 과 값을 비교하여 다르면 자동으로 UPDATE SQL을 생성한다.

'Spring' 카테고리의 다른 글

[Spring]HttpMessageConverter  (0) 2025.04.16
[SPRING/JPA]양방향 관계시 사용하는 CASCADE에 대해 알아보자  (1) 2025.04.11
[Spring] Annotation  (2) 2025.04.10
[Spring] Controller 와 RestContoller 의 차이  (0) 2025.04.10
[Spring] MVC 패턴  (0) 2025.04.07
'Spring' 카테고리의 다른 글
  • [Spring]HttpMessageConverter
  • [SPRING/JPA]양방향 관계시 사용하는 CASCADE에 대해 알아보자
  • [Spring] Annotation
  • [Spring] Controller 와 RestContoller 의 차이
코딩로봇
코딩로봇
금융 IT 개발자
  • 코딩로봇
    쟈니의 일지
    코딩로봇
  • 전체
    오늘
    어제
    • 분류 전체보기 (149) N
      • JavaScript (8)
      • SQL (11)
      • 코딩테스트 (30)
        • Java (15)
        • SQL (13)
      • Java (10)
      • 프로젝트 (29) N
        • 트러블슈팅 (10) N
        • 프로젝트 회고 (17) N
      • git,Github (2)
      • TIL (38)
      • Spring (19) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    java #arraylist #list #배열
    스파르타 코딩 #부트캠프 #첫ot
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코딩로봇
[Spring/JPA] 영속성 컨텍스트
상단으로

티스토리툴바