Spring Boot 9일차

김용진·2023년 10월 10일
0

갑자기 9일차 가는 이유는 중간에 계속 기존에 한 것 연장선으로 갔기때문에 9일차로 변경이 되었습니다.

1. 영속성 관리 - JPA 내부 구조

1-1. 영속성 컨텍스트

  • JPA를 이해하는데 가장 중요한 용어
  • 엔티티를 영구 저장하는 환경이라는 뜻
  • EntityManager.persist(entity);
    -> "entity"에 들어가는 객체(Team, Member..)등을 DB에 저장하는것처럼 보이지만 좀 더 깊은 의미가 있다.
  • DB에 저장하는게 아니라 영속성 컨텍스트라는 곳에 저장하는것
  • 영속성 컨텍스트는 논리적인 개념
  • 눈에 보이지 않는다.
  • 엔티티 매니저를 통해 영속성 컨텍스트에 접근한다.
  • 엔티티 매니저를 호출하면 생성하는 영속성 컨텍스트 1:1 생성된다.

1-2. 엔티티의 생명주기

  • 비영속(new/trasient)
    -> 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
  • 영속(managed)
    -> 영속성 컨텍스트에 관리되는 상태
  • 준영속(detached)
    -> 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 삭제(removed)
    -> 삭제된 상태

1-3. 비영속

  • JPA와 전혀 상관없는 상태

    	Member member = new Member();
    	member.setId("member1");
    	member.setUsername("회원1");

위 객체는 아직 컨텍스트에 영속되어 있지 않은 상태로 보면 된다.

아직 member라는 객체가 컨텍스트에는 포함되지 않은 상태이다.

1-4. 영속

  • JPA에 속해있는 상태

    	Member member = new Member();
    	member.setId("member1");
    	member.setUsername("회원1");
    
    	EntityManager em = emf.createEntityManager();
    	em.getTransaction().begin();
    
    	// 객체를 영속
    	em.persist(member);

em.persist(member);을 사용함으로써 컨텍스트에 영속을 시켜준다.

1-5. 준영속

  • 회원 엔티티를 영속성 컨텍스트에서 분리시키는것

    	em.detach(member);

1-6. 삭제

  • 객체 삭제를 요청

    	em.remove(member);

이후 persist를 다시 선언 해 주어야만 다시 영속이 가능하다.

사실 현재 commit을 선언하지 않았기 때문에 DB에는 SQL을 날리지 않은걸로 보면 되는 상황이다.
즉, Managed 상태만 보고있다고 보면 된다.

commit문을 날리게 되면 flush()가 포함되어있어, SQL을 insert하게 된다.

1-7. 영속성 컨텍스트의 이점

  • 1차캐시
  • 동일성(identity)보장
  • 트랜잭션을 쓰기 지연(transactional write-behind)
  • 변경 감지(Dirty Checking)
  • 지연 로딩(Lazy Loading)

1-8. 엔티티 조회 - 1차 캐시

  • 영속성 컨텍스트와 식별자 값
    -> 엔티티를 식별자 값(@id로 테이블의 기본 키와 매핑)으로 구분
    -> 영속 상태는 식별자 값이 반드시 있어야 한다.
    -> 식별자 값이 없으면 예외 상황
  • 영속성 컨텍스트와 데이터베이스 저장
    -> JPA는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터 베이스에 반영, 즉 플러시(flush)메서드가 실행된다는 뜻

컨텍스트 안에 key와 value값을 영속한 공간을 1차 캐시라고 하는데, 이때는 아직 commit을 날리기 전이므로 DB에는 값이 저장되어 있지 않다.

이 상태에서 엔티티매니저를 통해 find메서드를 선언하면, DB보다 1차캐시에서 값을 먼저 찾아 해당key에 value값이 있다면 보여준다.

만약 값이 1차캐시에 저장되어 있는 key가 없다면 DB에서 값을찾아 1차캐시로 return하여 저장하고 select한다.

1차캐시에 값이 있기 때문에 DB를 거치지 않고 바로 member라는 value를 반환한다.

1차 캐시에 값이 없는 member2 를 찾았기 때문에 DB에서 조회한 후 1차 캐시에 저장하고 그 값을 반환하는 모습을 볼 수 있다.

		EntityManagerFactory emf 
			= Persistence.createEntityManagerFactory("hello");
		EntityManager em = emf.createEntityManager();
		
		EntityTransaction tx = em.getTransaction();
		tx.begin();
		
		Member member = new Member();
		
		// 추가
		member.setId(5L);
		member.setName("UserC");
		
		//회원 조회
		Member findMember = em.find(Member.class, 2L);
		System.out.println("findMember.id : " + findMember.getId());
		System.out.println("findMember.name : " + findMember.getName());
		
		//회원 수정
		findMember.setName("SuperUser");
		
		em.persist(member);


		tx.commit();
		em.close();
		emf.close();

EntityManager를 만들면서, 트랜잭션을 시작하고, 미리 만들어둔 Member객체를 꺼내와, 데이터를 넣고 persist로 영속성 컨텍스트에 추가한 뒤, commit을 날려 DB에 저장하고 close로 트랜잭션과 엔티티매니저를 닫아주는 코드의 전체적인 모습이다.

profile
메모리폼

0개의 댓글