[JPA] @Embeddable, @Embedded

HeavyJ·2023년 3월 31일
0

스프링 이론 정리

목록 보기
3/5

@Embeddable / @Embedded

@Embeddable

  • 엔티티가 아닌 타입을 한 개 이상의 필드와 매핑할 때 사용합니다
  • 엔티티의 한 속성으로 @Embeddable 적용 타입이 사용됩니다.

DB 설계 시 여러 테이블에 관련된 값을 저장할 때가 있습니다.

이럴 경우 @Embeddable 어노테이션을 활용하여 조금 더 객체지향스럽게 개발이 가능합니다.

@Entity
@Getter
@Setter
public class Member{
	@Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;
    
    private String name;
    
    private String city;
    private String street;
    private String zipcode;
}

예를 들어, 회원 엔티티가 이름, 도시, 주소 번지, 주소 우편번호를 가집니다.
이때 도시, 주소 번지, 주소 우편변호는 회원의 주소를 알기 위해 가지는 칼럼입니다.

이때 상세 데이터 또한 하나의 객체로 묶게 되면 훨씬 객체 지향적으로 설계가 가능합니다.

@Embeddable
@Getter
public class Address{
	private String city;
    private String street;
    private String zipcode;
}

주소 임베디드 타입을 생성하기 위해 @Embeddable 어노테이션을 주소 클래스에 생성해주고

@Entity
@Getter
@Setter
public class Member{
	@Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;
    
    private String name;
   	
    @Embedded
    private Address address;

Member 객체에서 임베디드 타입으로 된 주소 객체를 @Embedded 어노테이션을 이용해 사용합니다.

저장

이럴 경우 저장이 객체 지향적으로 이뤄집니다.

tx.begin();
Address address = new Address("부산","해운대로","12345");
Member member = new Member(1, "김덕배", address);
em.persist(member);
tx.commit();

조회

Member member = em.find(Member.class, 1);
logger.info("주소 : {}", member.getAddress());

실제로 적용해보기

실제로 @Embeddable과 @Embedded 어노테이션을 프로젝트에서도 사용해봤습니다.

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "calendar_info_table")
public class Calendar {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    // 기본키(primary key)
    private Integer conNo;

    private String singer;

    private String conTitle;

    private String conContent;

    private LocalTime conTime;

    private LocalDate conStart;

    private LocalDate conEnd;

    private LocalDateTime createdDate;

    private LocalDateTime updatedDate;

}

공연 정보를 담은 테이블인데 conTime(공연 시작 시간), conStart(공연 시작 날짜), conEnd(공연 종료 날짜)를 ConcertTime이라는 클래스를 생성하여 묶어서 응집도를 높이고 ORM의 취지에 맞게 개발을 진행했습니다.

그래서 ConcertTime 클래스를 만들어주고 @Embeddable 어노테이션을 입력했습니다.

@Embeddable
@Getter
public class ConcertTime {
    private LocalTime conTime;

    private LocalDate conStart;

    private LocalDate conEnd;
}

그리고 기존의 엔티티에는 @Embedded 어노테이션을 추가했습니다.

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "calendar_info_table")
public class Calendar {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    // 기본키(primary key)
    private Integer conNo;

    private String singer;

    private String conTitle;

    private String conContent;
	
    @Embedded
    private ConcertTime concertTime;

    private LocalDateTime createdDate;

    private LocalDateTime updatedDate;
}

그러면 인텔리제이의 persistence 탭에서 확인해볼 수 있습니다

엔티티 릴레이션십 다이어그램

엔티티 릴레이션십 다이어그램을 통해 Calendar의 ConcertTime 객체가 3개의 데이터를 잘 묶고 있는 것을 확인할 수 있습니다.

참고로 엔티티 릴레이션십 다이어그램과 실제 DB 테이블의 형태는 다릅니다!!

실제 DB에 ConcertTime 테이블이 추가로 생성되는 것이 아닌 ConcertTime 클래스가 필드 역할을 하는 것입니다. 실제 DB의 필드에는 영향이 가지 않습니다.

@Embedded 어노테이션을 활용하여 조금 더 ORM스러운 개발을 진행할 수 있었습니다! 😀😀

profile
There are no two words in the English language more harmful than “good job”.

1개의 댓글

comment-user-thumbnail
2023년 4월 3일

점점 발전 하시는군요. 다만 embedded가 쓰다보면 약간 계륵같은 포지션일경우가 많습니다 ..ㅠㅠ

db와 entity의 관계가 직관적이지 않게 되는 지점 때문에 곤란할때가 있더군요.

그 부분의 해결방안까지 학습하시고 블로깅하시면 더 좋은 시리즈가 될 거 같아요!!

답글 달기