티스토리 뷰

반응형

JPA는 기본적으로 영속성 컨텍스트에 의해서 관리된다.

영속성 컨텍스트에 대해 자세하게 설명하기 전에 내가 느낀 영속성 컨텍스트는

DB로 저장하기 전, 중간 다리 같은 느낌을 많이 받았다.

 

영속성 컨텍스를 접근하기 위해서는 EntityManager를 통해서 접근하게 된다.

EntityManager는 DB에 요청이 있을때마다 EntityManagerFactory에서 생생해주게 된다.

EntityManagerFactory는 이름에서 느껴지듯 EntityManager를 만들어주는 용도의 객체이다.

 

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();

 

다음과 같이 EntityManager를 생성을 하고 이 EntityManager를 통해서 영속성 컨텍스트에 접근을 할 수 있다.

영속성 컨텍스트는 크게 4가지 경우가 있다.

  1. 비영속 상태
  2. 영속 상태
  3. 준영속 상태
  4. 삭제

여기서 비영속 상태란 entity객체를 생성하고 준비만 해둔 상태이다.

Member member = new Member();
member.setId(100L);
member.setUsername("HelloJPA");

[참고] Member.java

package hellojpa;

import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;


@Entity @Data
public class Member {
    @Id
    @Column(name = "MEMBER_ID")
    private Long id;

    private String username;
    private Integer age;

    @Enumerated(EnumType.STRING)
    private RoleType roleType;
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdDate;

    @Temporal(TemporalType.TIMESTAMP)
    private Date lastModifiedDate;

    @Lob
    private String description;
}

 

다음처럼 말 그대로 객체를 생성만 한 상태이고 DB와는 아무런 접점이 생기지 않은 상태이다.

 

다음으로 영속상태는 EntityManager를 통해서 생성한 객체를 관리가 되는 객체로 만드는 과정이다.

em.persist(member);

 

해당 소스코드로는 아직 DB에 쿼리가 날아간 상태는 아니다. 

이후에 트랜잭션을 commit하는 순간 쿼리가 날아간다. 그 전에는 쓰기 지연 SQL 저장소에 저장해두기만 한다.

이러한 이유는 batch로 한꺼번에 쿼리를 날려 속도에서 이점을 볼 수 있기 때문이다.

 

비영속 상태와 삭제는 다음과 같이 할 수 있다.

// 영속성 컨텍스트에서 관리하지 않는 상태로 만든다.
em.detach(member);
// DB에서 지우는 요청
em.remove(member);

 

이후, 저장한 객체를 찾게 되면 영속성 컨텍스트의 1차 캐시에서 찾아오게 된다.

한마디로 1차 캐시에 먼저 저장을 하고 조회 또한 1차 캐시에서 하게 된다.

만약 1차 캐시에 원하는 정보가 없다면 그때서야 DB에 커넥션을 맺어서 조회한 뒤 그것을 1차 캐시에 저장하게 된다.

EntityManager는 트랜잭션 단위에서만 존재하고 소멸하기 때문에 큰 효과를 볼 수 있다.
Member a = em.find(Member.class, 100L);
Member b = em.find(Member.class, 100L);

 

여기서 신기한점은 위와 같이 다른 객체를 통해 담았더라도 동일성을 보장해준다.(같은 객체가 된다.)

그 것이 되는 것도 1차 캐시에 저장을 했기 때문이다.

System.out.println("result: " + (a == b));
// >> true

 

영속성 컨택스트의 또 이점으로는 변경감지에 있다.

따로 update에 대한 쿼리 소스 코드를 적어 놓지 않아도 영속성 컨텍스트가 변경감지를 해서 알아서 반영시켜 준다.

b.setUsername("JPAHello");

다음과 같이 그냥 객체 자체에서 바꿔주기만 하면 알아서 변경되어 있다는 점이 JPA의 편리한 점이다.

 

flush를 호출하게 되면 중간에 한번 DB에 쿼리를 직접 날릴수 있다.

하지만, 1차 캐시는 유지되어 있다. 쓰기 지연 SQL 저장소가 DB에 반영되는 과정인 것이다.

JPQL 실행시에는 SQL로 번역하는과정이 있어 사용 전 flush를 날리게 된다.
Member member2 = new Member(200L, "member2");
em.persist(member2);
em.flush();

 

마지막으로 트랙잭션 commit을 하게 되면 쓰기 지연 SQL이 모두 반영되고 끝이나게 된다.

tx.commit();

 

영속성 컨텍스트에서 관리하고 싶지 않으면, 준영속 상태를 만들어주는 detach를 해주면 된다.

em.detach(member2);

 

출처 

인프런 자바 ORM 표준 JPA 프로그래밍 - 기본편

728x90
반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
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
글 보관함
250x250