값 타임

2022. 3. 3. 17:41·개발/JPA
반응형

2023. 02.07 17:00 복습 및 정리 시작

 

JPA는 데이터 타입을 크게 두 분류로 나눌 수 있다.

엔티티 타입

@Entity로 정의하는 객체다. 데이터가 변해도 식별자로 지속해서 추적이 가능하다.

회원 엔티티의 키나 나이 값을 변경해도 식별자로 인식 가능하다. 

값 타입

int, Integer, String처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체다.

숫자 100을 200으로 변경하면 완전히 다른 값으로 대체된다.

값 타입은 또 크게 3가지로 나눌 수 있다.

 

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

이제 차근 차근 알아보겠다. 우선 아래 예제 코드를 살펴보자.

@Entity
public class Member{
    @Id @GeneratedValue
    private Long id;
    
    private String name;
    private int age;
    
    //주소
    private String city;
    private String street;
    private String zipcode;
}

기본 값 타입

  • 위 코드에서는 String name, int age 변수가 기본 값 타입이다.
  • 생명주기를 엔티티에 의존한다. 
  • 값 타입은 공유하면 안 된다. 
  • 다른 회원 엔티티의 이름을 변경한다고 해서 나의 이름까지 변경되는 것은 잘못되었기 때문이다.

임베디드 타입

위 예제 코드에서 주소를 나타내는 필드들이 있다.

멤버가 상세한 데이터를 가지고 있는 것은 객체지향적이지 않으며 응집력만 떨어뜨린다.

이제 새로운 값 타입을 직접 정의해서 사용하는 임베디드 타입을 사용해보겠다.

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

회원 엔티티 코드는 아래와 같이 수정하면 임베디드 값 타입을 사용할 수 있다.

@Entity
public class Member{
    @Id @GeneratedValue
    private Long id;
    
    private String name;
    private int age;
    
    @Embedded Address homeAddress; //집 주소
}

임베디드 타입(복합 값 타입) 정리

  • 새로운 값 타입을 직접 정의할 수 있다.
  • 주로 기본 값 타입을 모아서 복합 값 타입이라고 한다. int, String과 같은 값 타입.
  • @Embeddable : 값 타입을 정의하는 곳에 표시
  • @Embedded : 값 타입을 사용하는 곳에 표시
  • 기본 생성자는 필수다.

장점

  • 재사용을 자주하며 높은 응집도를 가지게 된다.
  • 해당 값 타입만 사용하는 의미 있는 메소드를 만들 수 있다.
  • 임베디드 타입을 포함한 모든 값 타입은, 값 타입을 소유한 엔티티에 생명주기를 의존한다.

임베디드 타입과 테이블 매핑

  • 임베디드 타입은 엔티티의 값일 뿐이다.
  • 임베디드 타입을 사용하기 전과 후에 매핑하는 테이블은 같다.
  • 객체와 테이블을 아주 세밀하기 매핑하는 것이 가능하다.
  • 잘 설계한 ORM 애플리케이션은 매핑한 테이블의 수보다 클래스의 수가 더 많다.
  • 임베디드 타입에 정의한 매핑정보를 재정의하려면 엔티티에 @AttributeOverride를 사용하면 된다.
  • 임베디드 타입의 값이 null이면 매핑한 컬럼 값은 모두 null이다.

값 타입과 불변 객체

값 타입은 복잡한 객체 사상을 조금이라도 단순화하려고 만든 개념이다.

따라서 값 타입은 단순하고 안전하게 다룰 수 있어야 한다.

임베디드 타입 값 타입을 여러 엔티티에서 공유하면 위험하다. 부작용이 발생할 수도 있다.

아래와 같은 예시가 있을 수 있겠다.

값 타입 공유 참조

값 타입의 실제 인스턴스인 값을 공유하는 것은  매우 위험하다.

따라서 값을 복사해서 사용하자.

 

항상 값을 복사해서 사용하면 공유 참조로 인해 발생하는 부작용을 피할 수 있지만,

문제는 임베디드 타입처럼 직접 정의한 값 타입은 자바의 기본 타입이 아니라 객체 타입이다. 즉 주소를 참조한다.

자바 기본 타입에 값을 대입하면 값을 복사하지만, 객체 타입은 참조 값을 직접 대입하는 것을 막을 방법이 없다.

따라서 객체의 공유 참조는 피할 수 없다.

불변 객체

값 타입은 부작용 걱정 없이 사용할 수 있어야 한다. 부작용이 일어나면 값 타입이라 할 수 없다.

객체를 불변하게 만들면 값을 수정할 수 없으므로 부작용을 원천 차단할 수 있다. 따라서 값 타입을 될 수 있으면 불변 객체로 설계해야 한다.

불변 객체를 구현하는 다양한 방법이 있지만 가장 간단한 방법은 생성자로만 값을 설정하고 수정자를 만들지 않으면 된다.

이러면 불변이라는 작은 제약으로 부작용이라는 큰 재앙을 막을 수 있다.

Integer, String은 자바가 제공하는 대표적인 불변 객체다.

값 타입 비교

값 타입은 인스턴스가 달라도 그 안에 값이 같으면 같은 것으로 봐야 한다.

 

  • 동일성 비교 : 인스턴스의 참조 값을 비교, == 사용
  • 동등성 비교 : 인스턴스의 값을 비교, equals() 사용
  • 값 타입은 a.equals(b)를 사용해서 동등성 비교를 해야 함
  • 값 타입의 equals() 메소드를 적절하게 제정의(오버 라이딩)해서 사용하자.

값 타입 컬렉션

아래는 임베디드 타입을 하나 이상 가지고 싶어서 컬렉션에 보관한 케이스다.

값 타입 컬렉션

@ElementCollection과 @CollectionTable를 사용하면 값 타입 하나 이상을 컬렉션에 저장할 수 있다.

데이터베이스는 컬렉션을 같은 테이블에 저장할 수 없으며, 컬렉션을 저장하기 위한 별도의 테이블이 생긴다.

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

 

값 타입 컬렉션의 제약사항은 아래와 같다.

 

  • 값 타입은 엔티티와 다르게 식별자 개념이 없다.
  • 값은 변경하면 추적이 어렵다.
  • 값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고,
    값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다.
  • 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본키를 구성해야 한다. null 입력 X, 중복 저장 X.

이런 제약사항이 있으므로 실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 고려해야 한다고 한다.

일대다 관계를 위한 엔티티를 만들고, 여기에서 값 타입을 사용한다.

영속성 전이 + 고아 객체 제거를 사용해서 값 타입 컬렉션처럼 사용한다.

정리

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

 

참고자료

 

자바 ORM 표준 JPA 프로그래밍 - 김영한

자바 ORM 표준 JPA 프로그래밍 강의 - https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com

 

2023. 02.07 17:40 복습 및 정리 마무리

 
반응형
'개발/JPA' 카테고리의 다른 글
  • JPQL 중급 문법
  • JPQL 기본 문법
  • 영속성 전이, 고아 객체
  • 프록시, 즉시 로딩과 지연 로딩
Debin
Debin
공부 기록을 남기며 게시글 리팩토링을 진행하는 블로그입니다.
  • Debin
    리팩토링하는 블로그
    Debin
  • 전체
    오늘
    어제
    • 분류 전체보기
      • DB
        • DB 기초
        • MySQL
        • SQL 튜닝
      • OS
      • Network
      • Git
      • 디지털콘텐츠기획
      • 소프트웨어공학
      • 코딩테스트
        • 프로그래머스
        • 백준
        • 인프런
      • 공부 일지
      • 독서
        • 클린코드
        • 일상 속 사물이 알려주는 웹 API 디자인
        • 토비의 스프링
        • 객체지향의 사실과 오해
        • 자바 잘 읽는 법
      • 기록 및 회고
      • Cloud
        • AWS
      • 개발
        • Java
        • Spring Core
        • Spring MVC
        • Spring DB
        • Spring Boot
        • Spring Security
        • Spring Batch
        • JPA
        • Test
        • Android
      • 대외활동
        • UMC SERVER
        • 카엔프 SW 아카데미
      • 프로젝트
      • Docker
      • Gradle
      • ELK
      • 실무 이야기
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

    • 본인 깃허브입니다!
  • 인기 글

  • 태그

    프록시
    spring mvc
    토비의 스프링
    스프링
    docker
    AOP
    도커
    Java
    스프링 부트
    mysql
    container
    컨테이너
    트랜잭션
    데이터베이스
    innodb
    test
    AWS
    운영체제
    JPA
    redis
    SQL
    객체
    인덱스
    객체지향
    ORM
    spring boot
    코딩 #개발자 #노마드북클럽 #노개북
    리눅스
    자바
    spring
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
Debin
값 타임
상단으로

티스토리툴바