이 영역을 누르면 첫 페이지로 이동
시간의화살 블로그의 첫 페이지로 이동

시간의화살

페이지 맨 위로 올라가기

시간의화살

행복하세요

[JPA] 값 타입

  • 2022.12.26 20:06
  • Spring/JPA

 

 

 

값 타입은 복잡한 객체를 단순화하기 위해 도입된 개념이다.

JPA는 데이터 타입을 두 가지로 분류한다.

 

 

1. Entity

 

@Entity 애너테이션으로 지정하는 객체를 의미하고, 데이터가 변해도 식별자로 추적할 수 있다.

PK를 사용해 데이터를 찾고 데이터를 추적할 수 있다고 생각하면 된다.

 

 

2. 값 타입

 

자바의 Primitive 타입과 객체를 의미한다.

식별자가 없으니 값이 변경돼도 추적할 수 없고, 생명 주기를 엔티티에 의존한다.

 

값 타입은 다시 세 가지로 분류된다.

 

기본 값 타입 : Primitive 타입과 래퍼클래스, String을 의미한다.

임베디드 타입 : 사용자가 임의로 만든 객체를 의미한다.

컬렉션 값 타입 : ArrayList처럼 기본 값 또는 임베디드 타입을 넣어서 사용하는 객체를 의미한다.

 

기본 값 타입은 다른 엔티티와 공유되면 안 된다. (주소를 사용해 공유되는 경우가 없어야 한다)

자바의 Primitive 타입은 절대 공유되지 않지만 다른 타입 사용 시에는 주의해야 한다.

 

 

 

 

Member 객체를 정의할 때 공통되는 부분을 따로 객체로 정의했다고 하자.

일단 테이블에서는 공통되는 부분을 따로 빼든 안 빼든 같은 방식으로 설계된다.

 

이 때 @Embeddable과 @Embedded 애너테이션이 사용된다.

 

@Embeddable 애너테이션은 값 타입을 정의하는 곳에 표시하고 (Period와 Address 클래스를 정의하는 부분) @Embedded 애너테이션은 엔티티 클래스에 표시해준다. (하나만 해도 되지만 둘 다 사용하는걸 권장)

 

@Embeddable 애너테이션이 붙는 클래스에는 기본 생성자가 있어야 한다.

 

이렇게 공통되는 부분을 따로 정리함으로써 메서드를 만들어서 사용할 수 있고, 클래스의 구조를 좀 더 깔끔하게 가져갈 수 있다.

 

임베디드 타입 내부에 임베디드 타입을 다시 가질 수 있고, 엔티티 타입도 가질 수 있다.

 

엔티티 내부에서 같은 임베디드 타입을 두 번 이상 사용하는 경우 Column 명이 중복되니 @AttributeOverride 애너테이션을 사용해 Column 명을 재정의한 후 사용한다.

 

 

 


 

 

 

자바 객체가 변경되어 2개 이상의 엔티티에 영향을 주는 경우를 피하기 위해 객체를 불변 객체로 설계하는 방법을 사용한다. (값이 공유되기를 의도했으면 엔티티로 정의하는 편이 합리적이다)

 

불변 객체는 생성된 이후 값을 변경할 수 없는 객체로, private접근자로 멤버변수를 정의하고 setter를 만들지 않는 방식으로 만들 수 있다. (Integer, String도 불변 객체이다)

 

값 타입은 꼭 불변으로 설정해 오류를 방지하자.

 

 

 

 

 


 

 

 

관계형 데이터베이스에서는 값으로 컬렉션을 넣을 수 없다.

 

 

 

따라서 엔티티에 컬렉션 값 타입을 사용하는 경우 별도의 테이블을 생성해 데이터베이스와 매핑한다.

 

생성되는 테이블의 PK는 컬렉션에 들어가는 값 타입의 모든 멤버변수를 묶어서 설정된다.

 

 

 

 

 

 

 

 

 

데이터베이스와 매핑할 때는 @ElementCollection 애너테이션과 @CollectionTable 애너테이션을 사용한다.

 

위와 같은 구조를 만들기 위해 JoinColumn을 지정해줬다.

 

Set<String>의 경우 테이블에 저장되는 Column명을 지정해주기 위해 @Column 애너테이션을 사용했다.

 

List<Address>는 임베디드 타입이니 알아서 Column명이 정해진다.

 

 

 

 

엔티티 내부의 모든 값 타입들은 수명 주기를 엔티티에 의존한다.

컬렉션 값 타입은 지연 로딩이고, 임베디드 값 타입은 즉시 로딩으로 동작한다.

 

 

객체를 컬렉션으로 다루고 컬렉션을 수정할 경우 주인 엔티티와 연관된 모든 데이터를 삭제하고 값 타입 컬렉션에 있는 현재 값을 다시 저장하는 방식으로 동작한다.

 

값 타입에는 엔티티와 다르게 식별자가 없어서.. 어쩔 수 없다. 

 

딱 봐도 엄청나게 비효율적으로 동작하는데.. 해결할 방법이 없을까?

 

@OrderColumn 애너테이션을 사용해서 어떻게 해결할 수는 있지만, 권장하지는 않는다.

 

실무에서는 값 타입 컬렉션을 포기하고 일대다 관계로 엔티티를 설계하는 방법을 고려하자.

영속성 전이와 고아 객체 제거 기능을 사용하면 엔티티를 값 타입 컬렉션처럼 사용할 수 있어 깔끔하게 문제를 해결할 수 있다.

 

값 타입 컬렉션은 정말 간단한 경우만 사용하고, 웬만한 경우에는 일대다 관계로 설계하도록 하자.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형
저작자표시 (새창열림)

'Spring > JPA' 카테고리의 다른 글

[JPA] JPQL (2)  (0) 2022.12.28
[JPA] JPQL (1)  (0) 2022.12.27
[JPA] 영속성의 전이와 고아 객체  (0) 2022.12.24
[JPA] 프록시와 연관관계  (0) 2022.12.24
[JPA] 상속관계 매핑  (0) 2022.12.23

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • [JPA] JPQL (2)

    [JPA] JPQL (2)

    2022.12.28
  • [JPA] JPQL (1)

    [JPA] JPQL (1)

    2022.12.27
  • [JPA] 영속성의 전이와 고아 객체

    [JPA] 영속성의 전이와 고아 객체

    2022.12.24
  • [JPA] 프록시와 연관관계

    [JPA] 프록시와 연관관계

    2022.12.24
다른 글 더 둘러보기

정보

시간의화살 블로그의 첫 페이지로 이동

시간의화살

  • 시간의화살의 첫 페이지로 이동

검색

방문자

  • 전체 방문자
  • 오늘
  • 어제

카테고리

  • 분류 전체보기 (606)
    • Algorithm (205)
      • Data Structure (5)
      • Theory && Tip (33)
      • Baekjoon (166)
      • ALGOSPOT (1)
    • Spring (123)
      • Spring (28)
      • Spring Web MVC (20)
      • Spring Database (14)
      • Spring Boot (6)
      • Spring 3.1 (11)
      • Spring Batch (6)
      • Spring Security (16)
      • JPA (12)
      • Spring Data JPA (5)
      • QueryDSL (4)
      • eGovFramework (1)
    • Programming Language (74)
      • Java (19)
      • JavaScript (15)
      • C (25)
      • C++ (12)
      • Python (1)
      • PHP (2)
    • Computer Science (69)
      • Operating System (18)
      • Computer Network (17)
      • System Programming (22)
      • Universial Programming Lang.. (8)
      • Computer Architecture (4)
    • Database (21)
      • Database (7)
      • MySQL (3)
      • Oracle (3)
      • Redis (5)
      • Elasticsearch (3)
    • DevOps (20)
      • Docker && Kubernetes (8)
      • Jenkins (4)
      • Github Actions (0)
      • Amazon Web Service (8)
    • Machine Learning (28)
      • AI Introduction (28)
    • Mobile (28)
      • Android (21)
      • Flutter (7)
    • Solutions (13)
    • Life Logs (0)
    • 낙서장 (25)

최근 글

나의 외부 링크

메뉴

  • 홈

정보

13months의 시간의화살

시간의화살

13months

블로그 구독하기

  • 구독하기
  • RSS 피드

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. Copyright © 13months.

티스토리툴바