1 밸류 클래스 특징
- 밸류는 개념적으로는 한 개의 값을 표현한다.
- 다른 밸류 객체와 구분하기 위한 식별자를 갖지 않는다.
- 자신만의 라이프사이클을 갖지 않는다. 밸류는 자신이 속한 객체가 생성될 때 함께 생성되고 삭제될 때 함께 삭제된다.
- 밸류 객체를 사용하는 이유는 값의 의미를 더 잘 드러내기 때문이다.
2. 밸류 클래스의 구현
- 생성 시점에 모든 프로퍼티를 파라미터로 전달 받는다.
- 읽기 전용 프로퍼티만 제공한다.
- 각 프로퍼티의 값을 비교하도록 equals() 메소드를 재정의 한다.
- 각 프로퍼티의 값을 이용해서 해시코드를 생성하도록 hashCode() 메소드를 재정의 한다.
3. @Embeddable 어노테이션과 @Embedded 어노테이션을 이용한 밸류 매핑
// 호텔 클래스
@Entity
@Table(name = "r_hotel")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Hotel {
@Id
private String id;
private String name;
@Enumerated(EnumType.STRING)
private Grade grade;
@Embedded // 매핑 대상에는 @Embeddable를 추가한다.
private Address address;
}
// 주소 클래스
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Embeddable
public class Address {
private String zipcode;
private String address1;
private String address2;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Address address = (Address) o;
return Objects.equals(zipcode, address.zipcode) &&
Objects.equals(address1, address.address1) &&
Objects.equals(address2, address.address2);
}
@Override
public int hashCode() {
return Objects.hash(zipcode, address1, address2);
}
}
// 테스트 클래스
class HotelTest {
@Test
public void test2() {
EMF.init();
EntityManager em = EMF.createEntityManager();
EntityTransaction transaction = em.getTransaction();
try {
transaction.begin();
Address address = Address.builder()
.zipcode("08393")
.address1("서울시 구로구")
.address2("구로동 1128-1")
.build();
Hotel hotel = Hotel.builder()
.id("H001")
.name("베스트웨스턴 구로호텔")
.grade(Grade.STAR5)
.address(address)
.build();
em.persist(hotel); // 데이터 저장
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e; // 예외 전달 필요 !!
} finally {
em.close();
}
}
@Test
public void test() {
EMF.init();
EntityManager em = EMF.createEntityManager();
EntityTransaction transaction = em.getTransaction();
try {
transaction.begin();
Hotel hotel = em.find(Hotel.class, "H001");
System.out.println("hotel :" + hotel);
Address address = hotel.getAddress();
System.out.println(address.getAddress1());
System.out.println(address.getAddress2());
System.out.println(address.getZipcode());
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e; // 예외 전달 필요 !!
} finally {
em.close();
}
}
}
4. @Entity와 @Embeddable의 라이프사이클
- @Embedded로 매핑한 객체는 엔티티와 동일한 라이프사이클을 갖는다.
- 엔티티를 저장하고 수정하고 삭제할 때, 엔티티에 속한 @Embeddable 객체도 함께 저장되고 수정되고 삭제된다.