1️⃣ 엔티티 타입
@Entity
로 정의하는 객체2️⃣ 값 타입
int
, Integer
, String
처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체1️⃣ 기본값 타입
- 자바 기본 타입(int
, double
)
- 래퍼 클래스(Integer
, Long
)
- String
2️⃣ 임베디드 타입(embedded type, 복합 값 타입)
3️⃣ 컬렉션 값 타입(collection value type)
String name
, int age
📌 참고 : 자바의 기본 타입은 절대 공유 X
int
,double
같은 기본 타입(primitive type)은 절대 공유되지 X- 기본 타입은 항상 값을 복사함
- Integer같은 래퍼 클래스나 String 같은 특수한 클래스는 공유 가능한 객체이지만 변경 X
➡️ 회원 엔티티는 이름, 근무 시작일, 근무 종료일, 주소 도시, 주소 번지, 주소 우편번호를 가진다.
그러나 우리는 이렇게 표현할 수도 있다❗️
➡️ 회원 엔티티는 이름, 근무 기간, 집 주소를 가진다.
➡️ 이처럼 비슷한 필드를 하나의 타입으로 묶는 것을 임베디드 타입이라고 한다!
✔️ 특징**
✔️ 타입 사용법
@Embeddable
: 값 타입을 정의하는 곳에 표시@Embedded
: 값 타입을 사용하는 곳에 표시✔️ 임베디드 타입의 장점
Period.isWork()
처럼 해당 값 타입만 사용하는 의미 있는 메소드를 만들 수 있음📌 @AttributeOverride - 속성 재정의
🤔 : 만약 한 엔티티에서 같은 값 타입을 사용한다면 컬럼 명이 중복될 텐데..
😊 : 그럴 땐!@AttributeOverrides
,@AttributeOverride
를 사용해서 컬러 명 속성을 재정의하자!
📌 임베디드 타입과 null
- 임베디드 타입의 값이 null이면 매핑한 컬럼 값은 모두 null
값 타입은 복잡한 객체 세상을 조금이라도 단순화하려고 만든 개념❗️
따라서 값 타입은 단순하고 안전하게 다룰 수 있어야 한다😊
✔️ 값 타입 공유 참조
➡️ 임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험함
➡️ 부작용 발생!
✔️ 값 타입 복사
➡️ 값 타입의 실제 인스턴스인 값을 공유하는 것은 위험
➡️ 대신 값(인스턴스)를 복사해서 사용해야 함!
int a = 10;
int b = a; // 기본 타입은 값을 복사
b = 4;
➡️ 기본 타입
Address a = new Address(“Old”);
Address b = a; // 객체 타입은 참조를 전달
b.setCity(“New”)
➡️ 객체 타입
불변이라는 작은 제약으로 부작용이라는 큰 재앙을 막을 수 있다❗️
Setter
)를 만들지 않으면 됨📌 참고
Integer
,String
은 자바가 제공하는 대표적인 불변 객체
값 타입의 비교는, 인스턴스가 달라도 그 안에 값이 같으면 같은 것으로 봐야 한다❗️
int a = 10;
int b = 10;
➡️ 비교하면, True 반환
Address a = new Address(“서울시”)
Address b = new Address(“서울시”)
➡️ 비교하면, False 반환
💡 중요
- 동일성(identity) 비교
➡️ 인스턴스의 참조 값을 비교,==
사용- 동등성(equivalence) 비교
➡️ 인스턴스의 값을 비교,equals()
사용- 값 타입은
a.equals(b)
를 사용해서 동등성 비교를 해야 함- 값 타입의
equals()
메소드를 적절하게 재정의(주로 모든 필드 사용!)
값 타입을 컬렉션에 담아서 쓰는 것!!
📌 자세한 부분은 다음 시간인 실전 예제에서 다룰 예정임!
@ElementCollection
, @CollectionTable
사용해서 매핑📌 참고
값 타입 컬렉션은 영속성 전에(Cascade) + 고아 객체 제 거 기능을 필수로 가진다고 볼 수 있다!!
AddressEntity
➡️ Address 라는 값 타입을 하나 만들자!
Address
클래스 추가package jpabook.jpashop.domain;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.util.Objects;
@Embeddable
public class Address {
@Column(length = 10)
private String city;
@Column(length = 20)
private String street;
@Column(length = 5)
private String zipcode;
// 값 타입의 좋은 점 : 의미있는 메소드를 만들 수 있음
public String fullAddress() {
return getCity() + " " + getStreet() + " " + getZipcode();
}
public String getCity() {
return city;
}
private void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
private void setStreet(String street) {
this.street = street;
}
public String getZipcode() {
return zipcode;
}
private void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
@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(getCity(), address.getCity()) &&
Objects.equals(getStreet(), address.getStreet()) &&
Objects.equals(getZipcode(), address.getZipcode());
}
@Override
public int hashCode() {
return Objects.hash(getCity(), getStreet(), getZipcode());
}
}
➡️ setter
메소드는 모두 private
으로!
Member
클래스 수정package jpabook.jpashop.domain;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
import static javax.persistence.GenerationType.AUTO;
@Entity
public class Member extends BaseEntity {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
@Embedded
private Address address;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Embedded
private Address address;
⬆️ 위와 같이 한 줄만 추가해주면 자유롭게 사용 가능!
Delivery
클래스 수정package jpabook.jpashop.domain;
import javax.persistence.*;
import static javax.persistence.FetchType.*;
@Entity
public class Delivery extends BaseEntity {
@Id @GeneratedValue
private Long id;
@Embedded
private Address address;
private DeliveryStatus status;
@OneToOne(mappedBy = "delivery", fetch = LAZY)
private Order order;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public DeliveryStatus getStatus() {
return status;
}
public void setStatus(DeliveryStatus status) {
this.status = status;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
@Embedded
private Address address;
⬆️ 마찬가지로 위와 같이 한 줄만 추가해주면 자유롭게 사용 가능!
⬆️ 값 타입으로 만든 Address
정보가 Member
, Delivery
에 그대로 잘 반영된 것을 확인 👍🏻
소신 있는 내가 될테야