SEB_BE 50일차 - JPA 기반 데이터 액세스 계층2

subimm_·2022년 11월 2일
0

코드스테이츠

목록 보기
50/83

💡 오늘의 학습목표

  • 엔티티 매핑
  • 엔티티 간의 연관 관계 매핑

📔 엔티티 매핑

  • 단일 엔티티 매핑

📖 엔티티와 테이블 간의 매핑

  • @Entity 매핑 애너테이션을 이용해 엔티티 클래스와 테이블 매핑
    JPA 관리 대상 엔티티가 됨.

@Entity 애너테이션

  • 애트리뷰트
    • name : 엔티티 이름 설정, 설정하지 않으면 기본값으로 클래스 이름을 엔티티 이름으로 사용

@Table 애너테이션

  • 애트리뷰트
    • name : 테이블 이름 설정, 설정하지 않으면 기본값으로 클래스 이름을 테이블 이름으로 사용
    • @Table 애너테이션은 옵션, 추가하지 않을 경우 클래스 이름을 테이블 이름으로 사용
    • 테이블 이름이 클래스 이름과 달라야 할 경우에 추가

📖 기본키 매핑

  • JPA에서 지원하는 기본키 생성 전략
    • 기본키 직접 할당
    • 기본키 자동 생성
      • IDENTITY : 기본키 생성을 데이터 베이스에 위임 (대표적 AUTO_INCREMENT 기능을 통해)
      • SEQUENCE : 데이터베이스에서 제공하는 시퀀스를 사용
      • TABLE : 별도의 키 생성 테이블 사용 ( 성능면에서 좋지 않다 )

기본키 직접 할당 전략

  • @Id 애너테이션 추가로 기본키 직접 할당
  • 기본키를 직접 할당해서 엔티티 저장

IDENTITY 전략 (MySQL)

  • @GeneratedValue 애너테이션의 strategy 애트리뷰트의 값을 IDNETITY로 지정
  • 별도의 기본키 값을 할당해주지 않음

  • MEMBER 테이블에 데이터를 저장하고 기본키 값이 자동으로 생성됨.

SEQUENCE 전략(Oracle)

  • GenerationType을 SEQUENCE로 지정

  • 데이터베이스에서 시퀀스 생성
    Member 엔티티를 영속성 컨텍스트에 저장하기 전에 데이터베이스에서 시퀀스 값 조회

AUTO 전략

  • GenerationType.AUTO로 지정하면 JPA가 데이터베이스의 Dialect에 따라서 전략을 자동 선택

📖 필드(멤버 변수)와 컬럼 간의 매핑

Member 엔티티 클래스 필드와 컬럼 간의 매핑

  • (1) @Column 애넡이션은 필드와 컬럼을 매핑해주는 애너테이션, 만약 이 애너테이션이 없고 필드만 정의되어 있다면 JPA는 기본적으로 이 필드가 테이블의 컬럼과 매핑되는 필드라고 간주
    (애트리뷰트의 값은 디폴트 값이 모두 적용)

    • nullable
      • 컬럼에 null값 허용 여부 지정
      • 디폴트 값은 true
    • updatable
      • 컬럼 데이터를 수정할 수 있는지 여부
      • 디폴트 값은 true
    • unique
      하나의 컬럼에 unique 제약 조건 설정
      디폴트 값은 false
      • @Column 애너테이션이 생략되었거나 애트리뷰트 기본값 사용시 주의
        필드의 데이터 타입이 int나long 같은 원시 타입이면 null값 입력 불가
        원시 타입 필드에서 최소 nullable = false 설정
  • 테스트

  • (1) 메서드는 email 필드에 아무 값도 입력하지 않고 데이터 저장
    nullable=false 기 때문에 에러 발생

  • (2) 메서드는 이미 등록한 email 주소를 다시 수정
    updatable=false 기 때문에 주소가 수정되지 않아야 함.

  • (3) 메서드는 이미 등록된 email 주소를 한번 더 등록
    unique=true 이기 때문에 에러 발생

    API 계층의 GlobalExceptionAdvice 에서 캐치 후 처리가능

  • Member 클래스 엔티티 매핑

  • (1) @Column 애너테이션 애트리 뷰트

    • length
      • 컬럼에 저장할 수 있는 문자 길이 지정
      • 디폴트 값은 255
  • (2) 회원 정보가 등록 될 때의 시간 및 날짜를 매핑하기 위한 필드

    • LocalDateTime 타입일 경우 @Temporal 애너테이션 생략 가능
    • 컬럼의 TIMESTAMP 타입과 매핑됨.
  • (3) 별도의 이름 지정하여 다른 이름으로 컬럼 생성 가능

  • (4) @Transient` 애너테이션을 필드에 추가하면 테이블 컬럼과 매핑하지 않겠다는 의미

    • 데이터베이스에 저장x, 조회할 때도 매핑되지 않음
    • 주로 임시 데이터를 메모리에서 사용하기 위한 용도
  • Order 엔티티 클래스
  • (1) 의 @Enumerated 애너테이션은 enum 타입과 매핑할 때 사용
    • EnumType.ORDINAL : enum의 순서를 나타내는 숫자를 테이블에 저장
    • EnumType.STRING : enum의 이름을 테이블에 저장 (권장)

📜 엔티티와 테이블 매핑 권장 사용 방법

  • 클래스 이름 중복 등의 특별한 이유 없을 시 @Entity@Id 애너테이션만 추가
  • 기본키 생성 전략은 IDENTITY 또는 SEQUENCE 전략을 사용하는 것이 좋다.
  • 엔티티 클래스 필드 타입이 Java원시타입일 경우 @Column 애너테이션에 최소한 nullable = false 설정

📙 엔티티 간의 연관 관계 매핑

  • 단방향 연간 관계 / 양방향 연관 관계
  • 일대다, 다대일, 다대다, 일대일

📖 단방향 연관 관계

  • 한쪽 클래스만 다른 쪽 클래스의 참조 정보를 가지고 있는 관계

📖 양방향 연관 관계

  • 양쪽 클래스가 서로의 참조 정보를 가지고 있는 관계

📖 일대다 단방향 연관 관계

  • 일(1) 에 해당하는 클래스가 다(N)에 해당하는 객체를 참조할 수 있는 관계
    • 한 명의 회원이 여러 건의 주문을 할 수 있으므로 Member와 Order는 일대다 관계
    • 잘 사용하지 않음. ( 양방향 연관 관계를 만들 때 사용 )

📖 다대일 단방향 연관 관계

  • 다 (N) 에 해당하는 클래스가 일(1)에 해당하는 객체를 참조할 수 있는 관계
    • 여러 건의 주문은 한 명의 회원에 속할 수 있으므로 Order와 Member는 다대일 관계

✔ 다대일 연관 관계 매핑 방법

  • 다(N)에 해당하는 Order 클래스
  • (1) @ManyToOne 애너테이션으로 다대일의 관계를 명시
  • (2) @JoinColumn 애너테이션으로 ORDERS 테이블에서 외래키에 해당하는 컬럼명을 적어줌.
    • 일반적으로 부모 테이블에서 기본키로 설정된 컬럼명과 동일하게 외래키 컬럼을 만듬,
      MEMBER 테이블의 기본키 컬럼명이 MEMBER_ID
  • 다(N) 쪽에서만 설정을 해주면 매핑 작업 끝.

  • 테스트
  • (1) 에서 회원 정보 저장
  • 회원 정보의 주문 정보를 저장하기 위해서 (2) 와 같이 order 객체에 member 객체를 추가
    ( order객체에 추가된 member 객체는 외래키 역할을 한다.)
  • (3) 주문 정보 저장
  • (4) 등록한 회원에 해당하는 주문 정보 조회
  • (5) 주문에 해당하는 회원 정보를 가져와서 출력 (객체를 통해 다른 객체의 정보를 얻을 수 있는 것 : 객체 그래프 탐색)

다대일 매핑에 일대다 매핑 추가

  • 다대일 매핑만으로는 member 객체를 통해 내가 주문한 주문 정보인 order 객체를 조회 x

  • 다대일 매핑된 상태에서 일대다 매핑을 추가해 양방향 관계를 만들어 주면 된다.

    • 멤버 클래스
  • (1) 의 @OneToMany(mappedBy = "member") mappedby 지정

    • Order 클래스에서 외래키의 역할을 하는 필드는 member 필드
    • 두 객체들 간에 외래키의 역할을 하는 필드는 무엇인가?
    • 외래키의 역할을 하는 필드는 다(N)에 해당하는 클래스 안에 있다.
  • 테스트 ( 주문 정보 조회 )

  • (1) 에서 member 객체에 order 객체 추가

    • member 객체에 order 객체를 추가해주지 않으면 (5)에서 find 메서드로 조회한 member 객체로 order를 그래프 탐색하면 order 객체 조회 불가
      ( find() 메서드가 1차 캐시에서 member 객체를 조회하는데 (1)에서 order를 추가하지 않으면 1차 캐시에 저장된 member 객체에는 order를 가지고 있지 않기 때문)
  • (2) 에서 order 객체에 member 객체를 추가

    • member가 order의 외래키 역할을 하기 때문에 order객체 저장 시, 반드시 필요

📖 다대다 연관 관계

  • 테이블 설계 시, 다대다 관계는 중간에 테이블을 하나 추가해서 두개의 일대다 관계를 만들어 주는 것이 일반적인 방법
  • 두 개의 다대일 매핑 후 현실적으로 객체 그래프 탐색으로 원하는 객체 조회가 안된다면 그 때 일대다 양방향 매핑 추가

📖 일대일 연관 관계

  • 다대일 단방향 연관 관계와 매핑 방법 동일
  • OneToOne 애너테이션 사용
  • 일대일 단방향 매핑에 양방향 매핑을 추가하는 방법도 다대일에 일대다 매핑을 추가하는 방식과 동일 ( @OneToOne 애너테이션 사용)

📜 엔티티 간의 연관 관계 매핑 권장

  • 일대다 매핑은 사용하지 않는다.
  • 제일 먼저 다대일 단방향 매핑부터 적용
  • 다대일 단방향 매핑을 통해 객체 그래프 탐색으로 조회할 수 없는 정보가 있다면, 그 때 양방향 매핑 적용
profile
코린이의 공부 일지

0개의 댓글