java 스프링부트 ( spring boot ) / JPA ( 2 ) 영속성 컨텍스트

김동명·2022년 12월 16일
0

스프링부트

목록 보기
12/19

프로젝트 설정

  • application.properties

#port
server.port=9090

#encoding
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.force=true
server.servlet.encoding.enabled=true

  • 계정 생성
sqlplus

create user springjpa identified by springjpa;

grant connect, resource to springjpa;

  • 디비버
Database : XE
username = springjpa
password = springjpa
  • resources > META-INF 폴더 생성 > persistence.xml 생성
    • hibernate.hbm2ddl.auto 옵션
      • 데이터베이스 스키마 자동생성 옵션
      • create : 기존 테이블 삭제 후 다시 생성 ( drop + create )
      • create-drop : create와 같으니 종료시점에 테이블 drop
      • update : 변경분만 반영
      • validate : 엔티티와 테이블이 정상 매핑되었는지만 확인
      • none : 사용하지 않음
<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.2"
   xmlns="http://xmlns.jcp.org/xml/ns/persistence"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
   <persistence-unit name="hello">
      <properties>
         <!-- 필수 속성 -->
         <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.driver.OracleDriver" />
         <property name="javax.persistence.jdbc.user" value="springjpa" />
         <property name="javax.persistence.jdbc.password" value="springjpa" />
         <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:xe" />
         <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
		
        <!-- 테이블 생성 옵션 ( 필요할 때만 사용 ) -->
		<property name="hibernate.hbm2ddl.auto" value="create"/>
		
         <!-- 옵션 -->
         <!-- 콘솔에 하이버네이트가 실행하는 SQL문 출력 -->
         <property name="hibernate.show_sql" value="true" />
         <!-- SQL 출력 시 보기 쉽게 정렬 -->
         <property name="hibernate.format_sql" value="true" />
         <!-- 쿼리 출력 시 주석(comments)도 함께 출력 -->
         <property name="hibernate.use_sql_comments" value="true" />
      </properties>
   </persistence-unit>
</persistence>



ㅇ 개념 정리

- 영속성 컨텍스트

  • JPA를 이해하는데 가장 중요한 용어

  • 객체의 엔티티를 영구 저장하는 환경

  • EntityManager.persist(entity);
    -> "Entity"에 들어가는 객체 ( Member, Team, .. 등 ) 를 DB에 바로 저장하는 것이 아니라, 영속성 컨텍스트라는 곳에 저장한다.

  • EntityManager를 통해서 영속성 컨텍스트에 접근

  • 엔티티 생명주기

    • 비영속( new/transient)
      : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태

        Member member = new Member();
        member.setId("member1")
        member.setUsername("회원1");
    • 영속 ( managed)
      : 영속성 컨텍스트에 관리되는 상태

      	em.persist(member);
    • 준영속 ( detached )
      : 영속성 컨텍스트에 저장되었다가 분리된 상태

      	em.detach(member);
    • 삭제 ( removed )
      : 삭제된 상태

      	em.remove(member); 

  • 1차 캐시
    : 영속성 컨텍스트안에 데이터를 저장하는 공간으로 데이터를 불러 올 때 JPA가 확인하는 공간이다. 만약 1차 캐시에 데이터가 없다면 DB를 조회 한 후 1차 캐시에 데이터를 저장하고 리턴해주게된다.

  • 동일성 보장
    : 객체 변수에 같은 key값을 담을 경우 두 변수는 동일하다.
    	Member a = em.find(Member.calss, "member1" );
    	Member b = em.find(Member.calss, "member1" );

  • 트랜젝션을 지원하는 쓰기 지연
    : persist 하는 순간 쓰기 지연 SQL 저장소에 DB로 보낼 쿼리문을 작성하여 쌓아두고 commit되는 순간 DB에 sql문을 보낸다.

    	tx.begin();	: 트랜잭션 시작
    
    	em.persist(memberA);
    	em.persist(memberA);
    	// 여기까지는 insert sql을 데이터베이스에 보내지 않는다.
    
    	// 커밋하는 순간 데이터베이스에 insert sql을 보낸다.
    	tx.commit();	: 트랜잭션 커밋

  • 수정 변경 감지 ( Dirty Checking )
    : flush()가 호출되는 시점에 Entity와 스냅샷을 전부 비교 후 변경이 된 것을 감지 ( Dirty Checking ) 한 후에 update 쿼리를 작성 후, update 쿼리를 보낸다.

    //  엔티티 조회
    Member memberA =em.find(Member.class, "memberA");	
    
    memberA.setUsernae("hello");
    memberA.setAge(10);
    
    // em.update(member); // update가 필요할 것처럼 보이지만 JPA가 알아서 비교해서 update 쿼리를 작성해준다.
    tx:commit();	: 커밋

  • 삭제

    	Member
    
    	// 삭제 대상 엔티티 조회
    	Member memberA = em.find(Member.class, "memberA");
    
    	em.remove(memberA); 	: 엔티티 삭제

  • flush();
    : 영속성 컨텍스트의 변경 내용을 DB에 반영

    • 플러시 발생
      - 변경 감지
      - 수정된 엔티티 쓰기 지연 SQL저장소에 등록
      - 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송

    • 영속 컨텍스트를 플러시 하는 방법
      - em.flush() : 직접 호출
      - 트랜잭션 커밋 : 플러시 자동 호출
      - JPQL 쿼리 실행 : 플러시 자동 호출


  • 준영속 상태
    - 영속 - > 준영속
    - 준영속 : 영속 상태의 엔티티가 영속성 컨텍스트에서 분리 ( detached )
    - 영속성 컨텍스트가 제공하는 기능을 사용 하지 못함

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



1. 영속성 컨텍스트

  • JpaMain2.java 생성
public class JpaMain2 {

	public static void main(String[] args) {
			
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
		EntityManager em = emf.createEntityManager();
		
		// transcation 발생
		EntityTransaction tx = em.getTransaction();
		tx.begin();
		
		try {
			// 비영속 상태
			Member member = new Member();
			member.setId(100L);
			member.setName("Hello");
			
			// 영속상태
			// EntityManager 안에 있는 영속 컨텍스트로 관리
			// DB쿼리가 실행되는지 확인
			System.out.println("=======before=========");
			em.persist(member);
			System.out.println("=======after=========");
			
			// 쿼리가 보내지는 시점
			tx.commit();
		} catch (Exception e) {
			tx.rollback();
		} finally {
			em.close();
			emf.close();		
		}
		
	}

}


-> java 스프링부트 ( spring boot ) / JPA ( 3 ) Entity Mapping 계속

profile
코딩공부

0개의 댓글