엔티티타입은 식별자를 통해 지속적으로 추적이 가능하지만 값 타입은 식별자가 없고 숫자나 문자 같은 속성만 있으므로 추적이 불가하다.
값 타입은 의도치 않은 수정이 발생 할 수 있으므로 절대 공유하면 안된다.
@Entity
class Member{
@Id
private Long id;
private String name;
private int age;
}
2. 임베디드 타입(복합 값 타입)
새로운 값 타입을 직접 정의해서 JPA에서 사용하는 것을 임베디드 타입이라 한다.
직접 정의한 임베디드 타입도 int, String 처럼 값 타입이다.
예제를 살펴보면
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@Embedded Period workPeriod; // 근무기간
@Embedded Address homeAddress; // 집주소
...
}
// 근무기간 임베디드 타입
@Embeddable
public class Period {
@Temporal(TemporalType.DATE) Date startDate;
@Temporal(TemporalType.DATE) Date endDate;
...
public boolean isWork(Date date) {
// 값 타입을 위한 메소드 정의
}
}
// 집주소 임베디드 타입
@Embeddable
public class Address {
@Column(name="city") // 매핑할 컬럼 정의 가능
private String city;
private String street;
private String zipcode;
}
startDate, endDate를 합해 Period 클래스를 만들었다.
city, street, zipcode를 합해 Address 클래스를 만들었다.
새로 정의한 값 타입들은 재사용할 수 있고 응집도도 매우 높다. (재사용 할 수도 있고, Period.isWork()처럼 해당 값 타입만을 위한 메소드도 정의 가능하다.)
임베디드 타입을 사용하려면 2가지 어노테이션이 필요하다.(@Embeddable : 정의하는 곳, @Embedded : 사용하는 곳) 둘 중하나는 생략 가능하다.
기본 생성자가 필수다.
모든 값 타입(임베디드 타입 포함)은 엔티티 생명주기에 의존하므로 엔티티와 임베디드 타입의 관계를 UML로 표현하면 컴포지션 관계가 된다.
하이버네이트는 임베디드 타입을 컴포넌트라 표현한다.
2.1 임베디드 타입과 테이블 매핑
임베디드 타입은 그냥 값을 뿐이므로 당연히 임베디드 타입을 사용하기 전과 후에 매핑하는 테이블은 같다.
임베디드 타입이 없다면 1:1로 매핑(하나에 테이블에 하나의 클래스를 매핑)해야 하지만 JPA를 사용하면 좀 더 객체지향적으로 매핑 할 수 있다.
잘 설계한 ORM 애플리케이션은 매핑한 테이블의 수보다 클래스의 수가 더 많다.
2.2 임베디드 타입과 연관관계
임베디드 타입은 값 타입을 포함하거나 엔티티를 참조할 수 있다.
2.3 @AttirubteOverride: 속성 재정의
예를 들어 회원에게 주소가 하나더 필요하다면? (회사주소, 집주소를 같은 임베디드 타입을 가지고 표현하고 싶다.)
// 같은 임베디드 타입을 하나더 가지고 있는 회원
@Entity
public class Member {
...
@Embedded Address homeAddress;
@Embedded Address companyAddress;
}
// 임베디드 타입 재정의
@Entity
public class Member {
...
@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;
}
CREATE MEMBER (
...
city varchar(255),
street varchar(255),
zipcode varchar(255),
COMPANY_CITY varchar(255),
COMPANY_STREET varchar(255),
COMPANY_ZIPCODE varchar(255),
...
)
9. 값 타입
1. 기본값 타입
2. 임베디드 타입(복합 값 타입)
@Embeddable
: 정의하는 곳,@Embedded
: 사용하는 곳) 둘 중하나는 생략 가능하다.2.1 임베디드 타입과 테이블 매핑
2.2 임베디드 타입과 연관관계
2.3
@AttirubteOverride
: 속성 재정의2.4 임베디드 타입과 null
3. 값 타입과 불변 객체
3.1 값 타입 공유 참조
3.2 값 타입 복사
3.3 불변 객체
@AllArgsConstructor
,@NoArgConstructor
4. 값 타입의 비교
@EqualsAndHashcode
)5. 값 타입 컬렉션
@ElementCollection
으로 값 타입 컬렉션을 지정하고@CollectionTable
로 해당 값들을 저장한 테이블을 알려주는데 name 속성으로 테이블명을 joinColumns 속성으로 외래키를 지정해준다.@CollectionTable
를 사용해서 추가한 테이블에 매핑하면 된다.@Column
을 사용해서 컬럼명을 지정할 수 있다.@AttributeOverride
를 사용해서 재정의할 수 있다.@ColletionTable
을 생략하면 {엔티티이름}_{컬렉션 속성 이름}을 사용해서 매핑한다.5.1 값 타입 컬렉션 사용
@ElementCollection(fetch = FetchType.LAZY
))5.2 값 타입 컬렉션의 제약사항