9. 값 타입 (임베디드 타입)

HotFried·2023년 10월 2일
0

임베디드 타입

  • 새로운 값 타입을 직접 정의할 수 있다.

  • JPA는 그러한 값 타입을 임베디드 타입이라고 한다.

  • 주로 기본 값 타입을 모아서 만들기 때문에 복합 값 타입이라고도 한다.

  • int, String과 같은 값 타입

근무 시작일, 근무 종료일과 도시, 우편 번호, 주소는 공통으로 묶을 수 있는 데이터이다.


공통으로 묶을 수 있는 데이터를 Period Address 값 타입으로 정의한다.


사용법

  • @Embeddable : 값 타입을 정의하는 곳에 표시
  • @Embedded : 값 타입을 이용하는 곳에 표시
  • 기본 생성자 필수

특징

  • 재사용이 가능한다.
    -> 기간이나 주소는 시스템 전체에서 이용할 수 있는 데이터이다.

  • 응집도가 높다.
    -> Period.isWork()처럼 해당 값 타입만 이용하는 의미있는 메서드를 만들 수 있다.

  • 임베디드 타입을 포함한 모든 값 타입은, 값 타입을 소유한 엔티티에 생명주기를 의존한다.


임베디드 타입과 테이블 매핑

  • 멤버 엔티티
@Entity
public class Member {
	...
    // 임베디드 타입
    @Embedded
    private Period period;

    // 임베디드 타입
    @Embedded
    private Address address;

    // 응집성 있는 로직 구현
    public boolean isWork() {
        return true;
    }
    ...
}
  • Period 값 타입
@Embeddable
public class Period {

    private LocalDateTime startDate;
    private LocalDateTime endDate;
    
    //기본 생성자 필수
    public Period(){
    }
    
    public period(LocalDateTime startDate, LocalDateTime endDate) {
        this.startDate = startDate;
        this.endDate = endDate;
    }
}
  • Address 값 타입
@Embeddable
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;
    }
}
  • JpaMain
public class JpaMain {

    public static void main(String[] args) {
        Member member = new Member();
        member.setUsername("name");
        member.setAddress(new Address("city", "street", "10001"));
        member.setPeriod(new Period());

        em.persist(member);

        tx.commit();
    }
}

  • 임베디드 타입은 엔티티의 값일 뿐이다.

  • 임베디드 타입을 사용하기 전과 후에 매핑하는 테이블은 같다.

  • 객체와 테이블을 아주 세밀하게(find-grained) 매핑하는 것이 가능하다.

  • 잘 설계한 ORM 애플리케이션은 매핑한 테이블의 수보다 클래스의 수가 더 많다.


임베디드 타입과 연관관계

  • Address와 ZipCode처럼 임베디드 타입도 임베디드 타입을 가질 수 있다.
  • PhoneNumber와 PhoneEntity처럼 임베디드 타입이 Entity를 가질 수도 있다.
    FK만 가지고 있으면 가능하다.

@AttributeOverride : 속성 재정의

한 엔티티에서 같은 값 타입을 사용할때 이용한다.

@Entity
public class Member {

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "name")
    private String username;

    @Embedded
    private Period period;

    // 같은 임베디드 타입을 중복해서 사용할 경우 에러가 난다.
    @Embedded
    private Address homeAddress;

    @Embedded
    private Address workAddress;
}

같은 임베디드 값 타입을 중복해서 사용할 경우 에러가 난다.
이 때 @AttributeOverride 어노테이션을 이용해 새로운 컬럼 명을 정의해준다.

@Entity
public class Member {

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "name")
    private String username;

    @Embedded
    private Period period;

    @Embedded
    private Address homeAddress;

    // Column 이름 재정의
    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "city", column = @Column(name = "work_city")),
            @AttributeOverride(name = "street", column = @Column(name = "work_street")),
            @AttributeOverride(name = "zipcode", column = @Column(name = "work_zipcode"))
    })
    private Address workAddress;
}

임베디드 타입과 null

  • 임베디드 타입의 값이 null이면 매핑한 컬럼 값은 모두 null이다.
    -> period가 null이면 그 안에 있는 StartDate, EndDate 모두 null이다.

참고 :

김영한. 『자바 ORM 표준 JPA 프로그래밍』. 에이콘, 2015.

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

profile
꾸준하게

0개의 댓글