일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- exclusive lock
- 힙
- 비관적락
- BOJ
- fetch
- 유니크제약조건
- 데코레이터
- execute
- querydsl
- 연관관계
- 연결리스트
- JPQL
- CHECK OPTION
- dfs
- 스토어드 프로시저
- 다대일
- 다대다
- 이진탐색
- eager
- SQL프로그래밍
- FetchType
- 즉시로딩
- PS
- 백트래킹
- 동적sql
- 일대다
- 스프링 폼
- shared lock
- 지연로딩
- 낙관적락
- Today
- Total
흰 스타렉스에서 내가 내리지
[JPA] 값 타입1 - 복합, 연관관계, 재정의, 복사, 비교 본문
임베디드 타입 (복합 값 타입)
public class Member{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Embedded Period workPeriod;
@Embedded Address homeAddress;
@Embeddable
public class Period {
@Temporal(TemporalType.DATE)
Date startDate;
@Temporal(TemporalType.DATE)
Date endDate;
}
@Embeddable
public class Address {
@Column(name = "city")
private String city;
private String street;
private String zipcode;
}
- startDate, endDate를 합해서 Period 클래스를 만들었다.
- city, street, zipcode 를 합해서 Address 클래스를 만들었다.
임베디드 타입을 사용하려면 다음 2가지 어노테이션이 필요하다. 둘 중 하나는 생략해도 된다.
- @Embeddable : 값 타입을 정의하는 곳에 표시
- @Embedded : 값 타입을 사용하는 곳에 표시
임베디드 타입과 연관관계
@Entity
@Getter @Setter
public class Member{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Embedded Address address;
@Embedded PhoneNumber phoneNumber;
}
@Embeddable
public class Address {
@Column(name = "city")
private String city;
private String street;
private String state;
@Embedded Zipcode zipcode; // 임베디드 타입 포함
}
@Embeddable
public class Zipcode {
String zip;
String plusFour;
}
@Embeddable
public class PhoneNumber {
String areaCode;
String localNumber;
@ManyToOne PhoneServiceProvider provider;
}
@Entity
public class PhoneServiceProvider {
@Id String name;
}
@AttributeOverride : 속성 재정의
@Entity
@Getter @Setter
public class Member{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Embedded Address homeAddress;
@Embedded Address companyAddress;
집 주소에 회사 주소를 하나 더 추가했다.
문제는 테이블에 매핑하는 컬럼명이 중복되는 것이다.
이때는 @AttributeOverrides 를 사용해서 매핑정보를 재정의해야 한다.
@Embedded private 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"))
})
private Address companyAddress;
임베디드 타입이 null 이면 매핑한 컬럼 값은 모두 null이 된다.
값 타입 복사
값 타입의 실제 인스턴스인 값을 공유하는 것은 위험하다.
대신에 값(인스턴스)을 복사해서 사용해야 한다.
Address a = new Address("Old");
Address b = a.clone(); // 항상 복사해서 넘겨야 한다.
// Address b = a; // 이렇게 참조만 넘기면 부작용이 발생할 수 있다.
b.setCity("New");
복사를 하지 않고 넘기면, a와 b가 참조하는 인스턴스가 같기 때문에 마지막 줄 코드를 실행하면 a의 City 값도 바뀐다.
객체의 공유 참조는 피할 수 없다.
근본적인 해결책은 해당 필드의 Setter를 만들지 않는 것이다.
이렇게 하면 공유 참조를 해도 값을 변경하지 못하므로 부작용의 발생을 막을 수 있다.
값 타입은 될 수 있으면 불변 객체(immutable Obejct)로 설계해야 한다.
참고로 Integer, String은 자바가 제공하는 대표적인 불변 객체다.
값 타입의 비교
자바가 제공하는 객체 비교는 2가지다.
- 동일성 (Identity) 비교 : 인스턴스의 참조 값을 비교, == 사용
- 동등성 (Equivalence) 비교 : 인스턴스의 값을 비교, equals() 사용
값 타입은 비록 인스턴스가 달라도 그 안에 값이 같으면 같은 것으로 봐야 한다.
따라서 값 타입을 비교할 때는 a.equals(b)를 사용해서 동등성 비교를 해야 한다.
물론 Address의 equals() 메소드를 재정의해야 한다.
'Spring' 카테고리의 다른 글
[JPA] JPQL, Criteria, QueryDSL 소개 (0) | 2023.02.25 |
---|---|
[JPA] 값 타입2 - 값 타입 컬렉션 (0) | 2023.02.19 |
[JPA] 영속성 전이 : CASCADE, 고아 객체 (0) | 2023.02.19 |
[JPA] 프록시, 즉시로딩, 지연로딩 (0) | 2023.02.19 |
[JPA] 조인 테이블(연결 테이블) (0) | 2023.02.16 |