티스토리 뷰
임베디드 타입이란?
임베디드 타입은 기본 값 타입을 모아서 만들어진 복합 값 타입이라 한다. 아래 예제를 통해 알아보았다.
임베디드 타입 예제
아래 예제의 회원 엔티티는 간단하게 이름, 주소, 주소 상세, 우편 번호를 가진다. 그런데 주소, 주소 상세, 우편 번호는 하나의 객체로 표현이 가능한데 이를 임베디드 타입으로 정의하였다.
Member.java
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
private String userName;
@Embedded
private Address address;
// getter, setter 생략
}
Address.java(임베디드 타입)
@Embeddable
public class Address {
public Address() {}
public Address(String address, String daddress, String zcode) {
this.address = address;
this.daddress = daddress;
this.zcode = zcode;
}
private String address;
private String daddress;
private String zcode;
//getter,setter 생략
}
Main.java
// 엔티티 매니저 생략
Address memberAddress = new Address("address", "daddress", "123123");
Member member = new Member();
member.setUserName("member");
member.setAddress(memberAddress);
em.persist(member);
실행결과
Hibernate:
create table Member (
id bigint not null,
address varchar(255),
daddress varchar(255),
userName varchar(255),
zcode varchar(255),
primary key (id)
)
Hibernate:
/* insert for
jpabook.jpashop.domain.Member */insert
into
Member (address, daddress, zcode, userName, id)
values
(?, ?, ?, ?, ?)
위의 실행 결과를 보면 Member 테이블에 임베디드 타입으로 선언한 Address 객체 내의 address, daddress, zcode 속성이 생성된 것을 볼 수 있다. 여기서 어노테이션 @Embeddable, @Embedded 타입이 있는데 @Embeddable은 임베디드 타입을 정의할 때 사용하고, @Embedded은 임베디드를 사용하는 엔티티 객체에 사용한다. 이 어노테이션을 사용할 때 둘 중 하나만 적용하면 된다.
임베디드 타입 장점
- 재사용
- 높은 응집도
- 값 타입만 사용하는 메서드를 만들 수 있음.
- 임베디드 타입은 소유한 엔티티 객체에 의해 의존한다.
중복 사용할 경우
임베디드 타입을 중복 사용할 수 있다. 임베디드 타입에 @AttributeOverrides, @AttributeOverride 어노테이션을 사용해서 재정의 후 사용할 수 있다.
Member.java
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
private String userName;
@Embedded
private Address address;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "address",
column = @Column(name = "work_address")),
@AttributeOverride(name = "daddress",
column = @Column(name = "work_daddress")),
@AttributeOverride(name = "zcode",
column = @Column(name = "work_zcode"))
})
private Address workAddress;
// getter,setter 생략
}
실행 결과
Hibernate:
create table Member (
id bigint not null,
address varchar(255),
daddress varchar(255),
userName varchar(255),
work_address varchar(255),
work_daddress varchar(255),
work_zcode varchar(255),
zcode varchar(255),
primary key (id)
)
위의 실행 결과를 보면 재정의 한 속성이 추가된 것 을 볼 수 있다.
임베디드 타입을 수정시 문제점
임베디드 타입을 수정시 아래와 같은 문제점이 있다. 만약 member 2개가 같은 Address 임베디드 타입을 저장 후 meber 하나만 주소를 수정하면 어떻게 될까? 아래 예제를 통해 알아보았다.
수정 시 문제점 예제
Main.java
// 엔티티 매니저 생략
Address memberAddress = new Address("address", "daddress", "123123");
Member member = new Member();
member.setUserName("member");
member.setAddress(memberAddress);
em.persist(member);
Member member2 = new Member();
member2.setUserName("member2");
member2.setAddress(memberAddress);
em.persist(member2);
member.getAddress().setAddress("update");
실행 결과
Hibernate:
/* update
for jpabook.jpashop.domain.Member */update Member
set
address=?,
daddress=?,
zcode=?,
userName=?
where
id=?
Hibernate:
/* update
for jpabook.jpashop.domain.Member */update Member
set
address=?,
daddress=?,
zcode=?,
userName=?
where
id=?
위의 실행 결과를 보니 update문이 두 번 발생하였다. 이는 member 2개가 같은 Address 인스턴스를 공유했기 때문이다. 위와 같은 문제를 해결하기 위해서는 새로운 인스턴스를 생성 후 처리해야 한다. 아래 예제를 통해 알아보았다.
수정 시 문제점 해결 예제
Main.java
//엔티티 매니저 생략
Address memberAddress = new Address("address", "daddress", "123123");
Member member = new Member();
member.setUserName("member");
member.setAddress(memberAddress);
em.persist(member);
Address member2Address = new Address(memberAddress.getAddress(), memberAddress.getDaddress(), memberAddress.getZcode());
Member member2 = new Member();
member2.setUserName("member2");
member2.setAddress(member2Address);
em.persist(member2);
member.getAddress().setAddress("update");
실행 결과
Hibernate:
/* update
for jpabook.jpashop.domain.Member */update Member
set
address=?,
daddress=?,
zcode=?,
userName=?
where
id=?
위의 실행 결과를 보면 update문이 한번만 실행된 것을 볼 수 있다.
정리
임베디드 타입은 재사용이 높은 엔티티들의 값 타입에 적용하면 되고 중복 사용 시 @AttributeOverrides, @AttributeOverride 어노테이션을 사용하면 된다. 다만 임베디드 타입을 사용시 수정할 때 중복 update가 발생할 수 있으니 주의해야 한다.
본 포스팅은 “자바 ORM 표준 JPA 프로그래밍 - 기본 편/인프런”를 학습한 내용을 정리한 것
'Java > JPA' 카테고리의 다른 글
| <JPA> @Enumerated 사용 시 주의할 점 (0) | 2024.10.31 |
|---|---|
| <JPA> 벌크 연산시 주의할 점 (2) | 2024.10.03 |
| <JPA> 준영속 엔티티를 수정하는 2가지 방법 (0) | 2024.09.30 |
| <JPA> 즉시 로딩과 지연 로딩이란? (0) | 2024.09.23 |
| <JPA> @MappedSuperclass 이란? (0) | 2024.09.05 |
