일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- 도메인 주도 개발 시작하기
- scheduling messages with rabbitmq
- 밋업프로젝트
- java
- 객체지향 쿼리 언어
- delayed message plugin
- kusitms
- 30기
- Spring
- 최범균
- RESTClient
- JPA
- 교육기획팀원
- reactive operaton
- 영속성
- JPQL
- 교육기획팀
- Spring Batch
- 자바 ORM 표준 JPA 프로그래밍
- rabbitmq-delayed-message-exchange
- Domain Driven Design
- 자동처리
- jdbc
- 큐시즘
- 이펙티브자바
- cicd
- ddd
- GitHub Actions
- 한국대학생it경영학회
- springboot
Archives
- Today
- Total
코딩은 마라톤
[자바 ORM 표준 JPA 프로그래밍] 9장. 값 타입 본문
임베디드 타입(복합 값 타입)
- 새로운 값 타입을 직접 정의해서 사용할 수 있다. 이를 임베디드 타입이라 한다.
@Entity
public class Member {
...
// 집 주소 표현
private String city;
private String street;
private String zipcode;
...
}
- 위 코드에서 회원 엔티티의 집 주소를 나타낼 때, 모든 정보를 풀어서 저장한다.
- 이는 객체지향적이지 않으며 응집력만 떨어뜨린다.
- 따라서 풀어쓰지 않고 [집주소]를 가지도록 임베디드 타입을 사용한다.
@Entity
public class Member {
@Embedded Address homeAddress; // 집 주소
...
}
@Embeddable
public class Address {
@Column(name = "city")
private String city;
private String street;
private String zipcode;
}
- city, street, zipcode를 합해서 Address(주소) 클래스를 만들었다.
- 새로 정의한 값 타입들은 재사용할 수 있고 응집도 또한 아주 높다.
임베디드 타입 - 2가지 어노테이션
- @Embeddable: 값 타입을 정의하는 곳에 표시
- @Embedded: 값 타입을 사용하는 곳에 표시
또한 임베디드 타입은 기본 생성자가 필수다.
@AttributeOverride : 속성 재정의
@Entity
public class Member {
@Embedded Address homeAddress;
@Embedded Address companyAddress;
}
- 회원 엔티티에 회사 주소를 하나 더 추가했다.
이때 테이블에 매핑하는 컬럼명이 중복되는 문제점이 발생한다. (homeAddress와 companyAddress의 @Embeddable 클래스인 Address 클래스의 컬럼명이 동일하다.) - 따라서 @AttributeOverrides를 사용해서 매핑정보를 재정의한다.
@Entity
public class Member {
@Embedded Address homeAddress;
@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;
}
값 타입과 불변 객체
int a = 10;
int b = a;
b = 4;
- 위 코드는 자바의 기본 타입이다.
- 기본 타입은 값을 대입하면 값을 복사해서 전달한다.
- 따라서 b=4일 경우 a값은 변경되지 않는, 즉 a, b는 완전히 독립된 값을 가지고 있어 값 타입 복사의 부작용이 없다.
Address a = new Address("Old");
Address b = a;
b.setCity("New");
- 문제는 위와 같은 객체 타입이다.
- 객체에 값을 대입하면 항상 참조 값을 전달한다.
- 따라서 위에서 b.setCity("New") 에서는 a.city의 값 또한 New로 변경된다.
위와 같은 문제를 해결하기 위해 "불변 객체"를 사용한다.
불변 객체
- 구현 방법
- 생성자로만 값을 설정하고 수정자(Setter)를 만들지 않는다.
@Embeddable
public class Address {
private String city;
protected Address() {} // JPA는 기본 생성자는 필수다.
// 생성자로 초기 값을 설정한다.
public Address(String city) { this.city = city; }
// 접근자(Getter)는 노출한다.
public String getCity() {
return city;
}
// 수정자(Setter)는 만들지 않는다.
}
값 타입 컬렉션
값 타입을 하나 이상 저장하려면 컬렉션에 보관하고 @ElementCollection, @CollectionTable 어노테이션을 사용한다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@Embedded
private Address address;
@ElementCollection
@CollectionTable(name = "FAVORITE_FOODS",
joinColumns = @JoinColumn(name = "MEMBER_ID"))
@Column(name = "FOOD_NAME")
private Set<String> favoriteFoods = new HashSet<>();
@ElementCollection
@CollectionTable(name = "ADDRESS",
joinColumns = @JoinColumn(name = "MEMBER_ID"))
private List<Address> addressHistory = new ArrayList<>();
}
@Embeddable
public class Address {
@Column
private String city;
private String street;
private String zipcode;
}
- 값 타입 컬렉션은 영속성 전이(cascade) + 고아 객체 제거(orphan remove) 기능을 필수로 가진다.
- 값 타입 컬렉션은 조회할 때 페치 전략을 선택할 수 있는데 FetchType.LAZY가 기본이다.
'Backend > JPA' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍] 10장. Criteria 쿼리 (0) | 2024.06.21 |
---|---|
[자바 ORM 표준 JPA 프로그래밍] 10장. JPQL (1) (1) | 2024.06.16 |
[자바 ORM 표준 JPA 프로그래밍] 8장. 프록시와 연관관계 관리 (0) | 2024.02.25 |
[자바 ORM 표준 JPA 프로그래밍] 7장. 고급 매핑 (0) | 2024.02.22 |
[자바 ORM 표준 JPA 프로그래밍] 6장. 다양한 연관관계 매핑 (1) | 2024.02.12 |