🤔🤔 컨버터를 통해 자바객체에 맵핑하는 법을 배웠다. String이나 Int 같은 Row한 값으로 받아서 서비스 로직에서 변환해도 문제가 없을탠데 왜 이렇게 까지 할까?
바로 코드의 가독성 때문이다.
오픈소스나 기업체 상용소스같은 최근코드는 이해하기쉽고 읽기쉽게 가독성이 좋게 작성하는것이 트랜드이다. 그렇기에 Entity에 Embed클래스를 한번 사용해보자.
현업에서 Enbedded타입을 가장 많이 쓰는 예로써, 주문시의 가격 필드가 있다. 가격은 공급가 부가세 토탈가격 같은 가격필드는 상품 도메인이나, 주문 도메인, 결제, 정산 등등 여러가지 필드에 쓰이기 때문에 적합하다.
또한 주소정보도 적합하다. 주소정보를 String address에 모두 저장할 수 있지만, 그렇게 되면 값 자체가 정규화 되지 않아 서울, 서울시, 서울특별시 이런식으로 Data가 정리안될수 있다. 정규화해서 Data를 선택할수있게 하면 비표준화된 정보를 정리하여 생성할수 있다. 주소 값은 도 시 군.구 우편번호 등등 으로 나눈다. 주소를 예로 만들어보자.
public class User extends BaseEntity {
private String city;
private String district;
private String detail;
private String zipCode;
...
...
...
{
@Embeddable
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
private String city; // 시
private String district; // 구
private String detail; // 상세주소
private String zipCode; // 우편번호
}
public class User extends BaseEntity {
...
...
...
@Embedded
private Address address;
...
...
{
public class UserEntityListener {
...
...
userHistory.setAddress(user.getAddress());
userHistoryRepository.save(userHistory);
}
}
@Test
void embedTest() {
userRepository.findAll().forEach(System.out::println);
User user = new User();
user.setName("steve");
user.setAddress(new Address("서울시", "강남구", "강남대로 364 미왕빌딩", "06241"));
userRepository.save(user);
userRepository.findAll().forEach(System.out::println);
userHistoryRepository.findAll().forEach(System.out::println);
}
public class User extends BaseEntity {
..
.
.
@Embedded
private Address homeAddress;
@Embedded
private Address companyAddress;
.
.
.
}
@Test
void embedTest() {
user.setHomeAddress(new Address("서울시", "강남구", "강남대로 364 미왕빌딩", "06241"));
user.setCompanyAddress(new Address("서울시", "성동구", "성수이로 113 제강빌딩", "04794"));
.
.
{
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "city", column = @Column(name = "home_city")),
@AttributeOverride(name = "district", column = @Column(name = "home_district")),
@AttributeOverride(name = "detail", column = @Column(name = "home_address_detail")),
@AttributeOverride(name = "zipCode", column = @Column(name = "home_zip_code"))
})
private Address homeAddress;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "city", column = @Column(name = "company_city")),
@AttributeOverride(name = "district", column = @Column(name = "company_district")),
@AttributeOverride(name = "detail", column = @Column(name = "company_address_detail")),
@AttributeOverride(name = "zipCode", column = @Column(name = "company_zip_code"))
})
private Address companyAddress;
@Query(value = "select * from user", nativeQuery = true)
List<Map<String, Object>> findAllRawRecord();
@Test
void embedTest() {
userRepository.findAll().forEach(System.out::println);
User user = new User();
user.setName("steve");
user.setHomeAddress(new Address("서울시", "강남구", "강남대로 364 미왕빌딩", "06241"));
user.setCompanyAddress(new Address("서울시", "성동구", "성수이로 113 제강빌딩", "04794"));
userRepository.save(user);
User user1 = new User();
user1.setName("joshua");
user1.setHomeAddress(null);
user1.setCompanyAddress(null);
userRepository.save(user1);
User user2 = new User();
user2.setName("jordan");
user2.setHomeAddress(new Address());
user2.setCompanyAddress(new Address());
userRepository.save(user2);
userRepository.findAll().forEach(System.out::println);
userHistoryRepository.findAll().forEach(System.out::println);
userRepository.findAllRawRecord().forEach(a -> System.out.println(a.values()));
}
UserHistory(super=BaseEntity(createdAt=2022-02-16T18:43:54.365, updatedAt=2022-02-16T18:43:54.380), id=2, name=joshua, email=null, gender=null, homeAddress=null, companyAddress=null, user=User(super=BaseEntity(createdAt=2022-02-16T18:43:54.365, updatedAt=2022-02-16T18:43:54.365), id=7, name=joshua, email=null, gender=null, homeAddress=null, companyAddress=null))
UserHistory(super=BaseEntity(createdAt=2022-02-16T18:43:54.365, updatedAt=2022-02-16T18:43:54.380), id=3, name=jordan, email=null, gender=null, homeAddress=Address(city=null, district=null, detail=null, zipCode=null), companyAddress=Address(city=null, district=null, detail=null, zipCode=null), user=User(super=BaseEntity(createdAt=2022-02-16T18:43:54.365, updatedAt=2022-02-16T18:43:54.365), id=8, name=jordan, email=null, gender=null, homeAddress=Address(city=null, district=null, detail=null, zipCode=null), companyAddress=Address(city=null, district=null, detail=null, zipCode=null)))
entityManager.clear(); // 영속성 컨텍스트의 cache값을 지워주고 보자.
위 코드를 추가해주면 homeAddress=null, companyAddress=null) 값으로 통일되서 나온다.
Embeddable 클래스를 보면 Embeddable에 사용하기 좋은 예시들이 나와있다. 참고해보자.