[JPA] 임베디드 타입(@Embeddable)

옹심이·2025년 1월 1일
0
post-thumbnail

임베디드 타입이란?

JPA는 임베디드 타입을 통해 개발자가 별도의 클래스를 생성해 값 타입 처럼 사용할 수 있도록 도와준다.

임베디드 타입을 사용함으로써 코드 모듈화에 도움을 주며 재사용성을 높일 수 있다.
값 타입에 대한 자세한 내용은 이 포스트를 참고하자

사용 예제

Member 엔티티의 속성인 city, street, zipcode 등의 속성을 Address 임베디드 타입 클래스로 모듈화한 예제이다.

@Entity
public class Member {

    @Id
    @GeneratedValue
    private Long id;          // 식별자

    private String name;      // 회원 이름

    @Embedded
    private Address address;  // 임베디드 타입 사용
    ...
@Embeddable
public class Address {

    private String city;        // 도시
    private String street;      // 거리
    private String zipcode;     // 우편번호
		...

@Embedded와 @Embeddable로 매핑을 해주면 데이터베이스 테이블에서는 자동으로 임베디드된 속성들을 Member 테이블의 칼럼으로 사용할 수 있도록 해준다.

사용 시 주의 사항

1. 임베디드 타입 클래스에는 기본 생성자가 필요하다

리플렉션은 런타임에 런타임에 클래스, 메서드, 필드 등의 정보에 동적으로 접근하거나, 객체를 생성하는 기능을 제공한다

JPA는 리플랙션을 통해 객체를 생성한다. 따라서 임베디드 타입을 인스턴스화할 때 기본 생성자를 먼저 호출하고 리플렉션을 통해 임베디드 타입의 구조를 파악 후 객체를 생성한다.

기본 생성자가 정의되어 있지 않은 경우에는 InstantiationException이 발생한다.

2. 임베티드 타입은 값 타입이므로 불변성을 유지해야하며 여러 엔티티에서 공유를 금지한다.

Address address = new Address("Seoul", "Gangnam", "12345");

Member member1 = new Member("Member1", address);
Member member2 = new Member("Member2", address);

member1.getAddress().setCity("Busan"); // member2의 address도 변경됨

임베디드 타입은 기본적으로 값 타입의 성격을 띈다. 따라서 공유에 의해 값이 변화되는 경우 부작용이 발생한다.

임베디드 타입인 Address를 가지는 Member 클래스 객체를 두 개 생성하고 Address를 수정하면 다른 Member객체에도 적용된다.

Address copiedAddress = new Address(address.getCity(). address.getStreet, address.getZipcode());

대신 Address를 복사해 사용하면 임베디드 타입인 Address의 값에 영향을 주지 않을까? 임베디드 타입을 포함해 개발자가 만들어내는 객체는 모두 객체 타입이기 때문에 복사를 해도 참조를 복사한다. 결국 같은 객체를 가리키기 때문에 소용없다

공유로 인한 값 변경은 피할 수 없으므로 값을 변경할 수 없도록 하자. Setter를 사용하지 않거나 Private으로 정의하면 된다.

3. 임베디드 타입은 포함된 엔티티의 생명주기에 의존한다.

독립적으로 영속성을 가지지 않기 때문에 포함된 대상 엔티티를 기준으로 저장, 수정, 삭제 된다.

0개의 댓글