군만두의 IT 개발 일지

[스터디10] 09. 값 타입 본문

학습일지/Java

[스터디10] 09. 값 타입

mandus 2025. 8. 21. 01:25

목차

    9장. 값타입 

    JPA 데이터 타입은 엔티티 타입과 값 타입으로 나눌 수 있다.

     

    엔티티 타입:

    • @Entity로 정의하는 객체
    • 식별자, 생명주기가 있다. 공유할 수 있다.

    값 타입:

    • int, Integer, String처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체
    • 식별자가 없고, 생명주기를 엔티티에 의존한다. 공유하지 않는 것이 안전하다.

    9.1 기본값 타입

    • 자바에서 int, double 같은 기본 타입(primitive type)은 절대 공유되지 않는다.
    • Integer처럼 래퍼 클래스나 String 같은 특수한 클래스도 있다. 객체지만 자바 언어에서 지본 타입처럼 사용할 수 있게 지원되므로 기본값 타입으로 정의했다.

    9.2 임베디드 타입(복합 값 타입)

    • 새로운 값 타입을 직접 정의할 수 있는데, JPA에서는 임베디드 타입(Embedded Type)이라 한다.
    • int, String처럼 값 타입이다.
    • 사용하려면 2가지 중 하나의 어노테이션이 필요하다.
      • @Embeddable: 값 타입을 정의하는 곳에 표시
      • @Embedded: 값 타입을 사용하는 곳에 표시
    • 임베디드 타입을 포함한 모든 값 타입은 엔티티의 생명 주기에 의존하므로 엔티티와 임베디드 타입의 관계를 UML로 표현하면 컴포지션(Composition) 관계가 된다.

    9.2.3 @AttributeOverride: 속성 재정의

    임베디드 타입에 정의한 매핑정보를 재정의하려면 엔티티에 @AttributeOverride를 사용하면 된다.

    @Entity
    public class Member {
        @Id @GeneratedValue
        private Long id;
        private String name;
        
        @Embedded Address homeAddress;
        
        @Embedded
        @AttributeOverrides({
            @AttributeOverride(name="city", column=@Column(name="COMPANY_CITY")),
            @AttributeOverride(name="street", column=@Column(name="COMPANY_STREET")),
            @AttributeOverride(name="zipcode", column=@Column(name="COMPANY_ZIPCODE"))
        })
        Address companyAddress;
    }

    9.2.4 임베디드 타입과 null

    임베디드 타입이 null이면 매핑한 컬럼 값은 모두 null이 된다.

    9.3 값 타입과 불변 객체

    9.3.1 값 타입 공유 참조

    • 임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험하다.
    • 공유 참조로 인해 발생하는 버그는 찾아내기 어렵다.
    • 부작용(Side Effect): 뭔가를 수정했는데 전혀 예상치 못한 곳에서 문제가 발생하는 것

    9.3.2 값 타입 복사

    • 값 타입의 실제 인스턴스인 값을 공유하는 것은 위험하다.
    • 대신에 값(인스턴스)을 복사해서 사용해야 한다.
    • 객체의 공유 참조는 피할 수 없다. 단순한 방법은 객체의 값을 수정하지 못하게 막는 것이다.

    9.3.3 불변 객체

    객체를 불변하게 만들면 값을 수정할 수 없으므로 부작용을 원천 차단할 수 있다.

    • 값 타입은 불변 객체(Immutable Object)로 설계해야 한다.
    • 불변 객체를 구현하는 가장 간단한 방법은 생성자로만 값을 설정하고 수정자를 만들지 않는 것이다.

    9.4 값 타입의 비교

    자바가 제공하는 객체 비교는 2가지다.

    • 동일성(Identity) 비교: 인스턴스의 참조 값을 비교, == 사용
    • 동등성(Equivalence) 비교: 인스턴스의 값을 비교, equals() 사용
    • 값 타입은 a.equals(b)를 사용해서 동등성 비교를 해야 한다. 물론 equals() 메소드를 적절하게 재정의해야 한다.

    9.5 값 타입 컬렉션

    값 타입을 하나 이상 저장하려면 컬렉션에 보관하고 @ElementCollection, @CollectionTable 어노테이션을 사용한다.

    • 관계형 데이터베이스의 테이블은 컬럼 안에 컬렉션을 포함할 수 없다.
    • 따라서 별도의 테이블을 추가하고 @CollectTable를 사용해서 추가한 테이블을 매핑해야 한다.
    • @CollectTable를 생략하면 기본값을 사용해서 매핑한다.

    9.5.1 값 타입 컬렉션 사용

    • 값 타입 컬렉션도 조회할 때 페치 전략을 선택할 수 있는데, 기본이 LAZY다.
    • 값 타입 컬렉션은 영속성 전이(Cascade) + 고아 객체 제거(ORPHAN REMOVE) 기능을 필수로 가진다.

    9.5.2 값 타입 컬렉션의 제약사항

    • 엔티티는 식별자가 있으므로 엔티티의 값을 변경해도 식별자로 데이터베이스에 저장된 원본 데이터를 쉽게 찾아서 변경할 수 있다.
    • 값 타입은 식별자라는 개념이 없고, 값을 변경하면 데이터베이스에 저장된 원본 데이터를 찾기 어렵다.
    • JPA 구현체들은 값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 데이터베이스에 모두 다시 저장한다.
    • 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본키를 구성해야 한다. (기본 키 제약 조건으로 null 입력X, 중복 저장X)
    • 영속성 전이(Cascade) + 고아 객체 제거를 사용해서 값 타입 컬렉션처럼 사용할 수 있다.

     

    ✔️ 복습하기
    1. 임베디드 타입을 사용할 때 필요한 애노테이션 2개는?
    2. 값 타입을 불변 객체로 만드는 이유는?
    3. 값 타입 컬렉션의 제약사항은?

     

    이 글은 『 자바 ORM 표준 JPA 프로그래밍』 책을 학습한 내용을 정리한 것입니다.

     

    Comments