JPA 2

정해랑·2024년 4월 4일
  1. 영속성

1-1. 1차캐시

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

1-2. 1차 캐시에서 조회
Member member = new Member();
member.setid("member1");
member.setUsername("회원1");

em.persist(member); // 1차 캐시에 저장됨

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

1-3. 데이터베이스에서 조회
// 현재 member2라는 @id로는 1차 캐시에 Entity가 없는 상태

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

1-4. 트랜잭션을 지원하는 쓰기 지연
em.begin(); // 트랜잭션 시작

em.persist(memberA);
em.persist(memberB);
// 여기까지는 Insert SQL을 데이터베이스에 보내지 않는다.

// 커밋하는 순간 Insert SQL을 보낸다.
em.commit(); // 트랜잭션 커밋

1-5. 엔티티 수정 변경 감지(Dirty Checking)
em.begin(); // 트랜잭션 시작

// 영속 엔티티 조회
Member memberA = em.find(Member.class,"memberA");

// 영속 엔티티 데이터를 수정
memberA.setUserName("jpauser");

// 이런코드 예상..?
em.update(member);

em.commit(); // 트랜잭션 커밋

  • flush()가 호출되는 시점에 Entity와 스냅샷을 전부 비교후에
    ( 최적화 알고리즘으로 비교 ) 변경이 된 것을 감시(Dirty Checking)한 후에 update 쿼리를 작성 후, update 쿼리를 날린다.

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

// 엔티티 삭제
em.remove(memberA);

  1. 플러쉬
  • 변경 감지
  • 수정된 엔티티 쓰기 SQL 저장소에 등록
  • 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송
    (등록,수정,삭제 쿼리)
  1. 영속성 컨택스트를 플러쉬하는 방법
  • commit : 플러쉬 자동 호출
  • em.flush() : 직접 호출
  • JPQL 쿼리 실행 : 플러쉬 자동 호출
  1. 플러쉬란?
  • 영속성 컨텍스트를 비우지 않음
  • 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화
  • 트랜잭션이라는 작업 단위가 중요하다 -> 커밋 직전에만 동기화 하면 된다
  • JPA는 동시성, 데이터를 맞추거나 등을 모두 트랜잭션에 위임을 한다.
  1. 준영속
  • 영속 -> 준영속
  • 준영속 : 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)
  • 영속성 컨텍스트가 제공하는 기능을 사용하지 못함
  1. 준영속 상태로 만드는 방법(알아만 둘것)
  • em,detach(entity)
    -> 특정 엔티티만 준영속 상태로 전환
  • em.clear()
    -> 영속성 컨텍스트를 완전히 초기화
  • em.close();
    -> 영속성 컨텍스트를 종료
  1. 엔티티 매핑 소개
  • 객체와 테이블 매핑 : @Entity, @Table
  • 필드와 컬럼 매핑 : @Column
  • 기본키 매핑 : @Id
  • 연관관계 매핑 : @ManyToOne, @JoinColumn
  1. @Entity
  • @Entity가 붙은 클래스는 JPA가 관리, 엔티티라 한다
  • JPA를 사용해서 테이블과 매핑할 클래스는 @Entity가 필수
  • 기본생성자가 필수
  • final 클래스, enume, interface, inner 클래스 사용 X
  • 저장할 필드에 final 사용 X

9.@Table

  • 엔티티와 매핑할 테이블을 지정
  1. 데이터베이스 스키마 자동 생성
  • DDL을 애플리케이션 실행 시점에서 테이블 자동 생성
  • 테이블 중심 -> 객체 중심
  • 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL을 생성
  • 이렇게 생성된 DDL은 개발 장비에서만 사용
    ( 운영에서는 사용해서는 안된다 )
  • 생성된 DDL은 운영서버에서는 사용하지 않고, 적절히 다듬은 후 사용
  1. 데이터베이스 스키마 자동 생성 - 속성
  • "hibernate.hbm2ddl.auto" 라는 옵션이 있다
  • create
    -> 기존테이블 삭제 후 다시 생성(drop + create)
    create-drop
    -> create와 같으나, 종료시점에 테이블 drop
    update
    -> 변경분만 반영(운영 DB에서는 사용하면 안됨)
    validate
    -> 엔티티와 테이블이 정상 매핑되었는지만 확인
    none
    -> 사용하지 않음
  • 데이터베이스 방언 별로 달라진다.
  • 운영장비에는 절대 create, create-drop, update 사용하면 안된다
  • 개발 초기 단계는 create 또는 update
  • 테스트 서버는 update 또는 validate
  • 운영서버 none 또는 validate
  1. DDL 생성 기능
  • 제약조건 추가 : 회원이름은 필수, 10자 초과X
    @Column(nullable=false, length=10)
  • 유니크 제약조건 추가
    @Table(uniqueContraints={@UniqueContraint(name="name_unique")columnNames={"NAME",
    "AGE"}})
  • DDL생성 기능은 DDL을 자동 생성할 때만 사용되고, JPA의 실행 로직에는 영향을 주지 않는다.
  1. 필드와 컬럼 매핑
  • @Column : 컬럼 매핑
  • @Temploral : 날짜 타입 매핑
  • @Enumerated : enum 타입 매핑
  • @Lob : BLOB, CLOB 매핑
  • @Transient : 특정 필드를 컬럼에 매핑하지 않음(매핑 무시)
  1. @Lob
  • 데이터베이스 BLOB, CLOB 타입과 매핑
  • @Lob에는 지정할 수 있는 속성이 없다.
  • 매핑하는 필드 타입이 문자면 CLOB, 나머지는 BLOB매핑
  1. @Transient
  • 필드 매핑 X
  • 데이터베이스 저장 X, 조회 X
  • 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용하게 된다
  1. 기본키 매핑
  • @Id
  • @GeneratedValue
  1. 기본 키 매핑 방법
  • 직접 할당 : @Id만 사용
  • 자동 생성 : @GeneratedValue - 4가지 전략
    -> identity : 데이터베이스에 위임, MYSQL
    -> sequence : 데이터베이스 시퀀스 오브젝트 사용,
    ORACLE, @SequenceGenrator
    -> table : 키 생성 테이블을 사용, 모든 DB에서 사용 @TableGenerator 필요
    -> AUTO : 방언에 따라 자동 지정, 기본값
  • AUTO는 DB방언에 맞춰서 IDENTITY, SEQUENCE, TABLE 3개 중 하나가 선택된다.
  1. SEQEUNCE - @SequenceGenerator
  1. 도메인 모델 분석

0개의 댓글