영속성 관리 - 내부 동작 방식

최주영·2024년 12월 10일
0

JPA

목록 보기
2/5

영속성 컨텍스트 : 자바에 등록된 엔티티를 영구 저장하는 환경

  • 엔티티매니저 팩토리 는 하나만 생성해서 애플리케이션 전체에서 공유
  • 고객의 요청이 들어올때마다 엔티티매니저를 생성함
  • 엔티티매니저 를 생성시 한개의 영속성 컨텍스트 가 생성 ( 1 : 1 )
  • 엔티티매니저영속성 컨텍스트 를 사용 (저장,조회,수정,삭제)
  • 엔티티매니저 는 쓰레드 간에 공유하지 않음 (사용하고 버려야함)
  • JPA의 모든 데이터 변경은 트랜잭션 안에서 실행해야함
    EntityManager em = EntityManagerFactory.createEntityManager();

영속성 컨텍스트 장점

  • 1차 캐시 : 한번 조회했던 데이터를 다시 조회하면 DB 쿼리를 보내지 않고, 1차캐시라는 곳에서 찾음
  • 동일성 보장 : 1차캐시에서 찾은 데이터를 비교하기 때문에 == 으로 비교해도 같음
  • 변경감지 : update 할때 jpa가 자동으로 인식해서 알려줌

그럼 영속성이 정확히 무엇인지 알아보자


비영속성 : 그냥 일반적으로 객체가 만들어진 상태 (new 또는 builder로 객체가 생성된 상태)

Member member = new Member();
member.setId("member1");
member.setUsername("홍길동");

영속성 : 생성된 객체가 영속성 컨텍스트에 저장되어있는 상태 -> persist, find 메소드 이용

EntityManager em = EntityManagerFactory.createEntityManager();
em.getTransaction().begin();

Member member = new Member();

em.persist(member); // 객체를 영속성 컨텍스트에 저장(영속) = 아직 쿼리를 보내지 않음 = 영속성컨테스트에만 저장

em.getTransaction.commit(); // 트랜잭션이 커밋하는 시점에 DB에 쿼리가 날라감 = DB에 INSERT됨
// update 문을 보내려는 경우
	EntityManager em = emf.createEntityManager();
		EntityTransaction transaction = em.getTransaction();
		transaction.begin(); // [트랜잭션] 시작
		Member memberA = em.find(Member.class, "memberA"); // 영속 엔티티 조회
		
		memberA.setUsername("hi"); // 영속 엔티티 데이터 수정 (한문장으로 update 가능)
		
		transaction.commit(); // [트랜잭션] 커밋하는 순간에 DB에 UPDATE 쿼리 보냄
  • persist : 새로운 엔티티를 영속성 컨텍스트에 추가하여, 트랜잭션 커밋 시 데이터베이스에 저장
  • find : 데이터베이스에서 특정 엔티티를 검색하고, 반환값이 null이면 해당 데이터가 없다는 의미

준영속성 : 영속된 컨텍스트에 저장되어있다가 해제된 상태

// update 문을 보내려는 경우
	EntityManager em = emf.createEntityManager();
		EntityTransaction transaction = em.getTransaction();
		transaction.begin(); // [트랜잭션] 시작
		Member memberA = em.find(Member.class, "memberA"); // 영속 엔티티 조회
		
        em.detach(memberA); // memberA 엔티티를 영속성 컨텍스트에서 분리(준영속)
        
		memberA.setUsername("hi"); 	
        transaction.commit(); // 이미 MemberA가 준영속 상태로 되었기 때문에, 커밋시점에 update문을 실행 x

준영속성은 위에 영속성 과 다르게 update 쿼리가 보내지지 않는다
그 이유는 영속성 컨테스트에 있는 MemberA를 분리했기 때문

실제로는 직접 사용할 일은 없고, 웹 어플리케이션을 이해할 때 참고

준영속 상태로 만드는 방법은 다음과 같이 3개가 있다

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

삭제 : 객체를 삭제한 상태

em.remove(member); // DB에 DELETE 쿼리가 COMMIT 시점에 나감

✅ JPA 구조
기존에는 CRUD 요청을 JDBC에다 했지만 JPA를 사용하면 JPA가 CRUD 요청을 한다

엔티티와 영속성 컨텍스트가 돌아가는 구조는 다음과 같다
(1) : Entity 어노테이션을 적용한 java 클래스의 객체를 생성 -> 비영속 상태임
(2) : EntityManager 객체를 사용해서 persist() 메소드를 이용하여 영속 상태로 만들어줌
(3) : 등록한 영속객체들은 영속성 컨텍스트 가 관리해줌
(4) : 트랜잭션을 커밋 하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터 베이스에 반영
-> 자동으로 flush() 호출

flush : 영속성 컨테스트의 변경내용을 데이터베이스에 반영하는 작업

flush 가 호출되면

  • 변경이 감지됨, 수정된 엔티티가 쓰기/지연 SQL에 저장소에 등록됨
  • 쓰기/지연 SQL 저장소의 쿼리를 데이터 베이스에 전송함
EntityManager em = EntityManagerFactory.createEntityManager();
em.getTransaction().begin();

Member member = new Member();

em.persist(member); // 객체를 영속성 컨텍스트에 저장(영속) = 아직 쿼리를 보내지 않음 = 영속성컨테스트에만 저장

// 원래는 트랜잭션 커밋되는 순간에 쿼리가 보내지지만, flush() 메소드를 호출하면
em.flush(); // 이 시점에서 쿼리보내짐

em.getTransaction.commit(); 

데이터베이스 스키마 자동생성

지난 장에 JPA를 설정할 때 아래와 같은 문구가 있을 것이다
이 설정은 개발할 때 테스트 용도로 편하게 사용하기 위해서 존재한다

<property name="hibernate.hbm2ddl.auto" value="create"/> // value에속성 넣음

hibernate.hbm2ddl.auto 옵션을 사용
@Entity 가 매핑되어있는 클래스을 가지고 자동 생성이 됨
운영에서는 사용하지 않고 개발할 때에만 테스트용도로 사용추천

다음은 스키마 자동생성 속성의 종류다

  • create : 기존 테이블을 삭제 후 다시 생성함 (DROP + CREATE)
  • create-drop : create 속성과 동일하며, 종료시점에 테이블을 drop 시킴
  • update : 기존 테이블이 있다면 삭제하지 않고 변경한 부분을 update 시켜줌
  • validate : 엔티티와 테이블이 정상 매핑되어있는지 확인, 없으면 컴파일 오류 발생
profile
우측 상단 햇님모양 클릭하셔서 무조건 야간모드로 봐주세요!!

0개의 댓글