JPA에서 가장중요한건 2가지

- 객체와 관계형 DB 매핑

- 영속성 컨텍스트(JPA 내부동작이 영속성 컨텍스트와 연관되있다.)

 

 

 

영속성 컨텍스트란?

- 논리적인 개념으로 눈에 보이지않는다. 

- Enitity를 영구 저장하는 환경.

- em.persist(entity);    DB에 저장한다보단 영속성 컨텍스트라는곳에 저장한다.

 

- Entity Manager를 통해 영속성 컨텍스트에 접근한다.

 

엔티티의 생명주기

- 비영속(new): 영속성 컨텍스트와 전혀상관없는 새로운 상태

// 객체만 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");

- 영속: 영속성 컨텍스트에 관리되는 상태

 

EntityManager em = emf.createEntityManger();
Transaction tx = em.getTransaction()
tx.begin();
// 객체를 저장한 상태(영속)
em.persist(member)

 

- 준영속: 영속성 컨텍스트에 저장되었다가 분리된 상태

em.detach(member)

- 삭제 : 삭제된 상태 

em.remove(member);

 

영속성 컨텍스트의 이점

1. 1차캐시(엔티티 조회)

em.persist(member)를 하게되면 

영속성 컥텐스트 내부에 1차 캐시가 존재하는데. 1차 캐시에 id-entity가 key-value 형태로 저장한다.

 

이떄 

Member findMember = em.find(Member.class, "member1");를 하면 1차 캐시에서 조회가 이루어진다. 

1차 캐시에서 조회한 경우

그런데 여기서 member1대신에 member2를 조회하면 1차 캐시에 없으므로 DB에서 조회한다.

Member findMember = em.find(Member.class, "member2"); 

 

DB 트랜잭션이 끝나면 영속성 컨텍스트를 제거한다.(즉, 1차 캐시도 지워진다.)

애플리케이션 전체에서 공유하는것은 2차 캐시

하나의 트랜잭션 안에서의 공유는 1차 캐시

 

2.영속 엔티티의 동일성 보장

Member a = em.find(Member.class, "member1")
Member b= em.find(Member.class, "member2")

a==b // 동일성 비교 true

 

같은 트랙잭션안에서 1차 캐시로 인해 동일성 보장.

 

3. 트랜잭션을 지원하는 쓰기 지원

 

transaction.begin(); 
em.persist(memberA);
em.persist(memberB); 
//여기까지 insert sql을 db에 보내지않음.

transaction.commit() // 커밋하는순간 DB에 insert sql을 보낸다.

 

쓰기지연 SQL 저장소란게 존재하는데

persist(memberA) 를 하면 1차캐시에 저장되는것과 동시에 insert SQl를 생성하고 

쓰기지원 SQL 저장소에 저장한다. 

 

이를 transaction.commit()을 하게되면 쓰기지연 sql 저장소에 있는것들이 flush가 된다.

 

persist할떄 바로 쿼리를 안날리므로 버퍼링같은 기능(모았다가 한번에 보내는기능)을 줄수있다.

batch_size를 두어서 한번에 쿼리문을 보낼수있다.(성능상 이점이있다.)

 

 

4. 변경 감지(엔티티 수정)

Member memberA = em.find(Member.class, "memberA");
memberA.setUsername("hi");

// em.update(member)같은 이런코드가 있어야하지않나?

 

최초의 상태를 스냅샷으로 찍어둔다.

transaction.commit() 하게되면 내부적으로 flush가 된다.

그다음 엔티티 와 스냅샷 비교한다. 

그떄 다른게잇으면 Update Sql를 생성하고 Db에 flush가 된다.

 

엔티티 삭제는 호출시점에 삭제됨.

em.remove(MemberA)

 

 

5. 지연로딩

 

 

플러시란?

정의: 영속성 컨텍스트의 변경내용을 DB에 반영(영속성 컨텍스트의 변경내용을 DB에 동기화)

플러시 발생

변경 감지  -> 수정된 엔티티를 쓰기지연 SQL 저장소에 등록 ->  쓰기지연 SQL 저장소의 쿼리를 DB에 전송

 

영속성 컨텍스트를 플러시하는방법

- em.flush() - 직접 호출

이렇게 직접 호출하면 즉시 쿼리가 날라가서 DB에 반영

 

- 트랜잭션커밋 - 플러시 자동 호출

트랜잭션이라는 작업 단위가 중요해서 커밋직전에 flush 가되게 만들어져있음.

 

- JPQL쿼리 실행시 - 플러시 자동호출

em.persist(memberA);
em.persist(memberB);
// 이떄 쿼리가 안날라가

// JPQL 실행 : 이떄 자동으로 플러시가 된다. (조회를 해야하는데 DB에 반영내용 적용하려고)
query = em.createQuery("select m from Member m", Member.class); 
List<Member> members = query.getResultList();

 

 

준영속상태

 

em.detach(member) // 특정 엔티티만 준영속 상태로 전환
em.clear() // 영속성 컨텍스트를 완전히 초기화
em.close() // 영속성 컨텍스트 종료

 

 

 
 

'𝗦𝗣𝗥𝗜𝗡𝗚 > 𝐎𝗥𝗠-𝗝𝗣𝐀' 카테고리의 다른 글

고급 매핑  (1) 2024.01.03
다양한 연관관계 매핑  (0) 2024.01.03
연관관계 매핑 기초  (0) 2024.01.03
엔티티 매핑  (0) 2024.01.02
JPA 구동방식  (0) 2023.12.27