이번에 학습한 내용은 @Embeddable / @Embedded 필드입니다.
아, 오늘도 환경 설정 문제로 IDE에서 코드를 검증해보지는 않았습니다. 원격으로 작업하기 너무 번거로워서; 손코드인 점 양해 바랍니다. 내일은 원격이 아니라 코드를 복붙해서 진행해봐야겠네요. macOS에서 DB 쓰기 번거로운데... docker도 그렇고...
@Embeddable / @Embedded
개념은 이렇습니다. 엔티티의 여러 필드를 묶어서 하나의 클래스로 다루겠다는 거구요. 거꾸로 생각해보자면 Embeddable 인 객체의 모든 필드들을 특정 @Entity 의 필드에 포함시키는 거라고 볼 수 있습니다. 그래서 어노테이션 이름이 @Embeddable / @Embedded 인 거겠죠.
문서와 함께 각 어노테이션의 의미를 살펴봅시다.
- @Embeddable: 특정 객체가, 다른 @Entity 의 내용으로서 결합될 수 있다고 표시합니다. 클래스에 표시합니다.
Specifies a class whose instances are stored as an intrinsic part of an owning entity and share the identity of the entity.- 다른 엔티티에 녹여낼 개별 필드에도 @Column() 등의 어노테이션으로 칼럼 이름을 변경하거나 하는 등의 작업을 @Entity와 똑같이 할 수 있습니다.
- 프리픽스 없을까...? 강의에서는 안 나왔는데... 확인을 못 해보니 좀 답답하네요.
칼럼 이름이 따로 바뀌지는 않습니다. - 문서에 어떤 상황에서 써야하는지에 대한 예시가 많습니다.
- @Embedded: 특정 엔티티의 필드가, 사실은 여러개의 칼럼을 나타내고, 그 칼럼들의 정보는 필드의 필드들로부터 이 엔티티에 녹여낸다... 말로 표현하려니 어렵네요.
뭏든 @Entity의 필드 중 타입이 @Embeddable 인 필드에 달아줘야 합니다.
Specifies a persistent field or property of an entity whose value is an instance of an embeddable class.- 같은 클래스 두 개를 @Embedded 로 한 엔티티에 녹이려고 할 때, 칼럼 이름이 겹치는 문제가 발생합니다. @AttributeOverrides 와 @AttributeOverride 로 개별 필드의 칼럼 이름을 엔티티 쪽에서 바꿔줄 수 있습니다... 있는데요... 좀 깔끔하지가 않네요.
직접 해보기
코드를 테스트해볼수는 없는 관계로 결과 SQL을 확인해볼 수 없는 점이 아쉽네요. 아무튼 실제로 이걸 어떻게 쓰는지도 정리는 해놔야하니.
두 가지 정도의 사례를 들어주셨는데요, 하나는 여러 종류의 가격이 묶여있는 사례고 (적정가 / 표시가 / 최저가 ...) 나머지 하나는 외국 사이트에서 회원가입할 때 종종 주소를 시 동 면 상세주소 이렇게 세부적으로 나누는 사례인데, 이번에는 뒷내용에 해당하는 "주소"를 기준으로 잡고 진행했습니다.
@Embeddable
public class Address {
public String city;
public String district;
@Column(name="address_detail")
public String detail;
public String zipCode
}
그리고 User 클래스에 필드로 넣을거구요. 사용자의 주소는 집주소와 회사주소로 나눌수도 있으니, 같은 엔티티에 임베딩된 객체가 둘 이상인 경우도 한 번에 확인해볼 수 있을겁니다.
생략
@Entity
public class User {
생략
@Embedded
public Address homeAddress;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "city", column = @Column(name="company_city"),
같은 방식으로 나머지 필드도 이름을 바꿔줌
})
public Address companyAddress;
}
SQL 의 DDL은 다음과 같이 나옵니다. 실제 SQL을 확인할 수는 없으니 필드 목록만 나열해보겠습니다.
- 엔티티 User의 테이블상의 칼럼들
- ID (생략했었음)
- 그 외 필드
- city
- district
- address_detail
- zip_code
- company_city
- company_district
- company_address_detail
- company_zip_code
Address 클래스의 필드들이 User 엔티티에 납작하게 눌려서 들어갔습니다.
Address가 null이던, Address의 필드가 모두 null이던 같은 의미
그런데 한 가지 궁금할만한 점은 다음 두 가지의 차이점입니다.
- User.homeAddress = new Address(null, null, 전부 null)
이 후 저장 - User.homeAddress = null
그냥 Address인 필드를 아예 null로 지정
이 후 저장
위의 예상되는 필드 목록에서 보셨다시피, 이 두개는 사실 차이가 없습니다. 그럼에도 불구하고 강의에서 이걸 확인하기 위해 코드를 짜봤을 때에는 new Address()를 만들어서 save 한 뒤 findAll() 로 다시 찾아왔을 때에도 여전히 이 객체만 Address가 있었습니다.
@Test
void testEmbeddedToNull() {
User user1 = new User();
user1.name = "user1";
user1.homeAddress = new Address(null, null, null, null);
User user2 = new User();
user2.name = "user2";
user2.homeAddress = null;
userRepo.save(user1);
userRepo.save(user2);
userRepo.flush();
// entityManager.clear();
List<User> users = userRepo.findAll();
users.forEach(System::out::println);
}
이는 엔티티 매니저에 1차 캐시로 객체가 저장되어 있기 때문으로, 위 샘플 코드에 주석을 쳐놓은 부분처럼 em.clear() 를 호출해주면 user1 과 user2 가 동등하게 homeAddress 가 null 로 나오는 점을 확인하실 수 있습니다.
본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.
패스트캠퍼스: https://bit.ly/37BpXiC
#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #한번에끝내는JavaSpring웹개발마스터초격차패키지Online
담백...
다음 강의가 트러블슈팅이라고 하시던데 실습 환경이 필요하다는 생각이 들면 잠깐 미루고 스프링 시큐리티 강의를 먼저 봐야할지도 모르겠습니다.
'FastCampus - 한번에 끝내는 Java|Spring 웹 개발 > 04 JPA' 카테고리의 다른 글
JPA Ch 11 - 캐시와 DB의 불일치 - 패스트캠퍼스 챌린지 44일차 (0) | 2022.03.08 |
---|---|
JPA Ch 11 "N+1 문제" - 패스트캠퍼스 챌린지 43일차 (0) | 2022.03.07 |
JPA Ch 9 @Converter - 패스트캠퍼스 챌린지 40일차 (0) | 2022.03.04 |
JPA Ch 9 @Query (3), NativeQuery - 패스트캠퍼스 챌린지 39일차 (0) | 2022.03.03 |
JPA Ch 9 @Query (1, 2) - 패스트캠퍼스 챌린지 38일차 (0) | 2022.03.02 |