Be ready to study forever - 개발자 꿈나무
[JPA] 값 타입 본문
JPA의 데이터 타입 분류
JPA에서 분류하는 데이터 타입은 크게 볼 때 2가지가 있는데, 엔티티타입과 값타입이다. 값타입은 엔티티 객체에 속해 있는 값이라고 할 수 있다.(밑에 그림을 보면 이해가 아주 쉬움)
엔티티타입
- @Entity로 정의되어 있는 객체
- Id값이 있어서 추적이 가능
값타입
- 식별자가 없어서 값이 변해도 추적 X
- 자바에서 쓰이는 primitive type(int, double)이나 wrapper 클래스(Integer, Long, String)
값타입을 자세히 살펴보면 3가지로 나눌 수 있는데, 기본값타입, 임베디드 타입, 컬렉션 값 타입으로 나눌 수 있다. 큰 그림을 그림으로 보자면
엔티티타입(Entity type)과 값타입(value type)이 있고 값타입 밑에는 기본 값타입(basic type), 임베디드 타입(embedded type/composite type), 컬렉션 값타입(collection type)이 있다.
기본 값타입)
자바에서 사용하는 primitive type이나 wrapper class로 값을 표현하기 위해 존재하는 데이터 타입이다.
임베디드 타입)
집주소나, 생일(년,월,일) 같이 연관성이 깊은 데이터끼리 객체로 묶은 타입인데, 객체로 묶었지만 엔티티가 아니므로 연관관계와는 아무 상관이 없다(DB에는 값을 풀어서 하나한 칼럼으로 매핑 됨). 사용하는 이유는 별도의 메소드를 만들어 의미있게 사용이 가능하다. 만약에 임베디드 타입이 NULL이면 DB에 칼럼도 NULL로 저장된다.
임베디드 타입 사용법
- @Embeddable: 값타입을 정의하는 객체에 표시
- @Embedded: 값타입을 사용하는 곳에 표시
예제 코드를 보면
@Entity
public class Member {
...
@Embedded
private Address homeAddress;
@Embedded
private Address workAddress;
...
}
값타입을 사용하는 곳에는 @Embedded
@Embeddable
@NoArgsConstructor
public class Address {
private String city;
private String street;
private String zipcode;
...
}
@Embeddable
@NoArgsConstructor
public class Period {
private LocalDateTime startDate;
private LocalDateTime endDate;
...
}
값타입을 정의하는 곳에는 @Embeddable
만약에 임베디드 타입을 중복으로 사용하고 싶다면?
간혹 가다 임베디드 타입의 주소를 중복해서 집주소와, 직장주소 로 따로 사용하고 싶다면? 이럴경우 칼럼명이 중복되기 때문에 오류가 난다. 이것을 피하기 위해서 @AttributeOverrides, @AttributeOverride로 속성을 제정의 할 수 있는데
코드로 보자면
@Entity
public class Member {
...
@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;
...
}
처럼 재정의해서 DB의 칼럼에 매핑해 사용할 수 있다.
**주의할 점은 임베디드 타입은 자바의 reference타입이기 때문에 절대 다른 값과 공유 하면 안된다.(같은 주소값을 가르키기 때문에 한쪽을 바꾸면 공유한 쪽의 값도 바뀌어 DB에 저장됨)
따라서 공유할 수도 있는 문제점을 원천 봉쇄하기 위해서 이러한 값타입은 setter를 만들지 않고 생성자로만 값을 집어넣을 수 있게 하는 것이 바람직하다.
컬렉션 값 타입)
컬렉션 값타입은 값타입을 2개이상 저장 할 때 사용한다. 예를 들어 주소의 히스토리를 남기고 싶다던지 할 때 사용할 수가 있는데
그림과 같이 말이다.
@ElementCollection과 @CollectionTable 어노테이션을 사용해서 설정 할 수 있는데, 컬렉션은 기본적으로 DB에서 저장할 수 없으므로 별도의 테이블을 만들어야 한다. 그리고 몇가지 제약 사항이 더 있는데:
- 식별자가 없어서 변경시 추적이 어려움
- 값타입 컬렉션을 매핑하는 테이블은 그림과 같이 모든 칼럼을 묶어서 기본키로 사용하기 때문에 NULL이나 중복허용이 안됨
따라서 값타입 컬렉션을 사용하기 보다 일대다 관계로 매핑해서 고아객체를 삭제하는 것이 바람직하다.
'Programming > JPA' 카테고리의 다른 글
[JPA] JPQL (0) | 2021.01.24 |
---|---|
[JPA] 엔티티매핑 (0) | 2021.01.24 |
[JPA] 고급 매핑 - 3 (0) | 2021.01.23 |
[JPA] 다양한 연관관계 매핑-2 (0) | 2021.01.23 |
[JPA] 연관관계 매핑 기초 - 1 (0) | 2021.01.23 |