• EntityManager
    • JPA (Java Persistence API)에서 제공하는 핵심 인터페이스
    • 엔티티 객체와 데이터베이스 간의 상호작용을 관리
    • 주요 기능으로는 엔티티의 생성, 조회, 업데이트, 삭제
  • JPA의 영속성 컨텍스트(persistence context)
    • JPA에서는 EntityManager를 통해 엔티티 객체를 관리
    • EntityManager는 영속성 컨텍스트라는 세션과 같은 캐시를 유지하며, 이 컨텍스트 내의 엔티티는 관리 상태(persisted state)
    • 관리 상태에 있는 엔티티에 대한 변경 사항은 자동으로 데이터베이스에 반영
  • 변경 감지(dirty checking) 메커니즘
    • 더티체킹이라고 불리기도 하는 메커니즘
    • JPA는 트랜잭션이 커밋될 때 영속성 컨텍스트 내의 엔티티를 스캔하여 변경된 엔티티 검색
    • 변경된 엔티티가 감지되면, JPA는 save가 없어도 해당 변경 사항을 데이터베이스에 자동으로 반영
  • SpingDataJpa 메서드 명명규칙
    • findBy<Property>
      • 특정 필드의 값으로 엔티티를 검색. where propety = ?
    • findByNameAndEmail(String name, String email)
      • and 조건
    • findByNameOrEmail(String name, String email)
      • or 조건
    • findBy<Property>Between
      • 두 값 사이의 범위로 조회
      • findByAgeBetween(int start, int end)
    • findBy<Property>LessThan
      • 주어진 값보다 작은 값을 가진 엔티티를 조회
      • findByAgeLessThan(int age)
    • findBy<Property>GreaterThan
    • findBy<Property>IsNull 또는 findBy<Property>IsNotNull
    • findBy<Property>OrderBy<Property>Asc/Desc
      • 전체조회시 orderBy
        • findAllByOrderByDesc
      • 특정 필드에 대한 정렬 기준을 지정
    • Page<Entitiy> findBy<Property>(<PropertyType> value, Pageable pageable)는 페이징 처리를 위한 메서드
  • JPQL문
    • jpa의 객체지향 쿼리문법
    • 장점
      • DB에 따라 문법이 달라지 않는 객체지향언어, spring data jpa에서 사용시 컴파일타임에서도 jpql의 문법 check하고 검증
    • 단점
      • DB고유의 기능과 성능을 극대화하기는 어려움.
    • SELECT
      • 기본 형태: SELECT <projection> FROM <entity> [WHERE <condition>]
      • SELECT m FROM Member m WHERE m.age > 18
      • 엔티티의 특정 필드만 선택하려면, SELECT m.name, m.age FROM Member m 와 같이 사용
    • JOIN
      • SELECT m FROM Member m JOIN m.team
        • inner join
      • SELECT m FROM Member m LEFT JOIN m.team t
        • left join
  • JPA의 Entity 관련 주요 설정정보
    • @OneToMany
      • OneToMany어노테이션은 일대다 관계를 의미
      • mappedBy: 양방향 관계에서, 연관 관계의 주인을 지정.
        • 연관 관계의 주인이란 JPA에서 관계를 맺고 있는 두 엔티티 중 관계를 관리(데이터베이스의 외래 키를 업데이트)하는 책임을 가지는 쪽을 의미
        • "many" 쪽 엔티티의 필드 이름을 값으로 설정
        • 연관 관계의 주인이 Many쪽임에 유의
      • cascade
        • 엔티티 상태 변화(예: 저장, 삭제)를 연관된 엔티티에 전파하는 방식을 지정
        • 부모 엔티티를 삭제할 때 CascadeType.REMOVE 또는 CascadeType.ALL이 설정된 자식 엔티티도 함께 삭제
          • REMOVE, PERSIST등의 옵션도 존재
        • 예를 들어 author객체에 posts객체를 set하여 author객체를 save할 경우 cascade옵션이 설정돼 있으면 post객체에도 save
          • Cascade를 사용하면, 부모 엔티티를 저장할 때 자동으로 연관된 자식 엔티티들도 함께 저장함으로서 코드를 간결하게 만들고, 엔티티 간의 관계를 명확하게 표현
          • 더티체킹과 비교하면 더티체킹은 변경사항에 대해서만 반영하지만 cascade옵션을 통해서는 연관엔티티의 신규 사항 추가 가능
      • fetch
        • "fetch"는 가져오다라는 의미를 가진 단어로서, 엔티티 또는 엔티티의 연관된 컬렉션 및 엔티티를 데이터베이스로부터 어떻게 로드할지 결정하는 전략
        • FetchType.LAZY는 지연 로딩, FetchType.EAGER는 즉시 로딩
          • lazy설정시 엔티티를 참조하지 않는한 자식테이블로 쿼리발생X
            • 참조할 경우에는 N+1이슈가 발생하나, 참조하지 않으면 N+1이슈 발생안함
          • eager설정시 즉시, 상대엔티티를 참조하지 않더라도 자식테이블로 쿼리발생O
            • 즉, N+1 이슈 즉시 발생
          • @OneToMany과 OneToOne은 default설정이 FetchType.LAZY. @ManyToOne은 default가 FetchType.EAGER
    • @ManyToOne
      • @JoinColumn
        • 외래 키 명을 지정할때 사용
        • name 속성으로 외래 키 컬럼의 이름을 지정
        • nullable 속성으로 nullable 또는 not null지정
    • fetch와 N+1문제
      • JPA의 기본사상은, 연관관계에 있는 테이블의 데이터를 먼저 JOIN을 통해 데이터를 한꺼번에 가져 오는 것이 아닌, 추후에 연관 엔티티 참조시에 연관데이터를 조회하는 전략을 취함
      • 이때에 조회하는 방식으로 인해 N+1 문제 발생
        • 예시) 자식 엔티티를 조회하면, 자식 엔티티를 로드하는 1번의 쿼리와 부모엔티티(10개가 있다고 가정) 로드를 위한 10번의 쿼리가 발생하여 총 11번의 쿼리 발생
      • 다수의 쿼리로 인한 성능이슈 해결책으로 jpql의 fetch join 사용
        • fetch join을 통해 연관엔티티를 한꺼번에 가져옴으로서 N+1을 방지
        • 일반 JOIN과의 차이점은 일반 JOIN은 연관된 엔티티(Post 객체 등)를 실제로 로드하지 않는 다는 것
          • 이로 인해 일반 join을 하더라도 select * from post;와 실질적으로 차이가 없는 N+1발생 가능성 존재 다만 아래와 같은 목적으로 사용 가능
            • 일반 JOIN을 사용한 조건부 검색
              • select p from Post p left join p.author
            • fetch JOIN을 사용한 성능 최적화
              • select p from Post p left join fetch p.author