본문 바로가기
우아한테크코스/레벨 2 - Spring

[JPA] @Embedded, @Embeddable 개념과 사용법

by shyun00 2024. 5. 16.

이번 미션에서는 기존에 JDBC를 통해 관리하던 테이블을 JPA로 전환하는 작업을 진행했다.

 

그 과정에서 '객체'를 필드로 갖는 엔티티를 테이블에 저장할 때,

데이터를 어떻게 테이블에 넣을 수 있을지 고민했었는데, 그 과정을 기록해보려고한다.

 

* JPA 자체에 대한 내용은 생략했다. 필요하면 아래 게시글을 참고하기를 바란다.

JPA(Java Persistence API)

엔티티간 연관관계 매핑

Spring Data JPA(데이터 액세스 계층 구현)

 

내용을 정리하면서 과정을 좀 더 간단히 나타내기 위해 실제 코드가 아닌 예시 코드를 별도로 작성하였다.

 

1. Member 클래스 정의

회원 정보를 담고 있는 Member 객체가 있다고 가정하자.

회원의 고유 식별자, 이름, 이메일, 비밀번호, 주소를 필드로 갖는다.

@Entity
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    private String password;
    private String address;

    public Member(final Long id, final String name, final String password, final String address, final String email) {
        this.id = id;
        this.name = name;
        this.password = password;
        this.address = address;
        this.email = email;
    }

    protected Member() {
    }
}

 

애플리케이션을 실행시켜보면, 아래와 같은 쿼리로 테이블이 생성되고 있다.

 

우테코 지난 미션들의 요구사항 중 하나였던 '모든 원시값을 포장한다'를 적용시켜보자.

(요구사항이어서 무조건 적용한다기 보다는,

각 속성을 클래스로 관리했을 때 규칙이나 기능을 관리하기가 좋아서 적용하게 되었다.)

 

이름은 Name으로, 그리고 사용자의 중요한 개인정보(이메일, 비밀번호, 주소)는 별도의 객체로 관리한다고 가정하자.

 

2. 원시값 포장

원시값을 포장하면 아래와 같은 형태가 될 것이다.

아무런 작업을 하지 않았을 때에는 아래 이미지에서 보이는 것과 같이 포장된 Name, PersonalInformation에서 컴파일 에러가 발생했다.

 

애플리케이션을 실행했을 때의 에러 메세지를 확인해보면,

Name을 해결하지 못해 예외가 발생했음을 알 수 있다.

(PersonalInformation도 마찬가지일 것이다.)

 

3. @Embedded & @Embeddable 적용

이 때 사용할 수 있는 것이 @Embedded, @Embeddable 애너테이션이다.

 

공식 문서를 찾아보면 각 애너테이션에 대해 아래와 같이 설명하고 있다.

 

@Embedded

Specifies a persistent field or property of an entity whose value is an instance of an embeddable class. The embeddable class must be annotated as Embeddable.
The AttributeOverride, AttributeOverrides, AssociationOverride, and AssociationOverrides annotations may be used to override mappings declared or defaulted by the embeddable class.

→ 특정 필드나 속성이 embeddable 클래스임을 나타낸다. AttributeOverride 등을 통해 embedded된 속성의 필드 명을 명시해줄 수 있다.

 

@Embeddable

Defines 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.

→ 해당 인스턴스가 이를 소유하는 객체의 일부분(속성)으로 저장되고, 각 속성이 데이터베이스 테이블에 매핑된다.

 

Name, PersonalInformation에 @Embedded 애너테이션을 적용하고, 각 클래스에도 @Embeddable을 붙여주었다.

 

그 결과 컴파일 에러도 해결되고, 테이블 생성 SQL문도 다시 정상적으로 작성된것을 알 수 있다.

 

만약 데이터베이스에서 각 필드명을 임의로 작성해주고싶다면, AttributeOverride(s)를 통해 아래와 같이 설정해줄 수 있다.

생성된 Sql 문을 보면, 필드명을 지정해준 member_email, member_password로 생성된 것을 확인할 수 있다.

 

참고자료

@Embedded

@Embeddable

Jpa @Embedded and @Embeddable