본문 바로가기

Spring/JPA

JPA- 임베디드 타입

JPA 데이터 타입

 엔티티 타입

  JPA의 데이터 타입은 엔티티 타입값 타입 두가지로 구성된다.

엔티티는 기본적으로 우리가 많이 보았듯이, @Entity를 사용하며 값이 변경되어도 ID와 같은 식별자로 여전히 구분이 가능하다.

  • @Entity를 사용
  • 식별자로 추적이 가능

  값 타입

   값 타입은 int, double과 같은 기본 타입과, Integer, Long 같은 래퍼 클래스, 임베디드 타입, 컬랙션 타입으로 구성된다.  

 엔티티와는 달리 변경시 추적이 불가능하다는 차이점이 존재한다.

  - 기본 값 타입

  • (int, double ...) 기본 타입
  • (Integer, Long ...) 래퍼 클래스
  • String

 기본 값 타입은 기본적으로 call by value를 취하기에 만일 내가 엔티티의 어떠한 기본 값 타입 필드(예를 들면 int age)를 변경했다 해도 다른 엔티티에는 영향을 끼치지 못한다.

 

임베디드 타입

  임베디드 타입은 간단히 말해서 새로운 어떠한 클래스를 만들고,  그 내부에 기본 값 타입을 모아놓은 것이다. (이는 기존 필드들의 관리를 편리하게 위함이다.)

 다만 이는 클래스(객체)이지만 엔티티가 아닌 값 타입으로 인식된다.

 

  임베디드 타입을 사용하기 위해선 다음과 같은 어노테이션이 사용된다. 잊지 말아야 할 것은 임베디드 타입은

반드시 기본 생성자를 가진다. 

  • @Embeddable: 임베디드 타입으로 사용할 클래스에 선언한다.
  • @Embedded: 임베디드 타입을 사용하기 위한 위치에 선언한다.

 

예를 들어 Member 엔티티는 다음과 같이 생겼다고 하자.

 

 근데 지금보면 몇가지 연관된 것들이 보인다.

  1.  startDate, endDate
  2.  city, street, zipcode

1번은 시간을, 2번은 주소라는 공통점을 가지고 있다.

그렇다면 이렇게 연관된 것들을 하나로 묶어서 관리하면 편하지 않을까? 라는 물음에서 시작된 것이 바로 임베디드 타입이다.

 

 

 

 

유사한 필드들을 묶음. workPeriod(startDate, endDate), homeAddress(city, street, zipcode)

근데 사실 코드로 보는 것이 가장 이해가 빠르니 코드를 보자.

 

Period.class

package hellojpa;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.Embeddable;
import java.time.LocalDateTime;

// 임베디드 타입은 int, String과 같은 여러개의 기본 값 타입을 하나로 묶어서 관리가 용의하게 한다.
@Embeddable  // 임베디드 타입으로 정의 => 이 클래스는 엔티티가 아닌 기본 값 타입이된다.
@Getter @Setter
public class Period {

    private LocalDateTime startDate;
    private LocalDateTime endDate;

    // 임베디드 타입은 기본생성자가 필수!!
    public Period(){}

    public Period(LocalDateTime startDate, LocalDateTime endDate) {
        this.startDate = startDate;
        this.endDate = endDate;
    }
}

Address.class

package hellojpa;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.Embeddable;

// 임베디드 타입은 int, String과 같은 여러개의 기본 값 타입을 하나로 묶어서 관리가 용의하게 한다.
@Embeddable  // 임베디드 타입으로 정의 => 이 클래스는 엔티티가 아닌 기본 값 타입이된다.
@Getter @Setter
public class Address {

    private String city;
    private String street;
    private String zipCode;

    // 임베디드 타입은 기본생성자가 필수!!
    public Address(){}

    public Address(String city, String street, String zipCode) {
        this.city = city;
        this.street = street;
        this.zipCode = zipCode;
    }
}

Member.class

package hellojpa;

import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import static javax.persistence.FetchType.LAZY;

@Entity
@Getter @Setter
public class Member extends BaseEntity {

    @Id @GeneratedValue 
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME", nullable = false)
    private String userName;

    @Embedded // @Embedded: 임베디드 타입 사용하는 곳에 사용
    private Period workPeriod;

    @Embedded // @Embedded: 임베디드 타입 사용하는 곳에 사용
    private Address homeAddress;
}

  Address와 Period는 @Embeddable을 통해서 임베디드 타입으로 선언했고, 이를 @Embedded로 Member에서 사용하는 것을 확인 할 수 있다. 

 지금은 Address와 Period 내부에 따로 메서드를 구현하지 않았지만, 메서드를 구현한다면 관련 필드들을 좀 더 효율적으로 관리가 가능하다는 점도 임베디드 타입이 가지는 장점이다.

'Spring > JPA' 카테고리의 다른 글

JPA- 값 타입의 비교  (0) 2023.04.30
JPA- 값 타입과 불변 객체  (0) 2023.03.23
JPA- Cascade와 고아 객체  (0) 2023.03.21
JPA- 즉시 로딩, 지연 로딩  (0) 2023.03.16
JPA- 프록시  (0) 2023.03.16