
값 타입이란 단순한 값으로 사용하는 자바 기본 타입이나 객체를 말하며, 식별자가 없고 값만 있으므로 변경 시 추적이 불가능하다는 특징이 있다.
값 타입은 크게 세 가지로 나뉜다.
int, double 등Integer, Long 등String특징:
String은 참조가 공유될 수 있으나, 불변성을 가진다.임베디드 타입은 새로운 값 타입을 정의하여 복합적인 값을 표현할 때 사용된다. 주로 기본 값 타입을 모아 하나의 객체로 만들어 활용하며, 복합 값 타입이라고도 한다.
@Embeddable
public class Address {
private String city;
private String street;
private String zipcode;
protected Address() {} // 기본 생성자 필수 ⭐
public Address(String city, String street, String zipcode) {
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
// Getter만 제공하여 불변 객체로 설계 ⭐
public String getCity() { return city; }
public String getStreet() { return street; }
public String getZipcode() { return zipcode; }
}
@Embeddable: 값 타입을 정의하는 곳에 표시@Embedded: 값 타입을 사용하는 곳에 표시(@Embeddable, @Embedded 둘 중 하나 넣으면 하나는 생략해도 된다)
null이면 매핑한 컬럼 값은 모두 null이 된다.Period.isWork())@AttributeOverrides, @AttributeOverride를 사용하여 컬럼명을 재정의해야 한다.@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@Embedded
private Address homeAddress;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "city", column = @Column(name = "work_city")),
@AttributeOverride(name = "street", column = @Column(name = "work_street")),
@AttributeOverride(name = "zipcode", column = @Column(name = "work_zipcode"))
})
private Address workAddress;
}
잘 설계한 ORM 애플리케이션은 매핑한 테이블의 수보다 클래임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 어떤 일이 벌어질까?
→ 부작용이 발생한다!
한 엔티티의 값 타입만 수정하려고 해도, 값을 공유하는 모든 엔티티에서 해당 값이 바뀌어버릴 수 있다.
복사해서 사용하면 되는 거 아닌가?
→ 문제는 임베디드 타입이 객체 타입이라는 점이다. 객체 타입은 참조 값을 공유하기 때문에 복사해서 사용하는 것이 의미가 없다.
그렇다면 어떻게 해결할까?
→ 불변 객체로 만들자! 불변 객체란 생성된 이후 값이 변경되지 않는 객체를 말한다.
💡불변 객체를 만드는 방법
- 생성자로만 값을 설정하고,
- Setter를 아예 만들지 않는다.
그럼 값을 어떻게 변경하지?
→ 값을 변경하려면 기존 객체를 수정하지 말고, 새로운 객체를 만들어 교체하는 방식으로 처리해야 한다.
값 타입은 인스턴스가 달라도 그 안에 값이 같으면 동일한 것으로 간주해야 한다.
==): 인스턴스의 참조 값을 비교한다.equals()): 인스턴스 내부의 값을 비교한다.→ 값 타입은 동등성 비교를 해야한다!
값 타입을 하나 이상 저장해야 하는 경우에는 값 타입 컬렉션을 사용할 수 있다.
@ElementCollection, @CollectionTable 사용값 타입 컬렉션 대신 일대다 관계를 고려하라!
→ 엔티티를 사용하며, 영속성 전이(CASCADE)와 고아 객체 제거(orphanRemoval)를 활용해 값 타입 컬렉션과 비슷한 방식으로 처리할 수 있다.
값 타입은 정말 값으로만 판단될 때 사용해야 한다.
엔티티(Entity)와 혼동하지 말고, 식별자 개념이 필요하거나 생명주기를 독립적으로 관리해야 한다면 반드시 엔티티를 사용하자.
📌 본 포스팅은 '인프런 - 김영한님 강의(자바 ORM 표준 JPA 프로그래밍 - 기본편)'를 듣고 정리한 내용입니다.