[JPA] 임베디드 타입

Dawon Seo·2022년 9월 26일
0

JPA

목록 보기
5/5
post-thumbnail

JPA로 임베디드 타입을 사용하는 방법을 알아보겠습니다~

김영한님의 <자바 ORM 표준 JPA 프로그래밍>을 참고하여 작성한 글입니다!

임베디드 타입 사용해 보기

String, int와 같은 값 타입 외에도 JPA는 새로운 값 타입을 직접 정의해서 사용할 수 있는데, 이것을 임베디드 타입(embedded type)이라고 합니다.

예를 들어, Member라는 Entity가 다음과 같이 구성되어 있습니다.

Member.java

@Entity
public class Member {
	
    @Id
    private Long id;
    private String name;
    
    // 주소와 관련된 필드들
    private String zipcode;
    private String address;
}

zipcode와 address는 모두 주소와 관련된 값들이죠!
하지만 Member라는 엔티티가 주소와 관련된 상세 데이터를 그대로 가지고 있는 것은 객체 지향적이지 않으며, 응집력을 떨어뜨립니다.

때문에 주소와 관련된 값들을 새로운 class로 뽑아낸다면 다음과 같아집니다.

Address.java

@Embeddable
public class Address {
	private String zipdcode;
    private String address;
}

Member.java

@Entity
public class Member {
	
    @Id
    private Long id;
    private String name;
    
    @Embedded
    private Address address;
}

Member 테이블이 더욱 의미 있고 응집력 있게 변한 것을 확인할 수 있습니다!
위의 엔티티는 다음과 같은 테이블에 매핑됩니다.

이와 같은 임베디드 타입을 사용하기 위해서는,

  • 값 타입을 정의하는 클래스에 @Embeddable 어노테이션을 추가해야 합니다.
  • 값 타입을 사용하는 곳에 @Embedded 어노테이션을 추가해야 합니다.
  • 임베디드 타입은 기본 생성자가 필수입니다.

또한, 임베디드 타입은 다음과 같이 해당 값 타입만 사용하는 메소드도 만들 수 있습니다.
@Embeddable
public class Period {
	
    private LocalDate testLocalDate;
    private LocalDateTime testLocalDateTime;
    
    public boolean isWorkd(Date date) {
    	//.. 값 타입을 위한 메소드 정의
    }
}

임베디드 타입과 연관관계

임베디드 타입은 값 타입을 포함하거나 엔티티를 참조할 수 있습니다.

@Entity
public class Member {
	@Embedded Address address;	// 임베디드 타입 포함
    @Embedded PhoneNumber phoneNumber;	// 임베디드 타입 포함
}

@Embeddable
public class Address {
	String street;
    String city;
    String state;
    @Embedded Zipcode zipcode;	// 임베디드 타입 포함
}

@Embeddable
public class Zipcode {
	String zip;
    String plusFour;
}

@Embeddable
public class PhoneNumber {
	String areaCode;
    String localNumber;
    @ManyToOne PhoneServiceProvider provider; // 엔티티 참조
    ...
}

@Entity
public class PhoneServiceProvider {
	@Id String name;
    ...
}

위의 예제는 값 타입인 Addrress가 값 타입인 Zipcode를 포함하고, 값 타입인 PhoneNumber가 엔티티 타입인 PhoneServiceProvider를 참조합니다.


@AttributeOverride: 속성 재정의

임베디드 타입에 정의한 매핑정보를 재정의하려면 엔티티에 @AttributeOverride를 사용하면 됩니다.
예를 들어 회원 엔티티에 집 주소와 회사 주소가 필요할 때,

@Entity
public class Member {
	
    @Id @GeneratedValue
    private Long id;
    private String name;
    
    @Embedded Address homeAddress;
    @Embedded Address companyAddress;
}

위와 같이 엔티티를 설계할 경우 매핑하는 컬럼명이 중복되는 문제가 발생합니다.
이를 해결하기 위해, 아래와 같이 @AttrivuteOverrides를 사용하여 매핑정보를 재정의해야 합니다.

@Entity
public class Member {
	
    @Id @GeneratedValue
    private Long id;
    private String name;
    
    @Embedded Address homeAddress;
    
    @Embedded
    @AttributeOverrides({
    	@AttributeOverride(name="city", column=@Column (name = "COMPANY_CITY")),
        @AttributeOverride(name="street", column=@Column(name = "COMPANY_STREET"),
        @AttributeOverride(name="zipcode", column=@Column(name = "COMPANY_ZIPCODE"))
   	})
    Address companyAddress;

임베디드 타입과 null

임베디드 타입이 null이면 매핑한 컬럼 값은 모두 null이 됩니다.

member.setAddress(null); // null 입력
em.persist(member);

회원 테이블의 주소와 관련된 컬럼 값들은 모두 null이 됩니다.

0개의 댓글