📋 기본 값 타입 매핑
JPA에서는 데이터 타입을 최 상위 레벨로 분류하면 엔티티 타입과 값 타입으로 분류할 수 있습니다.
① 엔티티 타입은 @Entity로 정의하는 객체로 데이터가 변경되어도 식별자로 인식이 가능합니다.
ex) 회원 엔티티안에서 키 또는 나이의 값이 변경되어도 식별자를 이용해서 인식하여 내부 데이터가 변경되어도 추적이 가능합니다.
② 값 타입은 int, integer,String 처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체를 의미합니다.
식별자가 없고 값만 있으므로 (int나 integer는 단순한 값이기 때문에) 변경 시 히스토리 추적이 불가능합니다.
ex) 숫자 100을 200으로 변경하면 완전히 다른값으로 대체될 뿐 과거이력을 알 수는 없습니다. 게시판에 String 컨텐츠라는 건 Board라는 엔티티안에서 변경되는 경우 이전 값을 추적하기 어렵습니다.
- 기본 값 타입 은 JPA(Java Persistence API)에서 객체의 기본 데이터 타입을 데이터베이스의 열(Column)에 매핑하는 과정을 말합니다. 기본 값 타입에는 자바의 기본 데이터 타입(int, double, boolean 등), 해당 타입들의 래퍼 클래스(Integer, Double, Boolean 등), String 타입 의미합니다.생명주기를 엔티티에 의존하는 특징이 있습니다. 예를 들어, 회원을 삭제하게되면 이름, 나이 필드도 함께 삭제되어집니다. 값 타입에 value 자체는 절대로 공유하면 안됩니다. 회원 이름을 변경할 때, 다른 회원의 이름도 변경되는 사이드 이펙트 같은 부수효과가 일어나서는 안됩니다.
JPA에서 엔티티(Entity) 클래스의 속성을 데이터베이스의 열에 매핑할 때, 기본 값 타입을 사용하는 경우에는 각 속성의 데이터 타입을 그대로 데이터베이스의 열에 저장합니다. 이러한 기본 값 타입 매핑은 @Column 어노테이션을 통해 열의 이름 및 속성과 매핑 정보를 지정할 수 있습니다.
이 때, 엔티티 객체의 속성이 객체지향 프로그래밍에서 사용되는 기본 데이터 타입인 경우, 이를 데이터베이스에 매핑하여 영속화합니다. 엔티티 클래스의 속성 중에서 기본값 타입인 경우, 이 속성은 별도의 테이블로 분리되지 않고, 해당 엔티티의 테이블에 열(Column)로 직접 매핑됩니다. 이를 통해 엔티티 속성의 매핑 정보를 지정하고 데이터베이스와의 연결을 설정할 수 있습니다.
✍️ 기본 값 타입 예제
int 예시
int a = 10;
int b = a; //b가 초기화될 때, a의 10의 value가 복사가 되어 b에 저장됨
a = 20; //b value에 20을 넣으면 b의 값만 변하게 됨
System.out.println("a = " + a);
System.out.println("b = " + b);
==== 출력 ====
a = 20;
b = 10;
래퍼클래스 Integer 예시
Integer a = Integer.valueOf(10);
Integer b = a; // 이 땐, a의 value가 복사되어 넘어가는 것이 아니라 주소값(참조값)이 전달됩니다.
기본 값 타입은 항상 값을 복사하게 되어, value가 공유되지 않습니다.
* Integer같은 래퍼 클래스나 String 같은 특수한 클래스는 레퍼런스를 가지고 가기 때문에 참조값 공유가 가능한 객체이지만
* 변경자체를 불가능하게 두었기때문에, 사이드이펙트가 발생하지 않아 개발 시 안전하게 개발이 가능합니다. */
2. 임베디드 타입은 데이터베이스 내에 객체를 저장하는 방식 중 하나입니다. 객체를 데이터베이스의 한 열(column)에 저장하는 것이 아니라, 객체 내부의 필드를 테이블의 열로 매핑하여 저장하는 방식입니다. 이는 관계형 데이터베이스 시스템에서 객체 지향 프로그래밍의 객체를 효율적으로 저장하고 검색하는 방법을 제공하는 기술입니다.JPA는 임베디드 타입이라고 하고, 기본 값 타입을 모아서 만들어서 복합 값 타입이라고도 불립니다.
int나 String 처럼 임베디드 타입도 값 타입으로 변경이 불가하고 추적도 어렵습니다. 예를 들어, 자바의 JPA(Java Persistence API)에서는 @Embeddable 어노테이션을 사용하여 임베디드 타입을 정의하고, 이를 엔티티 클래스의 필드에 @Embedded 어노테이션을 통해 적용할 수 있습니다. 이를 통해 관계형 데이터베이스의 테이블 내부에 객체의 필드를 중첩하여 저장할 수 있습니다.
여러 엔티티에서 반복적으로 사용되는 기본 값 타입들을 하나의 임베디드 클래스로 새로운 값 타입을 정의하여 중복 코드를 줄이고 유지보수성을 높일 수 있습니다.이를 통해 복잡한 데이터 구조를 단순화하고 재사용성을 높일 수 있습니다.
✍️ @Embeddable과 @Embedded
@Embeddable : @Embeddable 어노테이션은 임베디드 타입을 정의하는 클래스에 붙입니다. 이 클래스는 데이터베이스 테이블의 열(column)처럼 객체 내부의 필드를 나타내며, 해당 필드들을 중첩해서 저장할 때 사용됩니다.
@Embedded : @Embedded 어노테이션은 엔티티 클래스의 필드에 임베디드 타입을 적용할 때 사용됩니다. 임베디드 타입의 필드들은 해당 엔티티의 테이블에 중첩해서 저장됩니다.
=== @Embeddable ===
@Embeddable
public class Address {
private String street;
private String city;
private String zipCode;
// ...
}
=== @Embedded ===
@Entity
public class Member {
@Id
private Long id;
private String name;
@Embedded
private Address address;
// ...
}
위의 예시에서 Address 클래스는 @Embeddable로 정의된 임베디드 타입이며, Member 클래스의 address 필드에 @Embedded 어노테이션을 사용하여 해당 임베디드 타입을 적용했습니다. 따
라서 Member 엔티티의 테이블에는 중첩된 형태로 Address의 필드들이 저장됩니다.
✅@Embeddable 타입의 장점
- 복합 객체를 단일 엔티티로 표현: 복합 객체(Composite Object)는 여러 개의 속성으로 구성된 객체를 말합니다. 예를 들어 주소(Address)나 이름(Name) 등은 여러 속성으로 구성될 수 있는데, 이러한 복합 객체를 단일 엔티티에 중첩해서 저장하고 관리할 수 있습니다.
- 코드의 가독성 향상: 여러 엔티티에서 공통적으로 사용되는 복합 객체를 중복 없이 정의하고 재사용할 수 있습니다. 이로써 코드 중복을 줄이고 가독성을 향상시킬 수 있습니다.
- 데이터베이스 효율성: 임베디드 타입은 엔티티의 속성을 테이블의 열(column)로 매핑하지 않고 중첩 구조로 저장합니다. 이로써 데이터베이스 테이블의 정규화(normalization) 원칙을 준수할 수 있어 중복 데이터를 효율적으로 관리하고 저장 공간을 절약할 수 있습니다.
- 객체 지향 설계 유지: 객체 지향 프로그래밍의 핵심 원칙 중 하나인 "객체는 상태와 행위를 함께 가진다"를 지키며 객체의 구조를 유연하게 설계할 수 있습니다.
- 쿼리 간결성: 임베디드 타입을 사용하면 복합 객체의 속성을 편리하게 조회하거나 조건 검색에 활용할 수 있습니다. 이로 인해 복잡한 쿼리를 작성하는 번거로움을 줄일 수 있습니다.
임베디드 타입은 엔티티의 값일 뿐입니다. 크게 의미가 있지 않으며, 임베디드 타입을 적용하기 전과 후의 매핑하는 테이블은 일치하다는 특징이 가장 중요한 특징입니다. 객체와 테이블을 아주 세밀하게 매핑하는 것이 가능하게 됩니다.
'[ BACKEND] > Spring' 카테고리의 다른 글
[SPRING] Servlet & MV (0) | 2023.08.22 |
---|---|
[SPRING] 값 타입 컬렉션 (0) | 2023.08.21 |
[SPRING] 영속성 전이 & 고아객체 (0) | 2023.08.19 |
[SPRING] 즉시 로딩과 지연 로딩 (0) | 2023.08.18 |
[SPRING] ✅ Proxy (0) | 2023.08.17 |