Skip to content

ZeroZoa/Spring-JPA-Study

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 

Repository files navigation

📚 Spring-JPA-Study

ZeroZoa의 스프링 JPA 공부 기록

이 저장소는 Java Persistence API (JPA)를 학습하고 정리한 내용을 담고 있습니다. ORM의 기본 개념부터 엔티티 매핑, 영속성 관리, 다양한 연관관계 전략 등 JPA의 핵심적인 내용을 다룹니다.


📌 JPA 실무 Best Practice

실무에서 JPA를 효과적으로 사용하기 위한 핵심 전략입니다.

  1. 🚀 모든 연관관계는 지연 로딩(LAZY)으로 설정하세요.

    • 즉시 로딩(EAGER)은 예측하지 못한 SQL이 발생하는 주범이며, 특히 JPQL에서 N+1 문제를 일으킬 수 있습니다.
    • @ManyToOne, @OneToOne은 기본값이 즉시 로딩이므로 반드시 fetch = FetchType.LAZY 옵션을 명시해야 합니다.
    • 성능 최적화가 필요한 경우 Fetch Join이나 @EntityGraph, **@BatchSize**를 사용해 필요한 데이터만 함께 조회하는 것을 권장합니다.
  2. 🔗 외래 키(FK)가 있는 곳을 연관관계의 주인으로 정하세요.

    • 연관관계의 주인은 외래 키를 직접 관리하는 엔티티가 되어야 합니다.
    • 주인이 아닌 곳에 외래 키를 매핑하면, 연관관계 관리를 위해 추가적인 UPDATE 쿼리가 발생하여 성능 저하의 원인이 됩니다.
  3. 🛡️ 엔티티에는 가급적 @Setter를 사용하지 마세요.

    • @Setter를 무분별하게 사용하면 엔티티의 변경 지점을 추적하기 어려워 유지보수가 힘들어집니다.
    • 대신, 변경 목적이 명확한 비즈니스 메서드를 별도로 만들어 관리하는 것이 좋습니다. (예: cancelOrder(), updateStock(int stock))
  4. 💎 값 타입(Embeddable)은 불변 객체(Immutable Object)로 설계하세요.

    • 객체 타입은 참조를 공유하기 때문에, 여러 엔티티에서 하나의 값 타입을 공유하면 예상치 못한 부작용(Side Effect)이 발생할 수 있습니다.
    • @Setter를 제거하고, 생성 시점에만 값을 할당하여 변경 불가능하게 만들면 안전하게 사용할 수 있습니다.
  5. ✨ 컬렉션은 필드에서 즉시 초기화하세요.

    • NullPointerException과 같은 예기치 않은 오류를 방지하기 위해, 컬렉션은 선언과 동시에 초기화하는 것이 안전합니다.
    • List<Comment> comments = new ArrayList<>();
  6. 📤 API를 만들 때 엔티티를 외부로 직접 반환하지 마세요.

    • 엔티티는 데이터베이스와 직접 연결된 핵심 도메인 객체입니다. 엔티티가 변경되면 API 스펙 전체가 흔들릴 수 있습니다.
    • 반드시 DTO(Data Transfer Object)를 사용하여 API 응답에 필요한 데이터만 선별적으로 노출하세요.
  7. 💥 벌크 연산 후에는 영속성 컨텍스트를 초기화하세요.

    • 벌크 연산은 영속성 컨텍스트를 무시하고 DB에 직접 쿼리를 실행합니다.
    • 데이터 정합성 문제를 피하기 위해, 벌크 연산 수행 직후에는 영속성 컨텍스트를 초기화(em.clear())하는 것을 권장합니다.


📖 Table of Contents

  1. JPA 소개
  2. JPA 시작하기
  3. 영속성 관리
  4. 엔티티 매핑
  5. 연관관계 매핑 기초
  6. 다양한 연관관계 매핑
  7. 프록시와 연관관계 관리
  8. 값 타입
  9. 객체지향 쿼리 언어 (JPQL)


📜 Chapter 1 : JPA 소개

ORM (Object Relational Mapping)

  • 이름 그대로 객체관계형 데이터베이스를 매핑하는 기술입니다.
  • ORM 프레임워크가 객체와 테이블 간의 패러다임 불일치 문제를 해결해 줍니다.

JPA (Java Persistence API)

  • Java 진영의 ORM 기술 표준 명세(Interface)입니다.

JPA의 특징

  1. 생산성: save(), findById() 등 기본적인 CRUD를 제공하며, DDL 자동 생성 기능도 지원합니다.
  2. 유지보수: 필드 변경 시 모든 SQL을 수정할 필요 없이, 매핑 정보만 수정하면 되어 유지보수가 용이합니다.
  3. 패러다임 불일치 해결: 상속, 연관관계, 객체 그래프 탐색 등 객체와 RDB의 차이에서 오는 문제를 해결합니다.
  4. 벤더 독립성: 추상화된 데이터 접근 계층을 제공하여 데이터베이스 변경에 유연하게 대처할 수 있습니다.
  5. 성능 최적화: 1차 캐시, 쓰기 지연, 지연 로딩 등을 통해 성능 최적화를 시도할 수 있습니다.

주요 메서드

save(S);       // 엔티티 저장 및 병합
delete(T);     // 엔티티 삭제
findById(ID);  // ID로 엔티티 조회
findAll();     // 모든 엔티티 조회

JPA

  • Chapter 1

    • Java Persistence API - JPA

      • ORM Object Relational Mapping
        • 이름 그대로 객체와 관계형 데이터베이스를 매핑
        • ORM 프레임 워크가 객체의 관계를 매핑한다.
    • JPA의 특징

      1. 생산성
        • JPA를 사용하면 컬렉션에 객체를 저장하듯이 JPA에게 저장할 객체를 전달하면 된다.
        • 더 나아가 JPA에는 DDL(가령 CREATE TABLE)문을 자동으로 생성해주는 기능도 있다.
      2. 유지보수
        • SQL을 이용하면 엔티티에 필드 하나만 추가되어도 관련된 코드를 모두 변경해야 했지만, JPA는 이런 과정을 생략해준다.
      3. 패러다임의 불일치 해결
        • 상속, 객체 그래프 탐색, 비교와 같은 패러다임 불일치 문제를 해결해준다.
      4. 데이터 접근 추상화와 벤더 독립성
        • 많은 경우 애플리케이션은 처음 선택한 데이터베이스 기술에 종속적이다.
          • 즉 데이터베이스 변경이 매우 어렵다.
        • 하지만 JPA는 애플리케이션 ↔︎ 데이터베이스 사이에 추상화된 데이터 접근 계층을 제공해 종속되지 않도록 방지해준다.
      5. 성능
        • JPA는 애플리케이션과 데이터베이스 사이에서 동작하므로 최적화 관점에서 시도해볼 수 있는 기회가 많다.
      6. 표준
        • ORM표준이라 다른 구현 기술로 손쉽게 변경 가능하다.
    • JPA의 주요 매서드

      save(S) //엔티티를 저장하고 병합delete(T) // 엔티티를 삭제findById(Id) // ID를 통해 엔티티를 조회findAll() //모든 엔티티를 조회
  • Chapter 2

    • JPA 사용법 1. 객체 매핑
      • JPA에서는 어노테이션을 통해서 객체 ↔︎ 클래스를 매핑한다.
      • 어노테이션 별 특징
        • @Entity
          • 이 클래스를 테이블로 매핑한다고 JPA에게 선언, 엔티티 클래스라고 한다
        • @Table
          • 매핑할 테이블의 정보를 알려주는 어노테이션, default값은 클래스 이름이 테이블 이름으로 매핑된다.
        • @Id
          • 엔티티 클래스의 필드를 기본키에 매핑한다. 즉 PK가 된다.
        • @Column
          • 필드를 컬럼에 매핑한다.
        • 매핑 정보가 없는 필드
          • 어노테이션을 생략하면 필드명이 데이터베이스의 컬럼명 “그 자체”가 된다.
    • JPA의 사용법 2. persistence.xml
      • persistence.xml는 JPA를 위한 설정 정보를 관리하는 파일
      • 별도의 설정 없이 JPA가 인식할 수 있다.
      • JPA의 표준속성
        • javax.persistence.jdbd.driver : JDBC드라이버
        • javax.persistence.jdbd.user : 데이터베이스 접속 ID
        • javax.persistence.jdbd.password : 데이터베이스 접속 PW
        • javax.persistence.jdbd.url : 데이터베이스 접속 URL
      • 데이버베이스 방언
        • JPA는 서로 다른 데이터베이스의 언어도 지원한다
    • JPA의 사용법 3.애플리케이션 개발
      • 엔티티 매니저 설정
        • 엔티티 매니저 팩토리 생성
          • 첫 번째로 persistence.xml의 설정 정보를 이용해 엔티티 매니저 팩토리를 생성
            • 엔티티 매니저 팩토리를 생성하는 비용은 아주 크다. 따라서 딱 한 번만 생성하고 공유해서 사용해야 한다.
        • 엔티티 매니저 생성
          • JPA의 기능 대부분을 수행한다.
          • 엔티티 매너저를 사용해서 엔티티를 데이터베이스에 CRUD할 수 있다.
          • 엔티티를 가상의 데이터베이스로 생각할 수 있다.
        • 종료
          • 사용이 끝난 엔티티 매니저는 반드시 종료해야 한다.
      • 트랜잭션 관리
        • JPA를 사용하면 항상 트랜잭션 안에서 데이터를 변경해야 한다.
        • 트랜잭션 없이 데이터를 변경하면 예외 발생
        • 트랜잭션을 시작하려면 엔티티 매니저에서 트랜잭션API를 받아와야 한다.
      • 비지니스 로직
        • 예를 들면 회원 엔티티를 하나 생성한 후 엔티티 매니저를 통해 데이터베이스에 CRUD한다.
        • save, update, remove, find로 비지니스 로직이 이루어진다.
      • JPQL
        • JPA를 사용하면 애플리케이션 개발자는 엔티티 객체를 중심으로 개발하고 데이터베이스에 대한 처리는 JPA에 맡겨야함
        • JPQL은 엔티티 객체를 대상으로 쿼리
        • SQL은 데이터베이스 테이블을 대상으로 쿼리
    • 결과적으로…
      • 개발자는 JPA를 통해 객체의 CRUD구현을 간단하게되었고, 결과값을 매핑해준다.
  • Chapter 3

    • 영속성 관리
      • JPA는
        • 엔티티와 테이블을 매핑하는 설계하는 부분
        • 매핑한 엔티티를 실제 사용하는 부분으로 나뉨
      • 엔티티 매니저는 엔티티를 CRUD하는 모든 일을 처리한다.
    • 엔티티 매니저 팩토리와 엔티티 매니저
      • 애플리케이션은 일반적으로 EntityManagerFactory를 하나만 생성한다.
        • Persistence.xml의 정보를 바탕으로 EntityManagerFactory를 생성한다.
      • 이렇게 생성된 EntityManagerFactory는 필요할 때마다 엔티티 매니저를 생성한다.
      • EntityManagerFactory는 EntityManager를 만드는 공장인데,
        • EntityManagerFactory는 생성 비용이 매우 커 한 개만 생성해 공유하여 사용한다.
      • EntityManagerFactory는 스레드들이 동시에 접근해도 안전하다.
      • EntityManager는 스레드들이 동시에 접근하면 동시성 문제가 발생 → 공유하면 안된다.
    • 영속성 컨텍스트란?
      • 영속성 컨텍스트 = 엔티티를 영구 저장하는 환경
      • 영속성 컨텍스트는 엔티티 매니저를 생성할 때 만들어지고, 엔티티 매니저를 통해서 영속성 컨텍스트를 접근, 관리할 수 있다.
    • 엔티티의 생명주기
      • 비영속성
        • 엔티티 객체를 생성한 후 아직 저장하지 않은 상태, 데이터베이스와는 전혀 관련이 없다.
      • 영속
        • 엔티티 매니저를 통해 엔티티를 영속성 컨텍스트에 저장한 상태
        • 영속성 컨텍스트가 관리하는 엔티티를 영속상태라 한다.
      • 준영속
        • 관리하던 영속 상태의 엔티티를 영속성 컨텍스트가 관리하지 않으면 준영속 상태가 된다.;
      • 삭제
        • 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제한다.
    • 영속성 컨텍스트의 특징
      • 영속성 컨텍스트와 식별자 값
        • 영속성 컨텍스트는 테이블의 기본 키와 매핑한 값으로 구분한다.
          • 따라서 영속 상태는 식별자 값이 반드시 있어야 한다.
        • 엔티티가 데이터베이스에 저장되는 시점
          • JPA는 트랜잭션이 Commit되는 순간 영속성 컨텍스트에 저장된 에티티를 데이터베이스에 반영한다.
      • 영속성 컨텍스트가 엔티티를 관리할 때의 장점
        • 1차 캐시
        • 동일성 보장
        • 트랜잭션을 지원하는 쓰기 지연
        • 변경 감지
        • 지연 로딩
    • 엔티티 조회
      • 영속성 컨텍스트는 캐시를 갖고있는데 이걸 1차 캐시라고 한다.
        • 1차 캐시에게 키(@Id)는 식별자 값이고 이 값은 데이터베이스 기본 키와 매핑되어 있다.
        • 1차 캐시에서 조회
          • find()매서드를 호출하면 1차 캐시 안에서 식별자 값으로 엔티티를 찾는다.
          • 만약 1차 캐시에 엔티티가 있으면 데이터베이스를 조회하지않고 엔티티를 조회할 수 있다.
        • 데이터베이스 조회
          • 만약 find()를 호출했는데 엔티티가 1차 캐시에 없으면 엔티티 매니저는 데이터베이스를 조회햇서 생성한다.
          • 그리고 난 뒤 1차 캐시에 저장한 후에 영속 상태의 엔티티를 반환한다.
        • 결과적으로 1차 캐시에 저장된 엔티티(영속 상태)는 바로 불러올 수 있기때문에 성능상 이점 + 엔티티 동일성을 보장한다.
    • 엔티티 등록
      • 엔티티 매니저는 트랜잭션을 커밋하기 직전까지 내부 쿼리 저장소에 INSERT SQL을 모아둔다.
      • 트랜잭션을 커밋할 때 모아둔 쿼리를 데이터베이스에 보내는데 이를 쓰기 지연이라고 한다.
      • 자세히
        • 트랜잭션을 커밋하면 엔티티 매니저는 영속성 컨텍스트를 플러시한다.
          • 플러시는 영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화하는 작업이다
          • 이때 CRUD한 엔티티를 데이터베이스에 반영한다.
          • 쓰기 지연 SQL저장소에 모인 쿼리를 데이터베이스에 보낸다.
          • ⇒ 즉 트랜잭션을 지원하는 쓰기 지연이 가능한 이유
    • 엔티티 수정
      • SQL 수정 쿼리의 문제점
        • SQL을 사용하면 수정 쿼리를 직접 작성해야 한다.
        • 프로젝트가 커지고 요구사항이 늘어나면 수정 쿼리도 점점 복잡해지고 커진다.
          • 결과적으로 이런 개발의 문제점은 수정 쿼리가 많아지는 것은 물론이고 비지니스 분석을 위해 SQL을 계속 확인해야한다.
      • JPA는 엔티티를 어떻게 수정할까?
        • JPA를 통해 엔티티를 데이터를 변경하면 자동으로 수정 사항을 반영한다.
        • 이를 변경 감지라고 한다.
          • JPA는 엔티티를 영속성 컨텍스트에 보관할때, 최초 상태를 저장해둔다. → 이를 스냅샷이라 한다.
          • 플러시 시점에서 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾는다.
          • 변경 감지는 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용된다.
          • 변경 감지에서 JPA의 기본 전략은 엔티티의 모든 필드를 업데이트 하는 것이다.
            • 이렇게 되면 데이터베이스에 보내는 데이터 전송량이 증가한다는 단점이 있다.
            • 하지만 수정 쿼리의 일정함, 재사용성에서의 장점이 있다.
    • 엔티티 삭제
      • 엔티티를 삭제하기 위해 먼저 해당 엔티티 조회가 필요하다.
      • 삭제 대상 엔티티를 넘겨주면 엔티티를 즉시 삭제하는 것이 아니라 엔티티 등록과 비슷하게 쿼리를 쓰기 지연 저장소에 등록한다.
    • 플러시
      • 플러시는 즉 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영한다는 것을 뜻한다.
      • 플러시를 실행하면…
        • 변경 감지가 동작하여 기존 데이터와 비교후 변경점을 찾고 수정 쿼리를 만들어 쓰기 지연 SQL 저장소에 등록한다.
        • 쓰기 지연 SQL저장소의 쿼리를 데이터 베이스에 전송한다.
      • 직접 호출
        • 엔티티 매니저의 flush매서드를 직접 호출하여 영속성 컨텍스트를 강제로 플러시
        • 거의 사용하지 않는다.
      • 트랜잭션 커밋 시 플러시 자동호출
        • 데이터베이스에 변경 내용을 SQL로 전달하지 않고 트랜잭션만 커밋하면 어떤 데이터도 데이터베이스에 반영되지 않는다. → 커밋 전 꼭 플러시 호출하여 영속성 컨텍스트 내용을 반영해야한다.
      • JPQL 쿼리 실행 시 플러시 자동 호출
        • 객체지향 쿼리를 호출할 때도 플러시가 실행된다.
          1. 엔티티를 영속상태로 만들었다 → 영속성 컨텍스트에는 존재
          2. 하지만 데이터베이스에는 반영되지 않았다.
          3. JPQL은 SQL로 변환되어 데이터베이스에서 엔티티를 조회
          4. 하지만 엔티티는 영속성 컨텍스트에만 존재하고 데이터베이스에는 없다.
          5. 따라서 쿼리 결과로 조회되지 않는다.
          6. 따라서 쿼리 실행 직전에 플로시를 해서 변경 내용을 데이터베이스에 반영해야한다.
      • 플러시 모드 옵션
        • 플러시 모드는 두 가지가 있다
          • 커밋이나 쿼리를 실행할 때 플러시하는 → AUTO
          • 커밋할때만 플러시하는 → COMMIT
        • 플러시는 이름때문에 영속성 컨텍스트에 보관된 엔티티를 지운다고 착각할 수도 있는데
        • 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화하는 것이 플러시이다.
    • 준영속
      • 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 상태
      • 준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능을 사용할 수 없다.
      • 영속 상태의 엔티티를 준영속 상태로 바꾸는 방법
        1. .detech매서드 : 특정 엔티티만 준영속 상태로 전환
          • 이 매서드를 사용하면 더는 영속성 컨택스트가 관리하지않는다.
          • 즉 준영속 상태이다.
          • 쓰기 지연 SQL 저장소의 INSERT SQL도 제거되어서 데이터베이스에 저장되지도 않는다.
        2. .clear : 영속성 컨텍스트를 완전히 초기화
          • 영속성 컨텍스트 초기화를 통해 모든 영속성 컨텍스트가 준영속 상태가 된다.
          • 준영속 상태이므로 영속성 컨택스트가 지원하는 변경 감지 또한 작동하지 않는다
        3. .close : 영속성 컨텍스트를 종료
          • 영속성 컨텍스는를 종료하면 해당 영속성 컨텍스트가 관리하던 영속 상태의 엔티티가 준영속 상태로 바뀐다.
      • 준영속의 특징
        • 거의 비영속 상태에 가깝다.
        • 식별자 값을 가지고 있다.
        • 지연 로딩을 할 수 없다.
      • 병합
        • 준영속 상태를 다시 영속 상태로 변경하기 위함
        • merge()매서드는 준영속 상태의 엔티티를 받아서 정보로 새로운 영속 상태의 엔티티를 반환한다.
      • 준영속 병합
      • 비영속 병합
        • 병합은 비영속 엔티티도 영속 상태로 만들 수 있다.
          • 병합은 파라미터로 넘어온 엔티티를 식별자값으로 영속성 컨텍스트에 조회 ⇒ 없으면 데이터베이스에서 조회 ⇒ 없으면 새로운 엔티티를 생성해서 병합한다.
    • 결과적으로…
      • 엔티티 매니저는 엔티티 매니저 팩토리에의해 생성
      • 영속성 컨텍스트는 애플리케이션과 데이터베이스 사이의 객체를 보과하는 가상의 데이터베이스라고 보면된다.(1차원 캐시, 동일성 보장, 트랜잭션, 쓰기 지연, 변경 감지, 지연 로딩등의 기능을 제공한다.)
      • 영속성 컨텍스트의 관리 유무에 따라 영속 상태를 나뉜다.
      • 영속 상태에서 벗어나면 영속성 컨텍스트가 제공하는 기능을 사용할 수 없다.
  • Chapter 4

    • 엔티티 매핑

      • JPA에서 엔티티-테이블의 정확한 매핑은 매우 중요하다.
        • 따라서 JPA에서는 어노테이션를 지원하여 매핑한다.
      • 매핑 어노테이션
        • 객체-테이블 매핑 어노테이션
          • @Entity, @Table
        • 기본 키 매핑
          • @Id
        • 필드와 컬럼 매핑
          • @Column
        • 연관관계 매핑
          • @ManyToOne, @joinColumn
    • @Entity

      • JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 어노테이션이 필수
      • @Entity가 붙은 클래스는 JPA가 관리하는 것으로 엔티티라고 부른다.
      속성 name
      기능 엔티티의 이름을 지정한다.
      (다른 패키지 이름과 중복되지 않도록 설정)
      기본값 기본값은 클래스 이름
      • 주의 사항
        • final class, enum, interface, inner 클래스에는 사용 불가능
        • 저장할 필드에 final을 사용하면 안된다.
        • 기본 생성자는 필수이다.
    • @Table

      속성 name
      기능 엔티티와 매핑할 테이블을 지정한다.
      기본값 엔티티 이름을 사용
    • 다양한 매핑 사용

      • 기본 키 매칭
        • 기본키를 직접 할당하려면 @Id만 사용하면 되고, 자동 생성 전략을 사용하려면 @Id에 @GeneratedValue를 추가하고 원하는 키 생성 전략을 선택하면 된다.
        • 기본 키 직접 할당 전략
          • IDENTITY 전략

            • 기본 키 생성을 데이터베이스에 위임하는 전략
            • @Id 컬럼 을 비워두면 데이터베이스가 순서대로 값을 채워준다.
            • @GeneratedValue어노테이션을 사용하고 식별자 생성 전략을 선택해야한다.
          • SEQUENCE 전략

            • 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트이다.
            • SEQUENCE전략은 이 시퀀스를 사용해서 기본 키를 생성한다.
            • 이 전략은 Oracle, PostgreSQL등에서 사용할 수 있다.
            • 시퀀스 사용 코드는 IDENTITY전략과 같지만 내부 동작 방식은 다르다
              1. 데이터베이스 시퀀스를 사용해서 식별자 조회
              2. 조회한 식별자를 엔티티에 할당
              3. 엔티티를 영속성 컨텍스트에 저장
              4. 이후 트랜잭션 커밋해서 플러시가 일어나면 엔티티를 데이터베이스에 저장
          • @SequenceGenerator

            속성 name initialValue allocationSize
            기능 엔티티와 매핑할 테이블을 지정한다. DDL 생생시에만 사용됨 DDL이 처음 시작하는 수를 지정한다. 시퀀스 한 번 호출에 증가하는 수
            기본값 엔티티 이름을 사용 1 50
            • JPA는 시퀀스에 접근하는 횟수를 줄이기 위해 @SequenceGenerator.allocationSize를 사용한다.
            • allocationSize값이 50이면 시퀀스를 한 번에 50 증가시킨 다음에 1~50까지는 메모리에서 식별자를 할당한다.
            • 그리고 그 값 즉 50을 넘기면 100까지 증가시킨다.
        • 테이블 전략
          • Table전략은 키 생성 전용 테이블을 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 시퀀스를 흉내내는 전략이다.
          • Table전략은 시퀀스 대신에 테이블을 사용한다는 것만 제외하면 SEQUENCE전략과 내부 동작방식이 같다.
          • @TableGenerator
            • Table전략은 값을 조회하면서 SELECT, 다음 값으로 증가시키기 위해 UPDATE를 사용한다
            • SEQUENCE에 비해 데이터베이스에 한 번 더 통신하는 단점이 있다.
        • AUTO 전략
          • Generation.AUTO는 선택한 데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략 중 하나를 자동으로 선택한다.
          • 장점으로
            • 데이터베이스를 변경해도 코드를 수정할 필요가 없다
            • 키생성 전략이 확정되지 않은 개발 초기, 프로토타입 개발시 편리
    • 결과적으로…

      • 엔티티의 식별자 값은 영속성 컨텍스트가 구분하는 기준이므로 매우 중요하다.
        • 직접할당 : 영속성 컨텍스트 호출전 직접 식별자 값을 할당
        • SEQUENCE : 데이터베이스를 통해 시쿼스 값으 갖고와 영속성 컨텍스트를 통해 저장
        • TABLE : 데이터베이스 시퀀스 생서용 테이블에서 식별자 값을 획득한 후 영속성 컨텍스트에 저장
        • IDENTITY : 데이터베이스에 엔티티를 저장해서 식별자 값을 획득한 후 영속성 컨텍스트에 저장한다.
      • 위와 같은 방법으로 @Id값을 생성할 수 있다.
      • 영한센세가 권장하는 식별자 선택 전략
        • 먼저 데이터베이스 기본키 조건을 만족할 것
          • NULL값을 허용하지 않는다.
          • UNIQUE하다.
          • 변하면 안된다.
        • 기본키 선택 전략
          • 자연키
            • 비지니스에 의미가 있는 키
            • 주민등록번호, 전화번호, 이메일
          • 대리키
            • 시퀀스, 시리얼, 키생성 테이블
        • 영한 센세는 자연키보다는 대리키를 권장한다.
          • 이유는…
            • 예를들면 전화번호는 유일하지만 변경 가능성이 있고, 주민등록번호조차 여러가지 이유로 변경될 수 있다.
            • JPA는 모든 엔티티에 일관된 방식으로 대리키 사용을 권장한다.
  • Chapter 5

    • 연관 관계 매핑의 핵심 키워드
      • 방향
        • 방향에는 단방향, 양방향이 있다.
      • 다중성
        • 다대일, 일대다, 일대일, 다대다 다중성이 있다
      • 연관 관계의 주인
        • 객체는 양방향 연관관계로 만들면 연관관계의 주인을 정해야 한다.
    • 단방향 연관 관계
      • Member - Team은 다대일 관계이다.
      • 객체 연관 관계
        • 회원과 팀은 단방향 연관 관계이다.
        • Member은 Team필드를 통해 팀을 알지만 Team은 Member을 알 수 없다.
      • 테이블 연관 관계
        • 하지만 테이블 연관 관계에서는 FK인 TEAM_ID를 통해 회원과 팀은 양방향으로 접근가능한 양방향 관계를 맺는다.
      • 객체 연관 관계와 테이블 연관 관계의 가장 큰 차이점
        • 객체의 참조를 통한 연관관계는 언제나 단방향이다.
        • 양방향으로 만들기 위해서는 반대쪽 필드에도 참조를 추가해줘야한다.
          • 이렇게 양쪽을 서로 참조하는 것을 양방향 연관관계라고 한다.
          • 하지만 정확히는 서로 다른 단방향 관계 2개이다.
      • 객체 연관 관계 vs 테이블 연관 관계
        • 객체는 참조를 통해 연관 관계를 맺는다.
        • 테이블은 PK로 연관 관계를 맺는다.
        • 이 두 특징은 비슷해보이지만 다른 특징을 가진다.
        • 참조는 단방향, 외래키는 양방향 연관 관계
    • 순수한 객체 연관 관계
      • 객체 참조를 통해 연관 관계를 탐색할 수 있는데 이것을 객체 그래프 탐색이라고 한다.
    • 테이블 연관 관계
      • 데이터베이스는 외래키를 통해 연관 관계를 탐색 할 수 있다.
    • 객체 관계 매핑
      • JPA를 통한 객체 관계 매핑
  • Chapter 6

    • 다양한 연관관계 매핑
      • 엔티티의 연관관계에서는 다중성과 방향을 고려해야 한다.
        • 엔티티 간의 관계가 1:1, 1:N인지 고려하고
        • 엔티티 간의 참조하는 방향이 단방향인지 양방향인지 고려해야 한다.
      • 다중성
        • N:1 @ManyToOne
        • 1:N @OneToMany
        • 1:1 @OneToOne
        • N:M @ManyToMany
        • 실무에서는 보통 다대일, 일대다 관계를 가장 많이 사용 다대다 관계는 실무에서 사용하지 않는다
      • 단방향, 양방향
        • 데이터베이스의 테이블 관점에서는 외래 키FK 하나로 양방향 쿼리가 가능하다.
        • 반면 객체는 참조용 필드를 가지고 있는 객체만 연관된 객체를 조회할 수 있다.
          • 한쪽만 참조하는 것을 단방향, 양쪽 전부 참조하는 것을 양방향 관계라고 한다.
      • 연관관계의 주인
        • 연관관계를 관리하는 것은 외래키FK이다.
        • 보통 외래키를 가진 엔티티가 관리하기 효율적이므로 연관관계 주인으로 선택된다.
          • 연관관계 주인은 mappedBy속성을 사용하지 않는다.
            • 단방향 연관관계에서는 주인이 명확하기때문에 필요없다.
            • 양방향 연관관계에서는 필요하다.
      • 다대일
        • 다대일 관계의 반대 방형은 일대다 관계이다.
        • 데이터베이스 관점에서 테이블의 일, 다 관계에서 외래키는 항상 다쪽에 있다.
          • 따라서 객체 양방향 관계에서 연관관계의 주인은 항상 다쪽이다.
        • 다대일 단방향
          • ex) Member - Team 객체의 관계
        • 다대일 양방향
          • 양방향은 외래키가 있는 쪽이 연관관계의 주인이다.
          • 양방향은 항상 서로를 참조해야 한다.
            • 양쪽에 다 작성할 경우 무한루프에 빠지므로 조심해야한다.
      • 일대다
        • 일대다 관계는 엔티티를 하나 이상 참조할 수 있으므로 자바 컬렉션 중에 하나를 사용해야 한다.
          • 일대다 단방향
            • 한쪽은 참조하지만 다른 쪽이 참조하지않으면 둘의 관계는 단방향이다.
            • 단방향 관계를 매핑할 때는 @JoinColumn을 명시해야한다.
            • 일대다 단방향 매핑의 단점
              • 본인 테이블에 FK가 있으면 저장과 연관관계 처리를 INSERT 한번으로 끝낼 수 있지만, 다른 테이블에 있다면 연관관계 처리를 위해 UPDATE를 추가로 실행해야 함
              • 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자!!
          • 일대다 양방향
            • 일대다 양방향 매핑은 존재하지 않는다.
            • 대신 다대일 양방향 매핑을 사용해야 한다.
            • 양방향 매핑에서 @OneToMany는 연관관계의 주인이 될 수 없다 → 다대일 관계에서는 항상 다 쪽에 FK가 있다. ⇒ 따라서 연관관계 주인은 @ManyToOne을 사용하는 다 쪽이고, 여기에는 mappedBy 속성이 없다.
      • 일대일
        • 일대일 관계는 양쪽이 서로 하나의 관계만 가진다 → 따라서 주 테이블, 대상 테이블 상관없이 FK를 가진다.
        • 그러면 누가 PK를 가질지만 정하면된다.
        • 우리는 주테이블에 외래 키를 두는 것이 좋을 것이다.
          • JPA를 통해 주테이블에 외래 키를 편리하게 매핑할 수 있기 때문
          • 그러면… @OneToOne을 사용하고, 참조되는 쪽에는 mappedby속성을 추가하면 됨
      • 다대다
        • RDB에서는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.
        • 그래서 일대다-다대일로 관계를 풀어 낸다
        • 객체는 컬렉션을 사용해 다대다 관계를 만들 수 있다. @ManyToMany를 통해 다대다 관계를 편리하게 매핑할 수 있다.
          • 하지만 테이블은 불가능하다.
        • 다대다 양방향
          • @ManyToMany를 통해 다대다 관계를 편리하게 매핑할 수 있지만, 결국에는 엔티티를 하나 더 만들어 @OneToMany, @ManyToOne으로 풀어 사용해야한다.
            • 실무에서는 컬럼을 추가하고, 약간의 변형이 필요하기 때문이다.
              • Member-Order-Product이런 식으로
  • Chapter 7

    • 프록시와 연관관계 관리
      • 프록시
        • 엔티티를 조회할 때 연관된 엔티티들이 항상 사용되는 것이 아니다.
        • Member-Team이 연관된 상태에서 memberId로 조회할때
          • 만약 member정보만 필요한 상태에서 memberId를 통해 Team까지 조회하는 것은 비효율적일 뿐만아니라 조회된 불필요한 데이터들이 사용되지도 않는다.
          • 따라서, JPA에서는 Team이라는 엔티티가 사용될때까지 데이터베이스에서 조회를 미룬다.
          • 이걸 지연로딩이라고 한다.
        • 그리고 지연로딩을 구현하기 위해서 JPA는 가짜객체인 프록시 객체를 갖고온다.
      • 프록시의 특징
        • 프록시 클래스는 실제 클래스를 상속 받아서 만들어지므로 실제 클래스와 겉 모양이 같다.
        • 사용하는 입장에서는 해당 객체가 진짜인지 프록시인지 구분하지 않고 사용 가능
          • 프록시 객체는 실제 객체에 대한 참조를 보관한다.
      • 프록시 객체의 초기화
        • 데이터베이스를 조회해서 실제 엔티티 객체를 생성하는것을 프록시 객체의 초기화라 한다.
        • 프록시 객체는 처음 사용할 때 한 번만 초기화된다.
        • 프록시 객체를 초기화해도 실제 엔티티로 바뀌는 것은 아니다
        • 프록시 객체는 원본 엔티티를 상속받은 객체이므로 타입 체크 시에 주의해서 사용해야 한다.
      • 프록시와 식별자
        • 엔티티를 프록시로 조회할 때 식별자 값을 파라미터로 전달하는데 프록시 객체는 이 식별자 값을 보관한다.
        • 연관관계를 설정할 때는 식별자 값만 사용하므로 프록시를 사용하면 데이터베이스 접근 횟수를 줄일 수 있다
      • 프록시 확인
        • JPA가 제곡하는 .isLoaded()메서드를 사용하면 프록시 인스턴스의 초기화 여부를 확인할 수 있다.
      • 즉시 로딩과 지연 로딩
        • 즉시 로딩
          • 엔티티를 조회할 때 연관된 엔티티도 함께 조회한다.
          • 대부분 JPA 구현체는 즉시로딩을 최적화 하기 위해 가능하면 조인 쿼리를 사용한다.
        • 지연 로딩
          • 연관된 엔티티를 실제 사용할 때 조회한다.
          • 프록시 객체를 통해 데이터가 실제 사용될 때까지 데이터 로딩을 미룬다.
        • JPA 기본 패치 전략
          • 연관된 객체간의 사용빈도에 따라 로딩 방법을 나눌 수 있다. (연관된 두 객체가 자주 사용되면, 즉시 로딩-가끔 사용되면 지연 로딩)
          • 객체의 연관된 엔티티가 하나면 즉시 로딩, 컬렉션이면 지연 로딩을 사용한다.
            • 컬렉션을 로딩하는 것은 비용이 크기 때문
        • 컬렉션의 로딩
          • FetchType.EAGER 사용 시 주의점
            • 컬렉션을 하나 이상 즉시 로딩하는 것은 권장하지 않는다.
            • 서로 다른 컬렉션이 조인되면서 N*M이 되면서 앱 성능을 저하 시킬수 있기때문
            • 컬렉션 즉시 로딩은 항상 OUTER JOIN을 사용한다.
            • JPA는 일대다 관계를 즉시 로딩할 때 항상 외부조인을 사용한다.
      • 프록시와 컬렉션 래퍼
        • 엔티티를 지연 로딩하면 프록시 객체를 사용해서 지연 로딩을 수행하지만 컬렉션은 컬렉션 래퍼가 지연 로딩을 처리해준다.
    • 영속성 전이 : CASCADE
      • 특정 엔티티와 연관된 엔티티 함께 영속 상태로 만들고 싶으면 영속성 전이 기능을 사용하면 된다.
      • JPA에서는 CASCADE 옵션으로 영속성 전이를 제공한다.
      • 영속성 전이 : 저장
        • 영속성 전이는 연관관계를 매핑하는 것과는 관련이 없다.
      • 영속성 전이 : 삭제
        • CascadeType.REMOVE로 설정하고 부모 엔티티를 삭제하면 연관된 자식 엔티티도 함께 삭제된다.
          • 따라서 부모 엔티티를 삭제하면 자동으로 DELETE SQL을 3번 실행하여 연관된 자식을 모두 삭제한다.
      • CASCADE의 종류
        • ALL, PERSIST, MERGE, REMOVE, REFRESH, DETACH등이 있다.
      • 고아 객체
        • JPA는 부모 엔티티와 연관관계가 끊긴 자식 엔티티를 자동 삭제하는 기능을 제공한다.
        • 부모 엔티티의 컬렉션에서 자식 엔티티의 참조만 제거하면 고아 객체가 된다.
        • orphanRemoval 옵션으로 인해 컬렉션에서 엔티티를 제거하면 데이터베이스의 데이터도 삭제된다. → 이를 통해 참조하지 않는 고아객체를 삭제할 수 있다.
      • 영속성 전이 + 고아 객체, 생명 주기
        • 자식을 저장하려면 부모에 등록만 하면 된다.
        • 자식을 삭제하려면 부모에서 삭제하기만 하면 된다.
    • 정리
      • JPA 구현체들은 객체 그래프를 마음껏 탐색할 수 있도록 지원하는데 이때 프록시 기술을 사용한다.
      • 연관된 객체를 즉시 로딩하는 바업ㅂ, 지연 로딩하는 방법이 있다.
      • 객체를 저장하거나 삭제할 때 연관된 객체도 함께 저장하거나 삭제할 수 있다.
      • 또한, 연관관계가 끊어진 고아 객체를 자동으로 삭제하는 기능도 있다.2
  • Chapter 8

    • 값 타입
      • JPA의 데이터 타입 구분
        • 엔티티 타입
          • 엔티티 타입은 @Entity로 정의하는 객체
        • 값 타입
          • 값 타입은 int, Integer, String같은 자바 기본 타입이나 객체
          • 값 타입 구분
            • 기본 값 타입
              • 자바 기본 타입
              • 패퍼 타입
            • 임베디드 타입(복합 값 타입)
              • 임베디드 타입은 JPA에서 사용자가 직접 정의한 값 타입이다.
            • 컬렉션 타입
      • 기본값 타입
        • Member엔티티는 id라는 PK 값을 가지고 생명주기도 있다
          • 하지만 Member 엔티티에 name, age같은 속성은 회원 엔티티가 제거되면 같이 제거된다.
      • 임베디드 타입
        • JPA에서는 직접 새로운 값타입을 정의할 수 있다. 그것을 임베디드 타입이라고 한다.
        • 임베디드 타입도 int, String처럼 값 타입이다.
        • 새로 정의한 값 타입(=임베디드 타입)은 재사용 가능성이 높고, 응집도도 높다.
        • 임베디드 타입을 사용하려면 2가지 애노테이션이 필요하다.
          • @Embeddable : 값 타입을 정의하는 곳에 표시
          • @Embedded : 값 타입을 사용하는 곳에 표시
          • 임베디드 타입은 기본 생성자가 필수이다.
        • 테이블 매핑
          • 임베디드 타입과 무관하게 매핑하는 테이블은 같다.
          • 덕분에 객체와 테이블을 아주 세밀하게 매핑하는 것이 가능하다.
        • 연관관계
          • 임베디드 타입은 값 타입을 포함하거나 참조할 수 있다.
        • 임베디드 속성 재정의
          • @AttributeOverride를 사용해서 임베디드 타입을 재정의 할 수 있다.
      • 값 타입과 불변 객체
        • 임베디드 타입을 여러 엔티티에서 공유하면 위험하다.
        • 값만 변경하길 원하지만 참조하고 있는 원치 않는 객체의 데이터도 수정되어 버린다.
        • 그에 대한 근본적인 해결책이 불변 객체이다.
      • 불변 객체
        • 위와 같은 부작용을 해결하기 위한 방법은 객체를 불변하게 만들면 부작용을 원천 차단할 수 있다.
        • 따라서 값 타입은 가능하면 불변 객체로 설계해야 한다.
        • Integer, String은 자바가 제공하는 대표적인 불변 개체이다.
  • JPA를 공부하며 참고할것

    • 외래키가 있는 곳을 연관관계 주인으로 정하라!

      • 외래키가 있는 곳을 연관관계 주인으로 정하지 않으면 다른 테이블이 업데이트 되므로 유지보수가 어렵고, 별도의 업데이트 쿼리가 발생해 성능에도 악영향을 미친다.
    • 엔티티에는 가급적 @Setter를 사용하지 말자!

      • @Setter는 너무 많은 변경 포인트를 만들어내 유지보수를 어렵게한다.
        • @Setter때문에 엔티티의 변경 추적이 어려워진다.
        • 실무에서는 @Setter대신 변경 지점이 명확한 비지니스 매서드를 별도로 만든다.
    • 값타입은 변경 불가능하게 설계하라!

      • 먼저 @Setter를 제거하자
      • 생성자에 값의 초기화를 우임해서 변경 불가능한 클래스를 만들자
        • 이때 기본 생성자를 public , protected로 설정해야 한다. (public 보다는 protected를 사용)
        • 직접 정의한 값 타입은 자바의 기본 타입이 아니라 객체 타입이다.
        • 자바의 기본 타입에 값을 대입하면 값 복사를 하지만
        • 객체 타입은 참조 값을 복사하기 때문에 불변객체로 설계하여 임의의 오류를 막는다.
    • 모든 연관관계는 지연로딩으로 설정하라!

      • 즉시로딩은 예측을 어렵게하여 오류를 일으키고, N + 1문제를 발생시킨다.
      • 따라서 실무에서는 모든 연관관계를 지연로딩으로 설정해야한다. (@OneToOne, @ManyToOne 관계는 기본이 즉시 로딩이므로 .LAZY명시를 필요로한다.)
      • 연관된 엔티티를 함께 조회해야할때는 Fetch join, Entity Graph, BatchSize를 사용한다.
    • 컬렉션은 필드에서 초기화 하라!

      • 컬렉션은 필드에서 초기화하는 것이 안전하다. (null문제)
      @OnetoMany(mappedBy = "feed")private List<Comment> comments = ***new Arraylist<>();*** //엔티티정의에서 초기화
    • API를 만들때는…

      • 엔티티를 외부로 반환하지마라!
        • 엔티티가 수정된다면, API도 변해버린다.
        • DTO를 사용해서 필요없거나 민감한 정보의 노출을 차단하자.
      • 페치 조인으로 쿼리 수를 최적화 하거나 @BatchSize로 최적화
    • JPA의 영속성

      • EntityManagerFactory
        • EntityManagerFactory는 생성하는데 많은데 많은 자원을 소모하기 때문에 싱글톤 패턴으로 애플리케이션 전체에서 공유
        • EntityManagerFactory는 쓰레드들이 동시에 접근해도 안전하다.
      • EntityManager
        • EntityManager는 쓰레드들이 공유하게 되면 동시성 문제가 발생하기때문에 공유해선 안된다.
      • Entity
        • 비영속
          • 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
        • 영속
          • 영속성 컨텍스트에 관리되는 상태
        • 준영속
          • 영속성 컨텍스트에 저장되었다가 분리된 상태
        • 영속성 컨텍스트의 이점
          • 동일성보장, 트랜잭션을 지원하는 쓰기 지연, 변경감지
        • 플러시
          • 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영한다.
          • 커밋 실행 시 자동 실행, 직접 호출, JPQL 쿼리 실생 시 장동 실행으로 플러시 할 수 있다.
    • JPA 페이징과 정렬

      • Page
        • 추가 count 쿼리 결과를 포함
          • page: 현재 페이지, 0부터 시작한다.
          • size: 한 페이지에 노출할 데이터 건수
          • sort: 정렬 조건을 정의한다.
      • List
        • 추가 count 쿼리 없이 결과만 반환
        • Pageable 파라미터를 통해 페이징과 정렬을 적용
        • Sort 파라미터를 통해 정렬만 적용
    • 벌크성 수정 쿼리

      • 벌크성 수정-삭제 쿼리는 @Modifying 어노테이션을 사용한다.
      • @Modifying(clearAutomatically = false(기본값)/true)를 사용해서 영속성 컨텍스트를 초기화해야한다.
        • 위 옵션없이 findbyId로 다시 조회하면 영속성 컨텍스트에 과거 값이 남아서 문제가 될 수 있다.
      • 벌크성 연산을 할때는…
        • 영속성 컨텍스트에 엔티티가 없는 상태에서 벌크 연산을 먼저 수행
        • 영속성 컨텍스트에 엔티티가 있는 상태에서 벌크 연산을 수행하면 수행 직후 영속성 컨텍스트를 초기화
    • @EntityGraph

      • JPQL 없이 페치 조인을 사용할 수 있다
      • 사실상 페치 조인의 간편 버전이다.
      • LEFT OUTER JOIN을 사용한다.
    • 연관 관계

      • 테이블은 연관관계를 외래키를 통해 찾고, 객체는 참조를 통해 찾는다.
      • 따라서 테이블과 객체는 간극이 존재한다.
      • 객체의 연관관계
        • Member → Feed (단방향)
        • Feed → Member (단방향) 조합으로 양방향처럼 보이게 만든다
      • 테이블의 연관관계
        • Member ↔︎ Feed (양방향)
      • 객체는 단방향 2개를 양방향처럼 보이게한다. 하지만 이는 단방향 2개이다.
      • 테이블은 외래키 하나로 두 테이블의 연관관계를 관리한다.
      • 따라서 관계를 갖는 객체 중 하나는 외래키를 관리해야한다.
      • 연관관계의 주인
        • 관계를 갖는 객체 중 하나를 연관관계의 주인으로 지정
        • 주인은 등록, 수정과 같은 관리가 가능하다.
        • 주인이 아닌 쪽은 Read만 가능하다.
        • 주인이 아닌 쪽은 mappedBy속성 사용
        • 외래키가 있는 곳을 객체의 주인으로 정해라
    • 프록시 엔티티

      • 실제 클래스를 상속 받아서 만들어지기 때문에 타입이나 특징이 같다.
      • 프록시 객체를 호출하면 프록시 객체는 실제 객체의 매서드 호출
      • 프록시 객체는 처음 사용할 때 한번만 초기화한다.
      • 지연 로딩시 프록시로 조회한다.
        • 실무에서는 지연로딩만 사용한다.
        • 즉시 로딩은 예상치 못한 SQL을 발생시키고, JPQL에서 N + 1 문제를 일으킨다.
    • 영속성 전이

      • CASCADE 타입을 통해 연관된 객체를 관리할 수 있다.
      • 예를 들면
        • 고아 객체
          • 부모 엔티티와 연관관계가 끊어진 자식엔티티
          • orphanRemoval = true로 사용하면 자동으로 삭제
        • CascadeType.ALL + orphanRemoval = true 두 옵션을 사용하면
          • 부모 엔티티를 통해서 자식의 생명주기를 관리할 수 있음
    • JPA의 데이터 타입 분류

      • 엔티티 타입
        • @Entity로 정의하는 객체이다.
        • 데이터가 변해도 식별자로 추적할 수 있다.
      • 값 타입
        • Integer, String처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체
        • 식별자가 없고 값만 있으므로 변경 시 추적이 불가능하다.
        • 값 타입 분류
          • 기본값 타입
            • 자바 기본 타입 : int, double
            • 래퍼 클래서 : Integer, Long
            • String
          • 임베디드 타입
            • 직접 정의한 값 타입을 JPA에서는 임베디드 타입이라고 함
            • 주로 기본 값 타입을 모아서 만들어서 복합 값 타입이라고도 함
              • @Embeddable: 값 타입을 정의하느 곳에 표시
              • @Embedded: 값 타입을 사용하는 곳에 표시
            • 기본 생성자 필수
            • 임베디드 타입의 장점
              • 재사용, 높은 응집도
            • 값 타입의 실제 인스턴스인 값을 공유하는 것은 위험하다
            • 대신 값을 복사해서 사용한다.
            • 따라서 불변객체로 만들어 수정할 수 없게 만들면 부작용을 차단할 수 있다.
    • JPQL (JAVA PERSISTENCE QUERY LANGUAGE)

      • 테이블이 아닌 객체를 대상으로 질의하는 객체 지향 쿼리이다.
      • SQL을 추상화해서 데이터베이스의 SQL에 의존하지 않는다.
      • 문법
        • 엔티티와 속성은 대소문자를 구분한다.
        • JPQL 키워드는 대소문자를 구분하지 않는다.
        • 엔티티 이름을 사용한다. (테이블 이름은 사용하지 않는다.)
        • 별칭은 선택이 아닌 필수이다.
        • 프로젝션
          • SELECT절을 통해 조회할 대상을 지정하는 것
        • 조인
          • 내부, 외부, 세타조인이 있다.

          • Fetch Join (페치 조인)

            • SQL 조인 종류 X
            • JPQL에서 성능 최적화를 위해 제공하는 기능
            • 연관된 엔티티나 컬렉션을 SQL 한번에 조회하는 기능
          • Entity Fetch Join

            • 회원을 조회하면서 연관된 팀도 함께 조회
            //JPQLselect m from Member m join fetch m.team//SQLSELECT M.*, T.* FROM MEMBER M
            INNER JOIN TEAM T ON M>TEAM_ID = T.ID
            • Fetch Join과 일반 Join의 차이점
              • 일반 조인은 실행시 연관된 엔티티를 함께 조회하지 않음
              • SELECT절에 지정한 엔티티만 조회할 뿐
              • 페치 조인을 사용할 때만 연관된 엔티티도 함께 조회(객체 그래프를 SQL 한번에 조회하는 개념)
              • Fetch Join의 특징과 한계
                • 둘 이상의 컬렉션은 페치 조인을 할 수 없다.
                • 컬렉션을 페치 조인하면 페이징을 사용할 수 없다.
                • 연관된 엔티티를 SQL한번에 조회하여 성능 최적화
                • 실무에서 글로벌 로딩 전략은 항상 지연로딩한다.
    • 벌크 연산 주의

      • 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리
        • 벌크 연산을 먼저 실행
        • 벌크 연산 수행 후 영속성 컨텍스트 초기화

About

ZeroZoa의 스프링 JPA 공부 기록입니다.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors