- 참조: 자바 ORM 표준 JPA 프로그래밍
- 값 타입
JPA 의 데이터 타입을 분류하면 엔티티 타입과 값 타입이 있다. 엔티티 타입은 @Entity 어노테이션으로 정의했던 객체들이고, 값 타입은 int, String 등 기본 타입이나 값으로 사용하는 객체를 말한다.
엔티티는 식별자가 있다. 우리는 어떤 사람이 자라면서 키나 몸무게가 달라진다고해서 그 사람을 다른사람이라고 인식하지 않는다. 반면 값은 100 에서 200 으로 변하면 완전히 다른 값이 된다. 이는 DDD에서 Value Object 와 Entity 를 구분하는 내용에도 등장하는 개념이므로 헷갈린다면 이번 기회에 이해해두도록 하자.
- 기본값 타입
@Entity
public class Member extends DateMarkable{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
private String city;
private String street;
private String zipcode;
기본값 타입은 너무 익숙하므로 간단하게 살펴보고 넘어가도록 하자. 위의 코드에서 name~zipcode 속성은 값 타입이다. id 식별자 값에 의존하여 생명주기를 가진다.
- 임베디드 타입
JPA 에서는 값 타입을 정의해서 사용할 수 있는데 이를 임베디드 타입이라고 한다.
@Entity
public class Member {
@Id
@Column(name = "USER_ID")
private String id;
private String userName;
@Temporal(TemporalType.DATE)
private Date startDate;
@Temporal(TemporalType.DATE)
private Date endDate;
private String city;
private String street;
private String zipcode;
위의 코드를 가장 단순하게 설명한다면 "회원 엔티티는 이름과 근무 시작일, 근무 종료일, 도시, 번지, 우편번호를 가진다." 라고 표현할 수 있다.
하지만 우리는 이정도로 단순하지는 않다. 좀더 축약해서 표현하면 "회원 엔티티는 이름과 근무기간, 주소정보를 가지고 있다." 라고도 말할 수 있다. 객체지향은 공통된 규칙과 부분을 추출해서 추상화를 하고 필요 없는 세부사항을 제거해야한다. 단순한 속성들을 타입으로 만들어 추상화시켜보자.
@Entity
public class Member {
@Id
@Column(name = "USER_ID")
private String id;
private String userName;
@Embedded
private Period perid;
@Embedded
private Address address;
Member 엔티티는 위와 같이 한눈에 알아보기 더 쉽게 변경되었다.
@Embeddable
public class Period {
@Temporal(TemporalType.DATE)
private Date startDate;
@Temporal(TemporalType.DATE)
private Date endDate;
..........
@Embeddable
public class Address {
@Column(name = "city")
private String city;
private String street;
private String zipcode;
@Embeddable 어노테이션을 이용하여 기간과 주소정보를 정의하면 된다. 이렇게 코드를 작성하면 응집력이 상당히 높아진다. 또한 각 타입에서 getter/setter 뿐만 아니라 의미 있는 메소드도 제공할 수 있다.
임베디드 타입은 기본 생성자가 필수이다. 임베디드 타입을 포함한 모든 값 타입은 엔티티의 생명주기에 의존하므로 UML 에서 컴포지션 관계가 된다.
위의 UML 에서 Period 와 Address 는 composition 관계이다. composition 은 aggregation 과 헷갈리는 경우가 많은데 가장 주요한 차이점은 생명주기의 의존성이다. Period 와 Address 는 Member 가 소멸하면 같이 소멸되므로 composition 이며, 만약 생명주기는 같이 하지는 않지만 관련성이 있다라고 표현하려면 aggregation 기호를 사용한다.
- 임베디드 타입과 연관관계
임베디드 타입은 값 타입을 포함하거나 엔티티를 참조할 수 있다. 아래는 값 타입 Zipcode 를 포함하는 Address 임베디드 타입이다.
@Embeddable
public class Address {
@Column(name = "city")
private String city;
private String street;
@Embedded
private Zipcode zipcode;.
.........
@Embeddable
public class Zipcode {
private String zip;
private String plusFour;
또한 임베디드 타입은 엔티티도 참조할 수 있다.
@Embeddable
public class PhoneNumber {
private String areaCode;
private String localNumber;
@ManyToOne
private PhoneServiceProvider provider;
.........
@Entity
public class PhoneServiceProvider {
@Id
private String name;
Member 에 위의 임베디드 타입을 포함시켜서 실행해보자.
@Entity
public class Member {
@Id
@Column(name = "USER_ID")
private String id;
private String userName;
@Embedded
private Period perid;
@Embedded
private Address address;
@Embedded
private PhoneNumber phoneNumber;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "TEAM_ID", referencedColumnName = "TEAM_ID")
private Team team;
@OneToMany(mappedBy = "member", fetch = FetchType.LAZY)
private List<Order> orders;
컬럼을 살펴보면 @Embedded 로 포함시킨 값 타입들의 Field 들이 Member 테이블에 포함되어있다.
그런데 @Embedded 로 여러 값 타입들을 포함시키다보면 중복된 Field 들이 있을 수 있다. 이럴 때에는 @AttributeOverride 어노테이션으로 속성을 재정의 해야 한다.
@Entity
public class Member {
@Id
@Column(name = "USER_ID")
private String id;
private String userName;
@Embedded
private 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"))
})
private Address companyAddress;
...............
@Embeddable
public class Address {
@Column(name = "city")
private String city;
private String street;
private String zipcode;
name 으로 해당 값 타입의 field 명을 참조하며, @Column 으로 테이블의 컬럼명을 설정한다.
'Framework and Tool > JPA' 카테고리의 다른 글
JPA - 값 타입 - 값 타입 컬렉션 (0) | 2021.07.25 |
---|---|
JPA - 값 타입 - 불변객체 (0) | 2021.07.22 |
JPA - 고급맵핑 - 요구사항 분석과 맵핑4 (0) | 2021.07.18 |
JPA - 영속성 전이와 고아 객체 (0) | 2021.07.17 |
JPA - 지연 로딩 (0) | 2021.07.16 |
댓글