본문 바로가기
김영한 스프링/김영한 스프링 JPA

영속성 관리

by hoshi03 2023. 11. 7.

• 영속성 컨텍스트 : 엔티티를 영구 저장하는 환경

EntitiyManager.persisrt(entity);

위 코드를 사용하면 영속성 컨텍스트에 저장한다

영속성 컨텍스트에 넣어서 관리가 된 상태가 되야

쿼리문이 작동한다

 

상태 4가지 비영속,영속,준영속,삭제

            // 객체를 생성한 상태, 여기까진 비영속
            Member member = new Member();
            member.setId(100L);
            member.setName("HelloJPA");

            //여기서부터 영속 상태
            em.persist(member);

            //회원 엔티티를 영속성 컨텍스트에서 분리한 준영속 상태
            em.detach(member);

            //객체를 삭제한 상타
            em.remove(member);

 

• 영속성 컨텍스트의 장점

 

 

1차 캐시에서 조회

멤버 객체를 persist로 저장하면

조회할때 db가 아닌 1차 캐시에 조회가 된다

영속성 컨텍스트에 없는 경우에는 db에서 조회한다음 1차 캐시에 저장한후 반환한다

1차캐시는 한 트랜잭션이 끝나면 더 조회가 안된다.. 전체 어플리케이션에서는 2차 캐시를 사용한다

 

try-catch 구문 안에서 이렇게 2번 조회를 하면

첫번째는 영속성 컨텍스트 안에 없어서 db에서 쿼리로 조회하고

두번째는 1차 캐시안에서 조회를 하기에 쿼리문 없이 조회가 된다!

Member findMember1 = em.find(Member.class, 100L);
Member findMember2 = em.find(Member.class, 100L);

 

영속 엔티티의 동일성 보장

 

같은 트랜잭션 안에서 find로 같은 엔티티를  두번 가져오면 동일한 엔티티를 가져온다

Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.println(a == b); //동일성 비교 true

 

jpa를 사용할때 엔티티에 기본 생성자가 있어야된다, 만들어두자

 

엔티티를 등록할때 트랜잭션을 지원하는 쓰기 지연

 

트랜잭션을 시작한 후에

쓰기 지연 sql 저장소에 sql을 저장해뒀다가(여기서는 em.persist~ 쿼리 두개를 저장)

트랜잭션을 커밋한 후에 sql을 db에 보낸다

 

commit 후 insert 쿼리가 두번 실행된다

EntityManager em = emf.createEntityManager(); 
EntityTransaction transaction = em.getTransaction(); 
//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다. 
transaction.begin();  
em.persist(memberA); 
em.persist(memberB);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다. 

//커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit();

 

엔티티 수정 변경감지

 

트랜잭션 안에서 이렇게만 해도 update 쿼리가 나가서 유저 이름이 수정이 된다!

 

이게 되는 이유: 트랜잭션을 커밋하면1차 캐시 안의 스냅샷(최초시점)과 엔티티를 비교해서 변경을 감지해서 반영한다

// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA"); 
// 영속 엔티티 데이터 수정
memberA.setUsername("hi"); 
memberA.setAge(10);

 

엔티티 삭제

 

삭제 대상 엔티티를 찾아서 삭제한다, 이것도 커밋 시점에 쿼리문이 작동한다

Member memberA = em.find(Member.class, “memberA"); 
em.remove(memberA); //엔티티 삭제

 

• 플러시

 

플러시 - 영속성 컨텍스트의 변경내용을 데이터베이스에 반영

트랜잭션 커밋 , jpql 쿼리 실행시 플러시가 자동 발생

em.flush()를 하면 flush가 바로 발생되서 커밋 전에도 db에 반영된다

플러시를 하면 쓰기 지연 sql 저장소의 쿼리들이 db에 반영 된다, 1차 캐시가 다 날아가지는 않는다

 

플러시 요약

 

영속성 컨텍스트를 비우지 않음
영속성 컨텍스트의 변경내용을 데이터베이스에 동기화
트랜잭션이라는 작업 단위가 중요 -> 커밋 직전에만 동기화 하면 됨

 

• 준영속 상태

 영속성 컨텍스트에서 분리가 된 상태

 

준영속 상태로 만드는 방법

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

 

find나 set 등으로 가져온게 준영속 상태가 되면 당연히 아무일도 일어나지 않는다 

 

 

 

정리

영속성 컨텍스트, jpa 매핑 과정, 엔티티 생명주기, 영속성 컨텍스트 이점, 플러시

위의 각 키워드를 자세히 설명 가능하게 복습하자

'김영한 스프링 > 김영한 스프링 JPA' 카테고리의 다른 글

JPA 어플리케이션 개발  (0) 2023.10.29
JPA 프로젝트 생성  (0) 2023.10.29