본문 바로가기
  • 실행력이 모든걸 결정한다
Spring 사전 준비/JPA Hibernate

[JPA] 복합 값 타입과 불변 객체

by 김코더 김주역 2022. 8. 3.
반응형

1. 복합 값(임베디드) 타입

아래 포스팅의 [3-3)@EmbeddedId 방식]과 사용 방법이 비슷하다. 아래 포스팅에서는 복합 키(@EmbeddedId)를 다룬 것이고, 이번 포스팅에서는 키가 아닌 복합 값(@Embedded)을 다룰 것이다.

https://kimcoder.tistory.com/486

 

[JPA] 고급 매핑 기술

1. 객체의 상속 관계 매핑 - 객체의 상속 구조와 DB의 슈퍼타입-서브타입 관계를 매핑하는 것이다. 1) 조인 전략 (1) 특징 - 엔티티들을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키

kimcoder.tistory.com

임베디드 타입은 엔티티와 달리 식별자라는 개념이 없다.★

 

예를 들어, Member 엔티티에 다음과 같은 정보들이 들어있다고 하자.

Member
id
name
city
street
zipcode

여기에서 {city, street, zipcode}는 큰 의미로 주소를 나타낸다. 그래서 {city, street, zipcode}를 하나로 묶어서 임베디드(복합 값) 타입으로 정의하면 Member 엔티티를 더욱 응집력 있게 만들 수 있게 된다.

임베디드 타입도 엔티티의 값이기 때문에 엔티티는 결국 하나의 테이블에 매핑된다는 사실도 알아두자. 즉, MEMBER 테이블에 저 5개의 정보가 모두 매핑된다.

 

<Member.class>

@Entity
public class Member {

    @Id
    @GeneratedValue
    private Long id;
    private String name;
    
    @Embedded Address homeAddress;
    
    // ...
}

 

<Address.class>

@Embeddable
@EqualsAndHashCode
public class Address {
    
    @Column(name="CITY")
    private String city
    private String street;
    private String zipcode;
    
    // ...
}

 

- 참고로, 임베디드 타입에도 연관관계를 설정할 수 있다. 임베디드 타입에 있는 값을 다시 세밀하게 분리했다면 @Embeddable 클래스의 필드에 다시 @Embedded를 설정하면 된다.

@Embeddable
public class Address {
    String street;
    String city;
    @Embedded Zipcode zipcode; // Zipcode 임베디드 타입을 따로 정의해서 사용할 것
    
    // ...
}

 

- 드문 경우지만, 한 엔티티에 같은 임베디드 타입을 중복해서 사용하게 되면 컬럼명이 중복된다. 이 때는 @AttributeOverrides 어노테이션을 사용해서 속성을 재정의해서 컬럼명의 중복을 피할 수 있다.

@Embedded Address homeAddress; // 1번째 Address 임베디드 타입
@Embedded
@AttributeOverrides({
    @AttributeOverride(name="city", column=@Column(name="COMPANY_CITY")),
    @AttributeOverride(name="street", column=@Column(name="COMPANY_STREET")),
    @AttributeOverride(name="zipcode", column=@Column(name="COMPANY_ZIPCODE"))
})
Address companyAddress; // 2번째 Address 임베디드 타입

 

- 임베디드 타입이 null값이면 그 안에 있는 모든 컬럼 값들도 null이 된다.

- 임베디드 타입은 기본적으로 엔티티와 같이 즉시 로딩으로 조회된다.

 

 

 

2. 불변 객체

- 임베디드 타입도 자바에서는 객체 타입이기 때문에, 임베디드 타입을 여러 엔티티에서 공유해서 사용하는 경우에는 속성값을 수정했을 때 공유 참조로 인해 의도하지 않게 다른 엔티티의 속성값까지 바뀌어버린다. 이를 부작용이라고 하며, 이러한 부작용을 막기 위해 객체를 불변하게 만들어서 값을 수정할 수 없게 하면 된다.

- 불변 객체를 구현하는 방법은 여러 가지가 있지만 가장 간단한 방법은 생성자로만 임베디드 타입 객체를 생성하고 수정자를 제거하는 것이다. 만약 값을 수정해야 한다면 다음과 같이 새로운 객체를 생성해서 사용해야 한다.

Address address = member1.getCompanyAddress(); // member1의 주소 정보를 가져온다.
Address newAddress = new Address(address.getCity()); // member1의 주소 정보를 활용하여 새로운 객체를 생성한다.
member2.setCompanyAddress(newAddress); // 새로 생성한 객체를 member2의 주소로 설정한다.

 

 

 

● 참고자료 : 자바 ORM 표준 JPA 프로그래밍

반응형

'Spring 사전 준비 > JPA Hibernate' 카테고리의 다른 글

[JPA] JPQL의 작성  (0) 2022.08.04
[JPA] 값 타입 컬렉션  (0) 2022.08.03
[JPA] CASCADE 기능  (0) 2022.08.03
[JPA] 즉시 로딩과 지연 로딩  (0) 2022.08.01
[JPA] 프록시 객체  (0) 2022.08.01

댓글