[JPA] @Embedded @Embeddable 사용법을 알아보자

오늘은 JPA 어노테이션인 @Embedded @Embeddable 에 대해서 알아보겠습니다.

 

 

서론


JPA 는 Java 에서 사용할 수 있는 ORM 으로 정말 유용한 도구 입니다.

보통 Java,Spring 개발자들은 Spring Data JPA 를 사용합니다.

 

Spring Data JPA 는 추상화가 아주 잘되어 있어 사용에 정말 유용 합니다. 

하지만 사용에 유용한 만큼, 잘 알고 사용할 필요가 있습니다. 

 

Spring Data JPA 를 추가하게 되면

jakarta.persistence;

 

위 패키지에서 추상화가 잘된 인터페이스 및 어노테이션을 사용할 수 있습니다.

그리고 공식문서 또한 보기 좋게 되어 있어, 개발 생산성에 아주 좋다고 생각합니다.

 

왜 JPA Entity 에서 @Embeddalbe , @Embedded 를 사용한다고 생각하시나요?

 

저는 위 어노테이션을 사용했을 때 객체지향 에 특성을 더 잘 살릴 수 있기 때문이라고 생각합니다.

 

📌 장점

1) 코드의 재사용

2) 가독성 향상

3) 높은 응집도

 

한 번 예시를 보며 한 번에 이해 할 수 있도록 도와드리겠습니다.

 

 

 

본론


아래 코드는 @Embeddable 을 설명하는 공식 문서입니다.

/**
 * Specifies a class whose instances are stored as an intrinsic 
 * part of an owning entity and share the identity of the entity. 
 * Each of the persistent properties or fields of the embedded 
 * object is mapped to the database table for the entity. 
 *
 * <p> Note that the {@link Transient} annotation may be used to 
 * designate the non-persistent state of an embeddable class.
 *
 * <pre>
 *
 *    Example 1:
 *
 *      @Embeddable 
 		public class EmploymentPeriod { 
 *       @Temporal(DATE) java.util.Date startDate;
 *       @Temporal(DATE) java.util.Date endDate;
 *      ... 
 *    	}
 *
 *    Example 2:
 *
 *      @Embeddable 
 		public class PhoneNumber {
 *        protected String areaCode;
 *        protected String localNumber;
 *        @ManyToOne PhoneServiceProvider provider;
 *        ...
 *     	}
 *
 *    @Entity 
 	  public class PhoneServiceProvider {
 *        @Id 
 		  protected String name;
 *         ...
 *     }
 *
 *    Example 3:
 *
 *    @Embeddable 
 	  public class Address {
 *       protected String street;
 *       protected String city;
 *       protected String state;
 *       @Embedded 
 		 protected Zipcode zipcode;
 *    }
 *
 *    @Embeddable 
 	  public class Zipcode {
 *       protected String zip;
 *       protected String plusFour;
 *     }


@Documented
@Target({TYPE}) 
@Retention(RUNTIME)
public @interface Embeddable {
}

 

위 코드에서 들어주시는 예시를 보시면 감이 좀 잡히시나요?

저는 영어를 잘하지 못해서 번역기를 돌리면서 읽습니다ㅎㅎ

 

위 코드를 보시면 이해가 잘 되시나요? 이해를 돕기 위해서 위 Example3 를 예시로 설명 드리겠습니다.

 

일단 첫번 째로 위 어노테이션을 뜻을 검색해보시고 뜻을 알면 이해하기 쉽습니다.

 

Embedded - 내장되어있는

Embeddable - 내장 가능한

이 정도로 해석할 수 있습니다. 

 

위 뜻을 보시면 짐작이 가시나요? 한번 코드를 봐보시죠

// 이해를 돕기 위해 클래스 한개 추가함     
public class Order {
   @Embedded
   private Address address;
}
     
     
     @Embeddable 
     public class Address {
        protected String street;
        protected String city;
        protected String state;
        @Embedded protected Zipcode zipcode;
     }
 
     @Embeddable 
     public class Zipcode {
        protected String zip;
        protected String plusFour;
      }

 

그냥 임의로 Order 클래스를 추가 했습니다. Order 인 이유는 Address 를 필요로 할 만한 내용이 대표적으로 주문 이 있기 때문 입니다.

 

그러면 구조가 최상위 Order - Address - Zipcode 순으로 되어 있습니다.

 

1) Order 안에 Address 가 내장되어 있음

2) Address 안에 Zipcode 가 내장되어 있음.

 

구조는 위 처럼 되어 있습니다.

 

즉 루트 객체에 포함되어 있는 하위 객체이거나 내가 어딘가에 포함이 될 수 있다고 생각하는 객체에 @Embeddable 을 사용합니다.

 

즉 Address 는 따로 테이블로 존재하지 않고, Order 에 속해있든, Member(그냥 예시임) 에 속해있든 어딘가에 속하는 객체이기 때문에

@Embeddable 을 사용해서 가독성을 올려줍니다.

 

@Embeddable 어노테이션은 간단하게 말하면 나는 메인 객체가 아니고, 어딘가에 포함되는 그냥 서브 객체이다? 

정도 느낌으로 알고있으면 좋을거 같습니다.

 

즉, 나는 다른 엔티티에 의해 embedded 될 것이라고 선언하는 것 입니다.

 

그럼 이제 @Embeddable 을 알았으니, 위 어노테이션이 선언된 객체 상위 객체에서 사용할 때는 명시적으로 

@Embeddable 객체를 사용한다는 걸 표시하기 위해 @Embedded 를 사용합니다.

 

즉, @Embedded 는 @Embeddable 이 선언된 객체를 다른 엔티티에 포함시키는 데 사용됩니다.

 

@Embedded 문서를 보시죠

위 @Embedded 문서를 보면 뭔가 제가 설명한 것과 다르게 이상한게 많지 않나요?

 

위 Example 에는 처음보는 @AttributeOverride(s), AssociationOverride(s) 등 해석하기 까다로워 보이는 어노테이션들이 있습니다.

 

간단한게 설명을 하면 위 클래스는 Entity 클래스에 포함되는 또 다른 클래스이며,

하위 클래스에서 임베디드 클래스의 특정 필드에 대한 매핑을 재정의하는 어노테이션 입니다.

 

✅ AttributeOverride:

 

@AttributeOverrides -> 임베디드 클래스 여러 매핑 재정의

@AttiributeOverride -> 임베디드 클래스 1개 매핑 재정의

 

✅ AssociationOverride:

 

@AssociationOverrides -> 임베디드 클래스 여러 개의 연관 관계 필드의 매핑을 재정의

@AssociationOverride -> 임베디드 클래스의 연관 관계 필드에 대한 1개 매핑을 재정의..

 

 

 

🖐🏻 간단하게 정리를 하면 

 

  • @AttributeOverride와 @AssociationOverride는 임베디드 클래스의 필드 매핑을 재정의할 때 사용합니다.
  • 관련된 여러 매핑 재정의는 @AttributeOverrides와 @AssociationOverrides를 사용해 그룹화할 수 있습니다.

 

추가적으로 @Entity 와 @Embeddable 로 클래스를 매핑하려면 기본 생성자를 제공해야 합니다.

 

DB에서 데이터를 읽어와 매핑된 객체를 생성할 때 기본 생성자를 사용해서 객체를 생성할 때 기본 생성자를 사용해서

객체를 생성하기 때문이다.

 

결론


🖐🏻 간단 정리

 

@Embeddable : 임베디드 클래스를 정의하는 곳에 선언

@Embedded : 임베디드 클래스를 엔티티에 포함시킬 때 선언

 

REF: https://www.baeldung.com/jpa-embedded-embeddable
728x90