Reference. 한 번에 끝내는 Java/Spring 웹 개발 마스터 초격차 패키지 Online
이전 글
더보기
9. 임베디드 타입 활용
- 현업에서 많이 사용하는 임베디드 타입
- 주문시의 가격 필드
- 주소 정보 (도, 시 군, 구, 상세주소)
@Embeddable
,@Embedded
어노테이션을 이용해 임베디드할 객체와 Entity 속성을 설정
@Embeddable
, @Embedded
사용 예시
User.java
public class User extends BaseEntity{
...
@Embedded
private Address address;
}
Address.java 생성
@Embeddable
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
private String city; //시
private String district; //구
@Column(name = "address_detail")
private String detail; //상세주소
private String zipCode; //우편번호
}
UserEntityListener.java 수정(User컬럼이 수정되면 수정 필요)
public class UserEntityListener {
@PostPersist
@PostUpdate
public void postPersistAndPostUpdate(Object o){
UserHistoryRepository userHistoryRepository = BeanUtils.getBean(UserHistoryRepository.class);
User user = (User) o;
UserHistory userHistory = new UserHistory();
userHistory.setName(user.getName());
userHistory.setEmail(user.getEmail());
userHistory.setUser(user);
userHistory.setAddress(user.getAddress());
userHistoryRepository.save(userHistory);
}
}
테스트 코드 및 결과
//UserRepositoryTest.java
@Test
void embedTest(){
User user = new User();
user.setName("steve");
user.setAddress(new Address("서울시", "강남구", "강남대로 364 미왕빌딩", "06242"));
userRepository.save(user);
userRepository.findAll().forEach(System.out::println);
}
//결과
Hibernate:
create table user (
id bigint not null auto_increment,
created_at datetime(6) default now(6) comment '생성시간' not null,
updated_at datetime(6) default now(6) comment '수정시간' not null,
city varchar(255),
address_detail varchar(255),
district varchar(255),
zip_code varchar(255),
email varchar(255),
gender integer,
name varchar(255),
primary key (id)
) engine=InnoDB
Hibernate:
insert
into
user
(created_at, updated_at, city, address_detail, district, zip_code, email, gender, name)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?)
User(super=BaseEntity(createdAt=2021-08-14T23:08:27, updatedAt=2021-08-14T23:08:27), id=1, name=martin, email=martin@fastcampus.com, gender=null, address=null)
User(super=BaseEntity(createdAt=2021-08-14T23:08:27, updatedAt=2021-08-14T23:08:27), id=2, name=dennis, email=dennis@fastcampus.com, gender=null, address=null)
User(super=BaseEntity(createdAt=2021-08-14T23:08:27, updatedAt=2021-08-14T23:08:27), id=3, name=sophia, email=sophia@slowcampus.com, gender=null, address=null)
User(super=BaseEntity(createdAt=2021-08-14T23:08:27, updatedAt=2021-08-14T23:08:27), id=4, name=james, email=james@slowcampus.com, gender=null, address=null)
User(super=BaseEntity(createdAt=2021-08-14T23:08:27, updatedAt=2021-08-14T23:08:27), id=5, name=martin, email=martin@another.com, gender=null, address=null)
User(super=BaseEntity(createdAt=2021-08-14T23:08:28.430528300, updatedAt=2021-08-14T23:08:28.430528300), id=6, name=steve, email=null, gender=null, address=Address(city=서울시, district=강남구, detail=강남대로 364 미왕빌딩, zipCode=06242))
임베디드 타입의 다른 예시 (재활용)
User.java
@AttributeOverrides
,@AttributeOverride
를 통해Address.java
객체의 컬럼 재정의- 재정의 하지 않으면 User테이블에 같은 컬럼이 중복되어 오류 발생
@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_detail")),
@AttributeOverride(name = "zipCode", column = @Column(name = "home_zipCode"))
})
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_detail")),
@AttributeOverride(name = "zipCode", column = @Column(name = "company_zipCode"))
})
private Address companyAddress;
UserEntityListener.java
public class UserEntityListener {
...
public void postPersistAndPostUpdate(Object o){
...
userHistory.setUser(user);
userHistory.setHomeAddress(user.getHomeAddress());
userHistory.setCompanyAddress(user.getCompanyAddress());
userHistoryRepository.save(userHistory);
}
}
테스트 코드 및 결과
//UserRepositoryTest.java
@Test
void embedTest(){
User user = new User();
user.setName("steve");
user.setHomeAddress(new Address("서울시", "강남구", "강남대로 364 미왕빌딩", "06242"));
user.setCompanyAddress(new Address("서울시", "성동구", "성수이로 113 제강빌딩", "04794"));
userRepository.save(user);
userRepository.findAll().forEach(System.out::println);
}
//실행결과
Hibernate:
create table user (
id bigint not null auto_increment,
created_at datetime(6) default now(6) comment '생성시간' not null,
updated_at datetime(6) default now(6) comment '수정시간' not null,
company_city varchar(255),
company_detail varchar(255),
company_district varchar(255),
company_zip_code varchar(255),
email varchar(255),
gender integer,
home_city varchar(255),
home_detail varchar(255),
home_district varchar(255),
home_zip_code varchar(255),
name varchar(255),
primary key (id)
) engine=InnoDB
Hibernate:
insert
into
user
(created_at, updated_at, company_city, company_detail, company_district, company_zip_code, email, gender, home_city, home_detail, home_district, home_zip_code, name)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert
into
user_history
(created_at, updated_at, company_city, company_detail, company_district, company_zip_code, email, gender, home_city, home_detail, home_district, home_zip_code, name, user_id)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
User(super=BaseEntity(createdAt=2021-08-14T23:34:19, updatedAt=2021-08-14T23:34:19), id=1, name=martin, email=martin@fastcampus.com, gender=null, homeAddress=null, companyAddress=null)
User(super=BaseEntity(createdAt=2021-08-14T23:34:19, updatedAt=2021-08-14T23:34:19), id=2, name=dennis, email=dennis@fastcampus.com, gender=null, homeAddress=null, companyAddress=null)
User(super=BaseEntity(createdAt=2021-08-14T23:34:19, updatedAt=2021-08-14T23:34:19), id=3, name=sophia, email=sophia@slowcampus.com, gender=null, homeAddress=null, companyAddress=null)
User(super=BaseEntity(createdAt=2021-08-14T23:34:19, updatedAt=2021-08-14T23:34:19), id=4, name=james, email=james@slowcampus.com, gender=null, homeAddress=null, companyAddress=null)
User(super=BaseEntity(createdAt=2021-08-14T23:34:19, updatedAt=2021-08-14T23:34:19), id=5, name=martin, email=martin@another.com, gender=null, homeAddress=null, companyAddress=null)
User(super=BaseEntity(createdAt=2021-08-14T23:34:20.112342100, updatedAt=2021-08-14T23:34:20.112342100), id=6, name=steve, email=null, gender=null, homeAddress=Address(city=서울시, district=강남구, detail=강남대로 364 미왕빌딩, zipCode=06242), companyAddress=Address(city=서울시, district=성동구, detail=성수이로 113 제강빌딩, zipCode=04794))
임베디드 타입의 null을 넣을 경우
null
,빈객체
로 넣는 경우 임베디드 된 모든 컬럼의 값은null
로 저장
UserRepository.java
- 실제 데이터베이스의 결과 확인을 위해
findAllRowRecords
생성
@Query(value = "select * from user", nativeQuery = true)
List<Map<String, Object>> findAllRowRecords();
UserRepositoryTest.java
@Test
void embedTest(){
User user = new User();
user.setName("steve");
user.setHomeAddress(new Address("서울시", "강남구", "강남대로 364 미왕빌딩", "06242"));
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);
userRepository.findAllRowRecords().forEach(a -> System.out.println(a.values()));
}
실행결과
- JPA에서
객체
와null
로 넣을때 결과 차이가 발생하는 이유는 영속성 컨텍스트 캐쉬 때문EntityManager
clear()
를 실행하면 DB에서 조회하기 때문에 둘 다 null로 표시
//JPA를 이용한 조회 (userRepository.findAll()
User(super=BaseEntity(createdAt=2021-08-14T23:40:54.880805400, updatedAt=2021-08-14T23:40:54.880805400), id=6, name=steve, email=null, gender=null, homeAddress=Address(city=서울시, district=강남구, detail=강남대로 364 미왕빌딩, zipCode=06242), companyAddress=Address(city=서울시, district=성동구, detail=성수이로 113 제강빌딩, zipCode=04794))
User(super=BaseEntity(createdAt=2021-08-14T23:40:55.034806400, updatedAt=2021-08-14T23:40:55.034806400), id=7, name=joshua, email=null, gender=null, homeAddress=null, companyAddress=null)
User(super=BaseEntity(createdAt=2021-08-14T23:40:55.041805400, updatedAt=2021-08-14T23:40:55.041805400), 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))
//데이터베이스 조회 (userRepository.findAllRowRecords())
[6, 2021-08-14 23:37:26.221536, 2021-08-14 23:37:26.221536, 서울시, 성수이로 113 제강빌딩, 성동구, 04794, null, null, 서울시, 강남대로 364 미왕빌딩, 강남구, 06242, steve]
[7, 2021-08-14 23:37:26.406535, 2021-08-14 23:37:26.406535, null, null, null, null, null, null, null, null, null, null, joshua]
[8, 2021-08-14 23:37:26.416538, 2021-08-14 23:37:26.416538, null, null, null, null, null, null, null, null, null, null, jordan]
'백엔드 > JPA' 카테고리의 다른 글
[ JPA ] 10. JPA 트러블슈팅 (0) | 2021.08.25 |
---|---|
[ JPA ] 8. 커스텀 쿼리 사용 (0) | 2021.08.18 |
[ JPA ] 7. 영속성 전이 (Cascade) (0) | 2021.08.12 |
[ JPA ] 6-4. 트랜잭션 매니저 (TransactionManager) (0) | 2021.08.08 |
[ JPA ] 6-3. Entity 생명주기 (1) | 2021.08.08 |