JPA의 데이터 단위는 최상위로 분류하면 두 가지로 분류한다.
값 타입은 크게 3가지로 나누어 볼 수 있다.
String name, int age
위의 예시는 기본 값 타입이다.
기본 값 타입은 생명주기를 엔티티에 의존한다.
값 타입은 공유하면 안된다.
int, double 등 자바의 기본 타입(primitive type)은 절대 공유하면 안된다.
기본 타입은 항상 값을 복사하지 공유되는 것이 아니다.
래퍼클래스나 String같은 클래스는 공유가 가능한 객체이지만 변경 자체가 불가능하다.
새로운 값 타입을 직접 정의할 수 있다.
이렇게 새롭게 정의하는 타입을 JPA는 임베디드 타입(Embedded type)이라고 한다.
임베디드 타입은 엔티티가 아니라 값 타입이라는 것 주의하자.
회원이 상세한 데이터를 그대로 가지고 있는 것은 객체지향적이지 않으며 응집력만 떨어뜨린다.
// 임베디드 타입 사용하지 않았을 때
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
//프로필
private String bio;
private String uri;
private String image;
....등
}
// 임베디드 타입 사용
@Entity
public class Member {
@Id @GeneratedVAlue
private Long id;
private String name;
@Embedded
private Profile profile; // 프로필
}
이렇게 프로필 타입이 있다면 코드가 더 명확해 진 것을 볼 수 있다.
@Embeddable을 값 타입을 정의하는 곳에 표시한다.@Embedded을 값 타입을 사용하는 곳에 표시한다.임베디드 타입은 엔티티의 값일 뿐이다.
@AttributeOverride : 속성 재정의
이런 경우에 @AttributeOverrides와 @AttributeOverride를 사용해서 컬럼 명 속성을 재정의 할 수 있다.
임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험하다.
하지만 임베디드 타입 처럼 직정 정의한 값은 자바의 기본 타입이 아닌 객체이다.
자바 기본 타입에 값을 대입하면 값을 복사하지만, 객체 타입은 참조 값을 직접 대입하는 것을 막을 수 없다.
객체의 공유 참조는 피할 수 없는 것이다.
//기본 타입(primitive type)
int a = 10;
int b = a; //기본 타입은 '값'을 복사
b = 4; //a에게는 아무 영향이 없다 a는 그대로 10
//하지만 객체 타입의 경우
Address a = new Address("Old");
Address b = a; //객체 타입이므로 참조를 전달한다.
b.setCity("newCity"); //a,b 둘다 바뀌게 된다. 같은 인스턴스를 공유하고 있기 때문에
그래서 객체 타입을 수정할 수 없게 값 타입은 불변 객체로 설계하도록 하자.
참고로 Integer와 String은 자바가 제공하는 대표적인 불변 객체이다.
값 타입을 하나 이상 저장할 때 사용한다.
@ElementCollection, @CollectionTable을 사용한다.
실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 사용하는 것을 고려하자.
(일대다 관계를 위한 엔티티를 만들고, 여기에서 값타입을 사용)
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard 김영한 님의 JPA 프로그래밍 강의
https://book.naver.com/bookdb/book_detail.nhn?bid=9252528 자바 ORM 표준 JPA 프로그래밍
위의 책을 참고하고, 강의를 수강하면서 작성한 글입니다.
틀린 부분 등 다양한 피드백 환영합니다.