JPA의 데이터 타입은 크게 2가지로 나뉜다. (엔티티 타입/ 값 타입)
값 타입
→ 3가지로 또 나뉨
새로운 값 타입을 직접 정의할때 임베디드 타입을 사용한다. → 직접 정의한 값타입
private Long id;
private String name;
@Temporal(TemporalType.Date) java.util.Date startDate;
@Temporal(TemporalType.Date) java.util.Date endDate;
private String city;
private String street;
private String zipcode;
위 코드에서는 엔티티가 이름, 근무 시작일, 근무 종료일, 주소도시, 주소 번지, 주소 우편번호를 가진다.
→ 단순한 정보를 풀어놓은 것. (근무 시작일과 주소는 아무런 관계가 없음)
private Long id;
private String name;
@Embedded Period workPeriod; //근무 기간
@Embedded Address homeAddress; //집 주소
@Embeddable
public class Period {
@Temporal(TemporalType.DATE) java.util.Date startDate;
@Temporal(TemporalType.DATE) java.util.Date endDate;
}
@Embeddable
public class Address {
@Column(name="city") //매핑할 컬럼 정의 가능
private String city;
private String street;
private String zipcode;
}
‼️ 임베디드 타입을 포함한 모든 값타입은 엔티티의 생명주기에 의존 (임베디드 타입의 관계를 UML로 표현 하면 컴포지션 관계가 됨)
임베디드 타입에 정의한 매핑정보를 재정의하고 싶다면 @AttributeOverride를 사용하면 된다.
@Embedded Address homeAddress;
@Embedded Address companyAddress;
->
@Embedded Address homeAddress;
@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;
임베디드 값타입을 여러 엔티티에서 공유하면 위험 하므로 복사해서 사용하자.
값 타입 복사
값 타입의 실제 인스턴스 값을 공유하는 것은 위험하므로 값을 복사해서 사용해야 한다.
member1.setHomeAddress(new Address("OldCity");
Address address = member1.getHomeAddress();
//회원 1의 address 값을 복사해 새로운 newAddress 값을 생성
Address newAddress = address.clone();
newAddress.setCity("NewCity");
member2.setHomeAddress(newAddress);
address는 객체 값이므로 대입시 참조값을 전달해 값타입과 다르게 인스턴스를 공유하게 된다.
따라서 clone을 사용해 복사를 하자.
불변객체
값 타입은 부작용 걱정없이 사용해야 하므로 객체를 불변하게 만들어 수정할 일을 없애준다.