본문 바로가기
TIL

Spring Boot - @Embeddable, @Embedded, @AttributeOverride, @AttributeOverrides (22.11.25 TIL)

by winteringg 2022. 11. 25.

풀스택 강의 중 나온 @Embeddable 과 @Embedded, @AttributeOverride 를 정리해보자!

@Embeddable, @Embedded

Embedded 는 끼워 넣다, 간직하다 라는 뜻을 가지고 있는데, DB 에는 객체를 넣을 수 없기 때문에 이 어노테이션을 사용하면 말 그대로 객체를 DB 에 끼워 넣을 수 있게 해 준다, 는 의미로 받아들이면 된다.

임베디드 타입을 적용하려면 새로운 클래스를 만들고 해당 클래스에 @Embeddable 을 선언해준다. 그리고 임베디드 타입으로 묶으려던 속성들을 넣어준 뒤 각 속성에 @Embedded 어노테이션을 붙여주면 된다.

  • @Embeddable : 값 타입을 정의하는 곳에 표시한다.
  • @Embedded : 값 타입을 사용하는 곳에 표시한다.

클래스 위에 붙는 @Embeddable
속성에 붙는 @Embedded

위 사진처럼 사용하게 되면 DB 에 sender 와 receiver, account_number 컬럼이 생성된다.

 

@AttributeOverride, @AttributeOverrides

하나의 클래스를 통해 여러 개의 정보를 만들고 싶은경우 컬럼명을 재정의해줄 수 있는 어노테이션이다.

@Embeddable
public class Address {
    private String city;
    private String district;
    private String detail;
    private String zipCode;
}

예를 들어 위의 코드처럼 회사의 주소와 집 주소의 형태는 시, 구, 상세 주소, 우편번호로 동일하다.

@Entity
@Table(name = "PERSON")
public class User {
    @Id
    @GeneratedValue
    private Long id;
    
    private String name;
    
    @Embedded
    private Address homeAddress;
    
    @Embedded
    private Address companyAddress;
}

이러한 경우 컬럼명을 재정의 해주지 않고 위 처럼 바로 사용하면 Repeated column in mapping for entity 라는 중복 에러가 발생한다. @Embedded 를 사용하는 경우 객체의 이름이 아닌 해당 객체 안에 작성된 필드의 이름을 컬럼으로 사용하기 때문이다.

재정의는 아래와 같이 해주면 된다.

@Entity
@Table(name = "user")
public class User {

.....

    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "city", column = @Column(name = "home_city")),
            @AttributeOverride(name = "district", column = @Column(name = "home_district")),
            @AttributeOverride(name = "detail", column = @Column(name = "home_address_detail")),
            @AttributeOverride(name = "zipCode", column = @Column(name = "home_zipCode"))
    })
    private Address homeAddress;

    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "city", column = @Column(name = "company_city")),
            @AttributeOverride(name = "district", column = @Column(name = "company_district")),
            @AttributeOverride(name = "detail", column = @Column(name = "company_address_detail")),
            @AttributeOverride(name = "zipCode", column = @Column(name = "company_zipCode"))
    })
    private Address companyAddress;
   
   	.....
}


여기서 의문은, @Column 어노테이션을 사용해서 속성 하나 하나 네이밍을 다시 해주면 안 될까?라는 것인데, 만약 아래처럼 사용해본다고 가정해보자.

@Embeddable
public class Address {
   @Column(name = "home_city")
   private String city;
   
   @Column(name = "home_district")
   private String district;
   
   @Column(name = "home_address_detail")
   private String detail;
   
   @Column(name = "home_zipCode")
   private String zipCode;
}


이렇게 사용하게 되면 애초에 같은 Address 라는 객체를 사용하는 것이기 때문에 객체 안에 있는 필드의 이름을 컬럼으로 사용하게 되므로 해결 방법이 되지 못한다. 따라서 @AttributeOverride 를 통해 객체 안에서 컬럼을 재정의해야만 한다.

 

 

참고 :

 

Overriding Column Definition With @AttributeOverride with Baeldung

https://www.baeldung.com/jpa-attributeoverride

JPA @Embedded And @Embeddable with Baeldung

https://www.baeldung.com/jpa-embedded-embeddable

 

[Spring JPA] @Embedded, @Embeddable

임베디드 타입 - 임베디드 타입은 복합 값 타입으로 불리며 새로운 값 타입을 직접 정의해서 사용하는 JPA의 방법을 의미한다.

velog.io

댓글