JPA 엔티티 매핑 & Spring Data JPA

InSeok·2022년 9월 9일
0

TIL

목록 보기
32/51

목차


  1. 엔티티와 테이블간의 매핑
  2. 기본키 매핑
  3. 필드와 컬럼 간의 매핑
  4. 엔티티 간의 연관 관계 매핑
  5. Spring Data Jpa

배운 내용


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

  • @Entity매핑 애너테이션을 이용해 엔티티 클래스와 테이블을 매핑
  • 클래스 레벨에 @Entity애너테이션을 붙이면 JPA 관리 대상 엔티티가 된다.

@Entity

  • 애트리뷰트 - name
    • 엔티티 이름 설정
    • 필수
    • 디폴트로 클래스이름을 엔티티 이름으로 사용

@Table

  • 애트리뷰트 - name

    • 테이블 이름 설정
    • 디폴트로 클래스이름을 테이블 이름으로 사용
    • 옵션이다. 테이블이름이 클래스와 달라야할 경우 사용
  • @Entity애너테이션과 @Id 애너테이션은 필수

  • 파라미터가 없는 기본 생성자필수로 추가 → 없으면 에러 종종 발생

**기본키 매핑**

기본키 생성 전략

기본키 직접 할당

  • 애플리케이션 코드 상에서 기본키를 직접 할당
  • @Id애너테이션 필드에 직접 추가

기본키 자동 생성

  @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // IDENTITY 전략
    private Long memberId;

	@Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)  // SEQUENCE 전략
    private Long memberId;

IDENTITY

  • 기본키 생성을 데이터베이스에 위임하는 전략.
  • MySQL의 AUTO_INCREMENT 기능을 통해 자동 증가 숫자를 기본키로 사용하는 방식이 대표적이다.

SEQUENCE

  • 데이터베이스에서 제공하는 시퀀스를 사용해서 기본키를 생성하는 전략
  • 데이터베이스 시퀀스유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트
  • 엔티티가 영속성 컨텍스트에 저장되기 전에 데이터베이스가 시퀀스에서 기본키에 해당하는 값을 제공

TABLE

  • 별도의 키 생성 테이블을 사용하는 전략

AUTO 전략

  • @GeneratedValue(strategy = GenerationType.AUTO)
  • JPA가 데이터베이스의 Dialect에 따라서 적절한 전략을 자동으로 선택
  • Dialect
    • 표준 SQL 등이 아닌 특정 데이터베이스에 특화된 고유한 기능

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

	// (1)
    @Column(nullable = false, updatable = false, unique = true)
    private String email;

@Column

  • 필드와 컬럼을 매핑해주는 애너테이션
  • @Column애너테이션이 없고, 필드만 정의되어 있다면 JPA는 기본적으로 이 필드가 테이블의 컬럼과 매핑되는 필드라고 간주하고, @Column애너테이션에 사용되는 애트리뷰트의 값은 디폴트 값이 모두 적용된다.
  • 애트리뷰트
    • nullable
      • 디폴트 값은 true
    • updatable
      • 디폴트 값은 true
    • unique
      • unique 유니크 제약 조건을 설정
      • 디폴트 값은 false
    • length
      • 컬럼에 저장할 수 있는 문자 길이를 지정
      • 디폴트 값은 255
  • 시간 및 날짜를 매핑하기위한 필드
    • java.util.Date, java.util.Calendar 타입으로 매핑하기위해서는 @Temporal
      애너테이션을 추가해야하지만, LocalDateTime 타입일 경우, @Temporal 생략가능
    • LocalDateTime은 컬럼의 TIMESTAMP 타입과 매핑

@Transient

  • 애너테이션을 필드에 추가하면 테이블 컬럼과 매핑하지 않겠다는 의미로 JPA가 인식
    • 데이터베이스에 저장도 하지 않고, 조회할 때 역시 매핑되지 않는다.
    • 임시 데이터를 메모리에서 사용하기위한 용도로 사용

@Enumerated

  • enum 타입과 매핑할 때 사용하는 애너테이션

  • EnumType.ORDINAL : enum의 순서를 나타내는 숫자를 테이블에 저장

    • 기존에 정의되어 있는 enum 사이에 새로운 enum 하나가 추가 된다면

      enum 순서 번호와 enum에 정의되어 있는 순서가 일치하지 않게 되는 문제가 발생

  • EnumType.STRING : enum의 이름을 테이블에 저장(권장)

  • 주의사항

    • @Column 애너테이션이 생략된 경우 기본적으로 nullable=true
    • 필드의 데이터 타입이 int, long 같은 Java의 원시 타입이라면 null값을 입력 불가
      • null은 객체 타입일 경우에만 적용
    • Java의 원시 타입 필드는 nullable=false로 설정하자

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

단방향 연관 관계

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

**양방향 연관 관계**

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

JPA는 단방향 연관 관계와 양방향 연관 관계를 모두 지원하는 반면에 Spring Data JDBC는 단방향 연관 관계만 지원

일대다 단방향 연관 관계

  • 일(1)에 해당하는 클래스가 다(N)에 해당하는 객체를 참조할 수 있는 관계
  • 일반적인 테이블 간의 관계를 정상적으로 표현하지 못해 잘 사용하지 않음
  • 다대일 단방향 매핑을 먼저 한 후에 필요한 경우, 일대다 단방향 매핑을 추가해서 양방향 연관 관계를 만드는 것이 일반적입니다.

**다대일 연관 관계**

  • 다(N)에 해당하는 클래스가 일(1)에 해당하는 객체를 참조할 수 있는 관계
  • 테이블 간의 관계처럼 자연스러운 매핑 방식이기 때문에 JPA의 엔티티 연관 관계 중에서 가장 기본으로 사용되는 매핑 방식
  • @ManyToOne : 다대일 관계 명시
  • @JoinColumn : 외래키에 해당하는 컬럼명을 적어준다.
@Entity
public class Order{

@ManyToOne   // 다대일
    @JoinColumn(name = "MEMBER_ID")  
    private Member member;
}

@OneToMany(mappedBy = "member") //일대다
    private List<Order> orders = new ArrayList<>();

객체 그래프 탐색

  • 객체를 통해 다른 객체의 정보를 얻을 수 있는 것
  • ex) findOrder.getMember().getMemberId()

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

  • 다대일 매핑이 되어 있는 상태에서 일대다 매핑을 추가해 양방향 관계를 생성
  • **@OneToMany(mappedBy = "member")**
  • mappedBy 선정 기준 (1) 두 객체들 간에 외래키의 역할을 하는 필드는 무엇인가? (2) 외래키의 역할을 하는 필드는 다(N)에 해당하는 클래스 안에 있다.

모든 관계의 중심을 외래키에서 부터 시작한다.

**다대다 연관 관계**

  • 중간에 연결 클래스를 추가해서 두 개의 다대일 매핑한후, 다대일 매핑을 통해 그래프 탐색으로 원하는 객체를 조회할 수 없다면 그 때 일대다 양방향 매핑을 추가하면 된다.

**일대일 연관관계**

  • @ManyToOne단방향 방식, 양방향 방식과 동일
  • @OneToOne 애너테이션을 사용

JPA 영속성 전이(CASCADE)

영속성전이(CASCADE)

  • 부모 엔티티가 영속화될 때 자식 엔티티도 같이 영속화되고, 부모 엔티티가 삭제될 때 자식 엔티티도 삭제되는 등 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 전이되는 것을 의미

종류

  • CascadeType.ALL: 모든 Cascade를 적용
  • CascadeType.PERSIST: 엔티티를 영속화할 때, 연관된 엔티티도 함께 유지
  • CascadeType.MERGE: 엔티티 상태를 병합(Merge)할 때, 연관된 엔티티도 모두 병합
  • CascadeType.REMOVE: 엔티티를 제거할 때, 연관된 엔티티도 모두 제거
  • CascadeType.DETACH : 부모 엔티티를 detach() 수행하면, 연관 엔티티도 detach()상태가 되어 변경 사항 반영 X
  • CascadeType.REFRESH: 상위 엔티티를 새로고침(Refresh)할 때, 연관된 엔티티도 모두 새로고침

Spring Data JPA

  • public interface MemberRepository extends JpaRepository<Member, Long>
    • CrudRepository를 상속하는 대신 JpaRepository를 상속

JPA에서 제공하는 복잡한 검색 조건을 지정하기 방법

  1. JPQL을 통한 객체 지향 쿼리 사용

    1. JPQL이라는 객체 지향 쿼리를 통해 데이터베이스 내의 테이블을 조회가능
    2. JPA가 내부적으로 JPQL을 분석해서 적절한 SQL을 만든 후에 데이터베이스를 조회하고, 조회한 결과를 엔티티 객체로 매핑한 뒤에 반환
    3. JPQL은 엔티티 클래스의 객체를 대상으로 한 조회이기 때문에 테이블이 아니라 클래스 객체를 지정해야하고, 컬럼이 아닌 필드를 지정해야한다.

    ex) SELECT c FROM Coffee c WHERE c.coffeeId = :coffeeId

    • Coffee는 클래스명 coffeeId는 필드명, c 는 클래스의 별칭
  2. 네이티브 SQL을 통한 조회

profile
백엔드 개발자

0개의 댓글