병원 이름
, 병원 전화번호
와 같은 각 값이 의미하는바가 다른 필드가 있는 반면 위도
,경도
,시/도
,...,번지 주소
와 같이 주소에 대한 정보들로 일루어진 필드들도 있다. @Entity
어노테이션으로 엔티티로 정의한 객체 타입PK
를 통하여 식별 가능임베디드 타입
(복합 값 타입)컬렉션 값 타입
(여러 이유로 사용하지 않을 것임, 1:N 연관관계로 대체)엔티티의 생명주기에 의존
한다.공유해서는 안된다.
복사
한다.여러 값 타입을 합쳐서 하나의 임베디드 타입으로 새로운 값 타입으로 정의하여 사용
주소
와 영업시간
정도를 값 타입으로 만들 수 있을 것이다.재사용
이 가능한 값 타입이 된다.엔티티
가 아니라 임베디드 타입
에 있으므로, 높은 응집도
를 갖는다.@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class Address {
private String sido; //서울
private String siqungu; //서대문구
private String bname; //북가좌동
private String jibunAddress; //서울 서대문구 북가좌동 328-51
private String roadAddress; //서울 서대문구 증가로29길 20-14
private String sangse;
private double x;
private double y;
private Long bCode;
}
@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Hospital extends TimeStamped {
//1. PK / 2. 자동으로 값 생성(아이덴티티 전략 -> 디비가 생성)
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long hosId;
private String hosName;
private String hosPhone;
@Embedded
private Address hosAddress;
// ...
}
엔티티
와 임베디드 타입
클래스 간 다이어그램은 다음과 같다."잘 설계한 ORM 애플리케이션은 매핑한 테이블의 수보다 클래스의 수가 더 많음"
김영한 - 자바 ORM 표준 JPA 프로그래밍 - 기본편
null
이면 안에 있는 컬럼 값 모두가 null
이다.Address address = Address.createAddress("지번주소", "상세주소");
Hospital hospital = Hospital.createHospital(hospitalSaveForm,address);
em.persist(hodpital);
public static Hospital createHospital(HospitalSaveForm form, Address hosAddress) {
return Hospital.builder()
// ...
.hosAddress(hosAddress)
// ...
.build();
}
임베디드 타입은
절대
공유하면 안된다.
복제
해서 사용해야한다.불변 객체
로 만들어야한다.Hospital hospital = em.find(Hospital.class, 1L);
Address address = Address.createAddress("변경된 지번", "변경된 상세");
hostpital.setAddress(address); // 실제로는 세터가 아닌 update하는 메소드를 사용
@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Hospital extends TimeStamped {
//1. PK / 2. 자동으로 값 생성(아이덴티티 전략 -> 디비가 생성)
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long hosId;
private String hosName;
private String hosPhone;
@Enumerated(EnumType.STRING)
private HosStatus hosStatus;
@Enumerated(EnumType.STRING)
private HosBooking hosBooking; // 예약 가능 상태를 나타내는 값
@Embedded
private Address hosAddress;
private String hosOpenhour;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "hos_sigudong")
private Sigudong hosSigudong;
@OneToMany(mappedBy = "hospital",orphanRemoval = true)
private List<HosImg> hosImgs = new ArrayList<>();
/*== 빌더패턴을 통한 생성 메소드 ==*/
public static Hospital createHospital(HospitalSaveForm form, Address hosAddress, Sigudong dong) {
return Hospital.builder()
.hosName(form.getHosName())
.hosPhone(form.getHosPhone())
.hosStatus(HosStatus.OPEN)
.hosBooking(HosBooking.POSSIBLE)
.hosAddress(hosAddress)
.hosSigudong(dong)
.hosOpenhour(form.getHosOpenHour())
.build();
}
/*상태 유지를 이용한 업데이트*/
public void update(HospitalUpdateForm hospitalUpdateForm, Address address, Sigudong sigudong) {
this.hosName = hospitalUpdateForm.getHosName();
this.hosPhone = hospitalUpdateForm.getHosPhone();
this.hosOpenhour = hospitalUpdateForm.getHosOpenHour();
this.hosAddress = address;
this.hosSigudong = sigudong;
}
}
@Embeddable
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Address {
private String sido; //서울
private String siqungu; //서대문구
private String bname; //북가좌동
private String jibunAddress; //서울 서대문구 북가좌동 328-51
private String roadAddress; //서울 서대문구 증가로29길 20-14
private String sangse;
private double x;
private double y;
private Long bCode;
public static Address createAddress (String jibunAddress, String sangse) {
AddressToCoordinate addressToCoordinate = new AddressToCoordinate();
JSONObject jsonObject = addressToCoordinate.coordinate(jibunAddress);
JSONObject roadJoso = addressToCoordinate.newAddressJson(jsonObject);
Long bCode = addressToCoordinate.bCode(jsonObject);
return Address.builder()
.sido((String) roadJoso.get("region_1depth_name"))
.siqungu((String) roadJoso.get("region_2depth_name"))
.bname((String) roadJoso.get("region_3depth_name"))
.jibunAddress(jibunAddress)
.roadAddress((String) roadJoso.get("address_name"))
.sangse(sangse)
.x(Double.parseDouble((String) roadJoso.get("x")))
.y(Double.parseDouble((String) roadJoso.get("y")))
.bCode(bCode)
.build();
}
}