값 타입

Jaca·2021년 8월 24일
0

JPA의 데이터 타입

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

  • 엔티티 타입 :
    • @Entity로 정의하는 객체
    • 데이터가 변해도 식별자로 지속해서 추적 가능
  • 값 타입 :
    • int, Integer, String처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체
    • 식별자가 없고 값만 있으므로 변경시 추적 불가

엔티티는 이제까지 많이 다뤄왔으므로 어느정도 친숙할 것이고, 값 타입에 대해 좀더 알아보자.
값 타입은 또 세가지 타입으로 나누어진다.

  • 기본 값 타입 : 자바 기본 타입, 래퍼 클래스 , String
  • 임베디드 타입 : 복합 값 타입
  • 컬렉션 타입

기본 값 타입

일단 먼저 얘기하고 가자면, 값 타입은 절대 공유가 되선 안된다.
한 데이터를 수정하려는데 값 타입이 공유되고 있다면, 의도치 않게 다른 데이터도 변경될 수 있다.

기본 값 타입은 자바의 Primitive type에 경우 별 걱정이 없다.
자바의 정석에서 보았듯 기본타입은 항상 값을 복사하기때문에 공유되지가 않기 때문이다.

Integer같은 래퍼 클래스나 String 같은 특수한 클래스는 공유 가능한 객체이지만 변경이 되지 않으므로 걱정할 필요가 없다.

임베디드 타입

새로운 값 타입을 직접 정의할 수 있다.

처음 자바를 공부할 때 class를 통해 c의 구조체처럼 만드는 것을 경험한 기억이 났다.

구조체를 만드는 것을 JPA는 임베디드 타입이라고 한다.

주로 기본 값 타입을 모아서 만들어서 복합 값 타입이라고도 한다.

임베디드 타입의 사용법은 아래와 같다.

  • @Embeddable: 값 타입을 정의하는 곳에 표시
  • @Embedded : 값 타입을 사용하는 곳에 표시
  • 기본 생성자가 필수

기존에 Member 클래스에 있던 startDate, endDate 를 Period 클래스로 빼주고, city, street, zipcode 를 Address로 빼준다.
이는 임베디드 타입을 정의 한 곳이니 @Embeddable 를 붙혀준다.

임베디드 타입은 엔티티의 값일 뿐이다.
이러한 매핑은 굳이 값 타입으로 빼지 않았을 때의 테이블 구조에 전혀 영향이 없다.
오히려 객체와 테이블을 아주 세밀하게 매핑하는 것이 가능하며,
잘 설계한 ORM 애플리케이션은 매핑한 테이블 수 보다 클래스의 수가 더 많다.

@AttributeOverride: 속성 재정의

만약 한 엔티티에서 같은 값 타입을 하려고 하면 어떻게 해야할까?
@AttributeOverrides, @AttributeOverride를 사용해서 컬러 명 속성을 재정의해준다.

address와 동일한 값 타입을 사용하는 workAddress를 생성했다.

불변 객체

수업에서는 이 부분에 대해 자세한 예시들을 보여주며 설명해주시는데,
자바의 정석을 보고있던 터라 아주 쉽게 이해되어 자세한 부분은 생략하고 큰 틀만 적고 넘어가자

일단 값 타입이 공유된다면 어떻게 되는지 보자.

당연한 결과. 참조 변수로 같은 객체를 가지고 있으니, city값을 변경해주니 둘다 변경되었다.
이러한 결과는 당연히 피해야 한다.

이를 위해 막기 불변 객체로 만들어 주는 것이다.

불변 객체로 만들기 위해서는 어떻게 해야할까?

말은 거창하지만 간단하다.
주석 처리된 부분 처럼 값을 복사하여 다른 객체를 생성하여 넣어주며,
생성자로만 값을 설정하고 수정자(Setter)를 만들지 않으면 된다.

컬렉션 타입

이름만 봐도 알 수 있듯이, 값 타입을 여러개 가지기 위해 컬렉션으로 구성하는 것이다.

@ElementCollection, @CollectionTable 를 사용한다.
데이터베이스는 컬렉션을 같은 테이블에 저장할 수 없다.
컬렉션을 저장하기 위한 별도의 테이블로 생성된다.

값 타입 컬렉션은 기본적으로 지연 로딩 전략을 사용하며, 영속성 전이(Cascade) + 고아 객체 제거 기능을 필수로 가진다고 볼 수 있다.

favorite_food 테이블을 보면 외래키인 MEMBER_ID와 값을 저장하는 FOOD_NAME 필드만 있는 것을 볼 수있다.
이 처럼 값 타입은 엔티티와 다르게 식별자의 개념이 없다.
그 말은 값을 변경하면 추적이 어렵다는 뜻이다.

또 컬렉션 타입의 치명적인 단점이 있는데, 변경 사항이 발생하면 테이블을 아예 삭제하고 새로 테이블을 구성한다는 것이다.

그래서 컬렉션 타입의 대안이 필요한데, 실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계의 엔티티를 사용할 것을 고려한다.

엔티티 내에 값 타입을 사용하고, 영속성 전이(cascade) + 고아 객체 제거를 사용해서 값 타입 컬렉션 처럼 사용하는 것이다.


주석 처리된 기존의 값 컬렉션을.. 아래의 엔티티를 생성해서 바꿔줌

엔티티 타입과 값 타입을 잘 판단해서 사용하자.

  • 엔티티 타입
    • 식별자 O
    • 생명 주기 관리
    • 공유 가능
  • 값 타입
    • 식별자 X
    • 생명 주기를 엔티티에 의존
    • 공유하면 안됨, 복사해서 사용하자
    • 불변 객체로 만들 것

값 타입은 정말 값 타입이라 판단될 때만 사용하자,
엔티티와 값 타입을 혼동해서 엔티티를 값 타입으로 만들면 안된다.
식별자가 필요하고, 지속해서 값을 추적, 변경해야 한다면 그것 은 값 타입이 아닌 엔티티이다.

profile
I am me

0개의 댓글