실전예제6 - 값 타입 매핑

학습 페이지

Untitled

Address라는 값 타입 컬렉션을 만들어서 추가해보자. Delivery와 Member가 사용하고 있다.

package jpashop.domain;

import jakarta.persistence.Embeddable;
import lombok.Getter;

import java.util.Objects;

@Embeddable
public class Address {

    private String city;
    private String street;

    private String zipcode;

    public String getCity() {
        return city;
    }

    public String getStreet() {
        return street;
    }

    public String getZipcode() {
        return zipcode;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Address address)) return false;
        return Objects.equals(city, address.city) && Objects.equals(street, address.street) && Objects.equals(zipcode, address.zipcode);
    }

    @Override
    public int hashCode() {
        return Objects.hash(city, street, zipcode);
    }
}

위는 인텔리제이의 도움을 받아 생성한 게터와 equals()오버라이딩, 그리고 hashCode()오버라이딩한 값 타입이다. equals()의 오버라이딩 메서드에서 눈여겨 볼 것 들이 있다.

   @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Address address)) return false;
        return Objects.equals(city, address.city) && Objects.equals(street, address.street) && Objects.equals(zipcode, address.zipcode);
    }

우선 instanceof연산자를 이용해 1차적으로 걸러주고 있다. 이건 인텔리제이가 프록시 객체가 인자로 들어오는 상황을 대비해 알아서 instanceof연산자를 사용해준 것이다. 왜 instanceof를 써야하는지 지난 시간 배웠다.

240417(프록시)

Untitled

⚠️ 반면 인텔리제이가 잡아주지 못한 부분도 있다.

return Objects.equals(city, address.city) && Objects.equals(street, address.street) && Objects.equals(zipcode, address.zipcode);

equals를 비교하기 위해서 필드값 자체를 비교하고 있다. 그런데 만약 프록시객체가 equals의 대상이었다면 필드값 자체는 텅텅비어있어서 제대로된 equals()가 일어나지 않는다. 이 경우에는 반드시 getter를 이용한 비교로 바꿔줘야 한다.

 return Objects.equals(getCity(), address.getCity()) && Objects.equals(getStreet(), address.getStreet()) && Objects.equals(getZipcode(), address.getZipcode());

이렇게 getter를 이용해 비교하면 프록시더라도 getter가 원본 필드를 참조하도록 되어있어 제대로된 equals()비교가 된다.

이는 hashCode()도 마찬가지이다.