• @Entity - 이 클래스를 테이블과 매핑한다고 Jpa에게 알려준다.

  • @Table - 엔티티클래스에 매핑할 테이블 정보를 알려준다.

  • @Id - 기본 키(primary key)에 매핑한다.

  • @Column - 필드를 칼럼에 매핑

  • @ManyToOne, @JoinColumn - 연관관계 매핑

  • JPA를 사용 시 문제는 검색 쿼리에서 발생

    • 이때 사용되는것이JPQL JPQL은 엔티티객체를 대상으로 쿼리한다(SQL은 데이터베이스 테이블을 대상으로 쿼리한다)

  • 영속성 컨텍스트란?
    • 엔티티를 영구 저장하는 환경
    • 예로 persist()메소드는 엔티티 매니저를 사용해서 회원엔티티를 영속성 컨텍스트에 저장한다.
  • 엔티티 생명주기
    • 비영속 - 영속성 컨텍스트와 관계없는 상태
    • 영속 - 영속성 컨텍스트에 저장된 상태( 영속성 컨텍스트에 의해 관리된다)
    • 준영속 - 영속성 컨텍스트에 저장되어있다가 분리된 상태
    • 삭제 - 삭제된 상태
  • 영속성 컨텍스트 특징
    • 영속 상태는 식별자 값이 반드시 있어야한다.
    • JPA는 트랜잭션에 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영(플러시))
    • 장점
      1. 1차캐시
      2. 동일성 보장
      3. 트랜잭션을 지원하는 쓰기 지연
      4. 변경 감지
      5. 지연 로딩

  • CASCADE - 특정 엔티티를 영속상태로 만들 때 연관된 엔티티도 함꼐 영속 상태로 만들떄 사용
    • 영속성 전이를 사용하면 부모 엔티티를 저장할때 자식엔티티도 함꼐 저장할 수 있다.
    • JPA에서 엔티티를 저장할 떄 연관된 모든 엔티티는 영속상태여야 한다.
    • 예) @OneToMany(mappedBy = “parent”, cascade - CascadeType.PERSIST) - 부모를 영속화 할떄 연관된 자식도 함께 영속
    • 저장한 부모와 자식 엔티티를 모두 제거하려면 각각의 엔티티를 하나씩 제거해야 한다.
    • 예) em.remove(findChild1); / em.remove(findChild2); / em.remove(findChild3); / em.remove(findParent);
    • 만약 CascadeType.REMOVE를 설정하지않고 이코드를 실행하면 부모엔티티만 삭제되는데 부모로우를 삭제하는 순간 자식테이블에 걸려있는 외래키 제약조건을 인해 DB에 외래키 무결성 예외가 발생한다.
  • CASCADE의 종류
    • ALL - 모두 적용
    • PERSIST - 영속
    • MERGE - 병합
    • REMOVE - 삭제
    • REFRESH - REFRESH
    • DETACH - DETACH
  • 고아객체 - JPA 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로삭제하는 기능을 제공한다. 이것을 고아(ORPHAN)객체 제거라 한다.
    • 예) @OneToMany(mappedBy = “parent”, orphanRemoval = true)
    • 부모 엔티티의 컬렉션에서 자식엔티티의 참조만 제거하면 자식엔티티가 자동으로 삭제된다.
    • 고아객체 제거는 참조가 제거된 엔티티는 다른 곳에서 참조하지않는 고아객체로 보고 삭제하는 기능이다.
    • 그래서 orphanRemovla은 @OneToOne, @OneToMany에서만 사용할 수 있다.
  • 영속성 전이 + 고아객체, 생명주기
    • cascadeType.ALL + orphanRemoval = True 를 동시에 사용한다면?
    • 일반적으로 엔티티는 EntityManager.persist()를 통해 영속화 되고 EntityManager.remove()에 의해 제거된다.
    • 엔티티 스스로 생명주기를 관리한다는 뜻이다.
    • 두 옵션을 모두 활성화하면 부모 엔티티를 통해서 자식의 생명주기를 관리할 수 있다.
// 자식을 저장하려면 부모에 등록만 하면된다.(CASCADE)

Parent parent = em.find(Parent.class, parentId);
parent.addChild(child1);

// 자식을 삭제하려면 부모에서 제거하면 된다(orphanRemoval)

Parent parent = em.find(Parent.class, parentId);
parent.getChaldren().remove(removeObject);

  • 영속성 전이는 DDD의 Aggregate Root개념을 구현할 때 사용하면 편하다.

  • 즉시로딩(pre-Loading) - 엔티티를 조회할 떄 연관된 데이터도 함꼐 조회한다.
    • 설정방법 - @ManyToOne(fetch = FetchType.EAGER)
    • JPA는 즉시로딩을 최적화 하기위해 가능하면 조인 쿼리를 사용한다.
  • 지연로딩(lazy-Loading) - 연관된 엔티티를 실제 사용할 떄 조회한다.
    • 설정방법 - @ManyToOne(fetch = FetchType.LAZY)
    • 연관된 엔티티를 프록시로 조회한다.
  • fetch 전략
    • 추천하는 방법은 모든 연관관계에 지연로딩을 사용하는 것이다, 개발중 필요한 곳에만 즉시로딩을 사용하도록 최적화 하는 것이 좋다.
  • FetchType.EAGER 사용 시 주의점
    • 컬렉션을 하나 이상 즉시 로딩하는 것은 권장하지 않는다.
    • 컬렉션 즉시 로딩은 항상 외부조인을 사용한다.

  • NULL 제약 조건과 JPA 조인 전략
    • NULL 값을 허용하면 JPA는 이런 상황을 고려해서 외부조인을 사용한다.
    • 하지만 내부조인이 성능과 최적화에서 더 유리하다, 내부조인을 사용하려면?
    • NOT NULL 제약조건을 설정하면 값이 있는 것을 보장한다, 따리서 이때는 내부조인만 사용해도 된다.
    • @JoinColumn에 nullable = false 설정해서 이 외래 키는 null을 허용하지않는다고 하면 JPA는 내부조인을 사용한다.

    • nullable = true : null 허용(기본값), 외부조인 사용
    • nullable = false : null 허용않음, 내부조인 사용
    • 또는 @ManyToOne.option = false 로 해줘도 내부조인을 사용한다.
    • JPA는 선택전 관계면 외부조인을 사용하고 필수 관계면 내부 조인을 사용한다.

  • 정리
    • @ManyToOne, @OneToOne
      • (optional = false) - 내부조인
      • (optional = true) - 외부조인
    • @OneToMany, @ManyToMany
      • (optional = false) - 외부조인
      • (optional = true) - 외부조인