티스토리 뷰

728x90
반응형

 

 

자바 ORM 표준 JPA 프로그래밍 - 기본편

김영한님 강의듣고 정리하기

 

1. 다양한 연관관계 매핑

연관관계 매핑시 고려사항 3가지

  • 다중성
    • 다대일 : @ManyToOne
    • 일대다 : @OneToMany
    • 일대일 : @OneToOne
    • 다대다 : @ManyToMany
  • 단방향, 양방향
    • 테이블 : 외래키 하나로 양쪽 조인 가능, 사실 방향이라는 개념이 없음
    • 객체 : 한쪽만 참조하면 단방향, 양쪽이 서로 참조하면 양방향
  • 연관관계의 주인
    • 연관관계의 주인 : 외래키를 관리하는 참조
    • 주인의 반대편 : 외래키에 영향을 주지않음, 단순조회만 가능

 

다대일 [N:1]

  • 다대일 단방향 - 가장 많이 사용하는 연관관계

  • 다대일 양방향 - 외래키가 있는 쪽이 연관관계의 주인, 양쪽을 서로 참조하도록 개발

 

 

일대다 [1:N]

  • 일대다 단방향
    • 일(1)이 연관관계의 주인
    • 테이블에서는 일대다 관계는 항상 다(N) 쪽에 외래키가 있음
    • 객체와 테이블의 차이 발생, JoinColumn을 꼭 사용해야함 (그렇지 않으면 중간에 테이블을 하나 추가해서 사용한다.)
    • 엔티티가 관리하는 외래키가 다른 테이블에 있으므로 연관관계 관리를 위해 추가로 UPDATE SQL 실행, 일대다 매핑 보다는 다대일 양방향 매핑을 사용하자

  • 일대다 양방향
    • 이런 매핑은 공식적으로 존재 X
    • @JoinColumn(insertable = false, updateable = false) , 읽기전용 필드를 사용해서 양방향 처럼 사용하는 방법
    • 다대일 양방향을 사용하자

 

일대일 [1:1]

일대일 관계는 그 반대도 일대일

주 테이블 (둘중에 더 자주쓰는 테이블)이나 대상 테이블 중에 외래키 선택 가능

외래키에 데이터베이스 유니크(UNI) 제약조건 추가

 

  • 일대일 : 주 테이블에 외래키 단방향
    • 다대일 단방향 매핑과 유사 (외래키에 UNI키만 추가)

 

  • 일대일 : 주 테이블에 외래키 양방향
    • 다대일 양방향 매핑처럼 외래키가 있는곳이 연관관계의 주인, 반대편은 mappedBy 적용

 

  • 일대일 : 대상 테이블에 외래키 단방향
    • 대상 테이블에 단방향 관계는 JPA에서 지원 X

 

  • 일대일 : 대상 테이블에 외래키 양방향
    • 일대일 주테이블에 외래키 양방향과 매핑 방법은 같다.

 

일대일 정리

  • 주 테이블에 외래키 (많이씀)
    • 장점 : 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
    • 단점 : 값이 없으면 외래키에 null 허용
  • 대상 테이블에 외래키
    • 장점 : 주 테이블과 대상 테이블에 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지
    • 단점 : 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩된다.

 

 

다대다 [N:M]

관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.

연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야함

하지만 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계가 가능하다.

 

 

 

@ManyToMany를 사용하면 주문시간, 수량 같은 데이터가 들어올 수 있음

편리해 보이지만 실무에서 사용 X

 

 

다대다 한계 극복

  • 연결 테이블용 엔티티 추가 (연결 테이블을 엔티티로 승격)
  • @ManyToMany => @OneToMany, @ManyToOne 
    • 테이블에 중간 테이블이 있는것처럼 객체에서도 중간 엔티티를 사용해 ManyToMany를 풀어서 사용해야한다.
    • PK키는 위에 그림처럼 같이사용 해도 되지만 테이블 유연성을 고려해 ORDER_ID 같은 PK를 따로 만들어주는게 편리하다고 함

 

@JoinColumn

외래키를 매핑할 때 사용

 

referencedColumnName은 참조할때 기본키 말고 다른 값을 참조하고 싶을때 사용하면된다.

 

 

 

2. 고급매핑

 

상속관계 매핑

관계형 데이터베이스는 상속 관계 X

슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사

 

상속관계 매핑 : 객체의 상속 구조와 DB의 슈퍼타입 서브타입 관계를 매핑

상속관계 매핑할때 부모 클래스는 독단적으로 사용 할 일이 없으므로 abstract 추상클래스로 선언하는게 좋다.

 

 

주요 어노테이션

  • 상속관계 매핑 어노테이션은 @Inheritance(strategy = InheritanceType.XXX)로 3가지 전략이 존재한다.
    • JOINED : 조인 전략
    • SINGLE_TABLE : 단일 테이블 전략
    • TABLE_PER_CLASS : 구현 클래스마다 테이블 전략
  • @DiscriminatorColumn(name="DTYPE") : 부모 엔티티에 붙여준다, 어느 자식의 값이 들어온건지 알 수 있다.
  • @DiscriminatorValue("XXX") : 자식 엔티티에 붙여주고 부모엔티티 DiscriminatorColumn(name="DTYPE")에 들어갈 이름을 정의할 수 있다.

 

조인 전략

장점

  • 테이블 정규화
  • 외래키 참조 무결성 제약조건 활용가능
  • 저장공간 효율화

단점

  • 조회시 조인을 많이 사용, 성능 저하
  • 조회 쿼리가 복잡함
  • 데이터 저장시 INSERT SQL 2번 호출

 

단일테이블 전략

장점

  • 조인이 필요 없으므로 일반적으로 조회 성능이 빠르다.
  • 조회 쿼리가 단순함

단점

  • 자식 엔티티가 매핑한 컬럼은 모두 null 허용
  • 단일 테이블에 모든것을 저장하므로 테이블이 커질 수 있다. 상황에 따라서 조회 성능이 오히려 느려질 수 있다.

 

구현 클래스마다 테이블 전략

이 전략은 데이터베이스 설계자와 ORM 전문가 둘 다 추천 X

장점

  • 서브 타입을 명확하게 구분해서 처리할때 효과적
  • not null 제약조건 사용가능

단점

  • 여러 자식 테이블을 함께 조회할 때 성능이 느림(UNION SQL 필요)
  • 자식 테이블을 통합해서 쿼리하기 어려움

 

@MappedSuperclass

공통 매핑 정보가 필요할 때 사용 (DB는 바뀌지 않는데 객체만 중복되는 것을 줄이기 위해 사용해준다.)

 

  • 이 어노테이션은 상속관계 매핑이 아니고 엔티티도 아니고 테이블과 매핑이 되지도 않는다. 테이블과 관계없고, 단순히 엔티티가 공통으로 사용하는 매핑정보를 모으는 역할
  • 조회, 검색 불가, 직접 생성해서 사용할 일이 없으므로 추상 클래스 권장
  • 주로 등록일, 수정일, 등록자, 수정자 같은 전체 엔티티에서 공통으로 사용하는 정보를 모을 때 사용
  • 참고 : @Entity 클래스는 @Entity나 @MappedSuperclass로 지정한 클래스만 상속 가능

 

 

3. 프록시와 연관관계 관리

 

프록시 기초

  • em.find() vs em.getReference()
  • em.find() : 데이터베이스를 통해서 실제 엔티티 객체 조회
  • em.getReference() : 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회

 

프록시 객체의 초기화

프록시에 실제 객체의 값이 없을경우 영속성 컨텍스트를 통해서 실제 객체를 찾아 연결한다.

프록시의 특징

  • 프록시 객체는 처음 사용할 때 한 번만 초기화
  • 프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는 것은 아님, 초기화 되면 프록시 객체를 통해서 실제 엔티티에 접근가능
  • 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티 반환

 

프록시 주의 사항

  • 프록시 객체는 원본 엔티티를 상속받음, 따라서 타입 체크시 주의해야함 (== 비교하지 말고, instance of 사용)
  • 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때, 프록시를 초기화하면 문제발생

 

즉시로딩과 지연로딩

 

member를 조회할 때 연관관계인 Team을 많이 사용한다면

즉시로딩(Eager)을 사용하여 member를 조회할때 Team도 같이 들어오도록 쿼리를 보낸다.

 

member를 조회할 때 연관관계인 Team을 거의 사용하지 않는다면

지연로딩(Lazy)으로 값이 필요할떄만 쿼리가 나가도록 하고 값을 찾기전에는 Team은 프록시로 받아온다.

 

지연로딩

지연로딩(LAZY)를 사용하면 team을 프록시로 조회하고 실제로 team을 사용하는 시점에 초기화(DB 조회)를 한다.

@Entity
public class Member {
  
  @Id
  @GeneratedValue
  private Long id;
  
  @Column(name = "USERNAME")
  private String name;
  
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "TEAM_ID")
  private Team team;
}

 

즉시로딩

member를 조회할때 연관관계인 team도 함께 조인해서 같이 조회한다.

@Entity
public class Member {
  
  @Id
  @GeneratedValue
  private Long id;
  
  @Column(name = "USERNAME")
  private String name;
  
  @ManyToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "TEAM_ID")
  private Team team;
}

 

즉시로딩 주의사항

  • 가급적 지연 로밍만 사용 (특히 실무에서)
  • 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생
  • 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다.
  • @ManyToOne, @OneToOne은 기본이 즉시로딩(EAGER) -> 지연로딩(LAZY)으로 설정
  • @OneToMany, @ManyToMany는 기본이 지연로딩

 

영속성 전이 : CASCADE

특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을때 사용한다.

(부모 엔티티를 저장할 때 자식 엔티티도 함께 저장)

CASCADE 주의사항

  • 영속성 전이는 연관관계를 매핑하는 것과 아무관련이 없다.
  • 엔티티를 영속화할 때 연관된 엔티티도 함께 영속화 하는 편리함을 제공할 뿐이다.

 

CASCADE의 종류

  • ALL : 모두 적용
  • PERSIST : 영속
  • REMOVE : 삭제
  • MERGE : 병합
  • REFRESH : REFRESH
  • DETACH : DETACH

 

고아 객체

고아 객체 제거 : 부모엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제

orhanRemoval = true를 붙여주면 된다.

 

고아객체 주의사항

  • 참조하는 곳이 하나일 때 사용해야한다.
  • 특정 엔티티가 개인 소유할 때 사용
  • @OneToOne, @OneToMany만 가능
  • 개념적으로 부모를 제거하면 자식은 고아가 된다. 따라서 고아 객체 제거 기능을 활성화 하면, 부모를 제거할 때 자식도 함께 제거된다. 이것은 CascadeType.REMOVE 처럼 동작한다.

 

영속성 전이 + 고아객체

  • CascadeType.ALL + orphanRemovel = true
  • 스스로 생명주기를 관리하는 엔티티는 em.persist()로 영속화, em.remove()로 제거
  • 두 옵션을 모두 활성화 하면 부모 엔티티를 통해서 자식의 생명주기를 관리 할 수 있다.
  • 도메인 주도 설계(DDD)의 Aggregate Root 개념을 구현할 때 유용

 

 

 

 

Reference


www.inflearn.com/course/ORM-JPA-Basic/dashboard

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., 본 강의는 자바 백엔

www.inflearn.com

 

 

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30