Application/JPA

[JPA] 값 타입, 임베디드 타입, @Embeddable

반응형

자바 ORM 표준 JPA 프로그래밍

JPA의 데이터 타입을 크게 분류하면 엔티티 타입과 값 타입으로 나눌 수 있다.

 

엔티티 타입

@Entity로 정의하는 객체.

식별자(@Id)를 통해 지속해서 추적할 수 있음.

값 타입

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

엔티티 타입과는 달리 식별자가 없어 추적할 수 없다.

 

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

새로운 값 타입을 직접 정의해서 사용하는 타입.

@Entity // 엔티티 타입
public class Member {

    @Id
    @GeneratedValue
    private Long id;
    
    @Embedded
    private Period period;
    
}

@Embeddable // 값 타입 (임베디드 타입)
public class Period {

    private LocalDate startDate;
    
    private LocalDate endDate;
    
}

새로 정의한 값 타입들은 재 사용할 수 있고, 응집도도 매우 높다. (좀 더 객체지향적이고, 코드가 더 명확해질 수 있다.)

 

임베디드 타입을 사용하기 위한 어노테이션

@Embeddable: 값 타입을 정의하는 곳에 표시

@Embedded: 값 타입을 사용하는 곳에 표시

- 참고로 둘 중 하나는 생략해도 된다.

 

값 타입과 불변 객체

임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험하다.

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

따라서 값 타입은 불변 객체로 설계해야 한다.

 

불변 객체도 결국 객체라, 인스턴스의 참조 값 공유를 피할 수 없다. 하지만 참조 값을 공유한다 해도 인스턴스의 값을 수정할 수 없으므로 부작용이 발생하지 않는다.

@Embeddable
public class Address {

    private String city;
    
    protected Address() {
    
    }
    
    public Address(String city) {
        this.city = city;
    }
    
    public String getCity() {
       return this.city;
    }
    
}

위와 같이 생성자로만 값을 설정하고, 수정자 즉 Setter를 만들지 않으면 된다.

 

값 타입의 비교

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

- 동일성 비교: 인스턴스의 참조 값을 비교 (==)

- 동등성 비교: 인스턴스의 값을 비교, equals()

 

값 타입은 동등성을 비교해야한다. 따라서 값 타입의 equals() 메소드를 재정의해야 한다.

값 타입의 eqauls() 메소드를 재정의할 때는 보통 모든 필드의 값을 비교하도록 구현한다.

 

cf) equals()를 재 정의하면 hashCode()도 재 정의하는 것이 안전하다.

 

[이펙티브 자바 3판] 아이템 11. equals를 재정의하려거든 hashCode도 재정의하라

[Effective Java 3th Edition] Item 11. Always override hashCode when you override equals

madplay.github.io

반응형