Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- 13460 구슬탈출 2
- 객체 지향 설계와 스프링
- 백준 13460 Python
- 7장 고급매핑
- 코틀린인액션
- Kotlin in action 6장
- Kotlin in action 5장
- 컨베이어 벨트 위의 로봇 Python
- 싱글톤 컨테이너
- kotlin in action 정리
- 스프링 핵심 원리 - 기본편
- Kotlin in action 3장
- 스프링 핵심 원리 이해
- 20055 컨베이어 벨트 위의 로봇
- 스프링 핵심 원리
- 자바 ORM 표준 JPA 프로그래밍 7장
- 스프링 컨테이너와 스프링 빈
- Kotlin in action 10장
- Kotlin
- 20055
- 코틸린인액션
- spring
- 기능개발 python
- Python
- Kotlin In Action
- 백준
- 백준 20055 컨베이어 벨트 위의 로봇
- KotlinInAction
- 고급매핑
- 코틀린
Archives
- Today
- Total
기록하는 습관
[JPA] 9장 값 타입 본문
JPA 의 데이터 타입을 가장 크게 분류하면 엔티티 타입과 값 타입으로 나눌 수 있다.
- 엔티티 타입 : @Entity로 정의하는 객체
- 식별자를 통해 지속적으로 추적할 수 있다.
- 엔티티의 속성 값을 변경하더라도 같은 엔티티이다.
- 값 타입 : int, Integer, String 처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체를 말한다.
- 식별자가 없고 숫자나 문자같은 속성만 있으므로 추적할 수 없다.
- 숫자 값을 100에서 200으로 변경하면 완전히 다른 값으로 대체된다.
값 타입은 다음의 3가지로 나눌 수 있다.
- 기본값 타입(Basic value type)
- 자바 기본 타입(예: int, double)
- 래퍼 클래스(예: Integer)
- String
- 임베디드 타입(복합 값 타입)
- JPA 에서 사용자가 직접 정의한 값 타입
- 컬렉션 값 타입
- 하나 이상의 값 타입을 저장할 때 사용한다.
1. 기본값 타입
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
private int age;
}
Member 엔티티의 값 타입인 name, age 속성은 식별자 값도 없고 생명 주기도 회원 엔티티에 의존한다.
따라서 회원 엔티티 인스턴스를 제거하면 name, age 값도 제거된다.
값 타입은 공유하면 안 된다.
2. 임베디드 타입(복합 값 타입)
-
@Embeddable : 값 타입을 정의하는 곳에 표시
-
@Embedded : 값 타입을 사용하는 곳에 표시
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@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;
}
- 임베디드 타입이 null이면 매핑한 컬럼 값은 모두 null이 된다.
3. 값 타입과 불변 객체
member1.setHomeAddress(new Address("oldCIty"));
Address address = member1.getHomeAddress();
address.setCity("newCity");
member2.setHomeAddress(address);
- 영속성 컨텍스트는 회원1의 주소도 newCity로 변경시켜버린다.
- 이러한 부작용을 막으려면 값을 복사해서 사용하면 안된다.
값 타입 복사
- 자바는 기본 타입에 값을 대입하면 값을 복사해서 전달하고 객체에 값을 대입하면 참조값을 전달한다. (Call by value, Call by reference)
- 문제는 임베디드 타입처럼 직접 정의한 값 타입은 자바의 기본타입이 아니라 객체 타입이여서 대입해서 사용하게 되면 공유 참조로 인한 Side Effect가 발생할 수 있다.
- 객체의 공유참조는 피할 수 없는데, 따라서 근본적인 해결책이 필요하다.
- 가장 단순한 방법은 객체의 값을 수정하지 못하게 막으면 공유 참조해도 값을 변경하지 못하므로 부작용을 막을 수 있다.
불변 객체
- 객체를 불변하게 만들면 값을 수정할 수 없으므로 부작용이 원천 차단 가능하다.
- 따라서 되도록 값 타입은 불변 객체로 설계하자.
- 불변 객체도 결국 객체여서 참조 값 공유를 피할 수는 없지만 인스턴스의 값을 수정할 수 없으므로 부작용이 발생하지 않는다.
- 불변 객체를 구현하는 방법은 다양하지만 가장 간단한 방법은 생성자로만 값을 설정하고 수정자를 만들지 않으면 된다. (setter를 제거)
4. 값 타입의 비교
- 자바가 제공하는 객체 비교 2가지
- 동일성 : ==
- 동등성 : equals()
- 값 타입을 비교할 때는 equlas()를 사용해서 동등성을 비교해야 한다.
- 값 타입의 equals() 메소드를 재정의할 때는 모든 필드값을 비교하도록 구현한다.
- 자바에서 equals()를 재정의하면 hashCode()도 재정의하는 것이 안전하다. 그렇지 않으면 해시를 사용하는 컬렉션(HashSet, HashMap)이 정상 동작하지 않는다.
5. 값 타입 컬렉션
값 타입을 하나 이상 저장 하려면 컬렉션에 보관하고 @ElementCollection, @CollectionTable 어노테이션을 사용하면 된다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@Embedded
private Address homeAddress;
@ElementCollection
@CollectionTable(
name = "FAVORITE_FOODS",
joinColumns = @JoinColumn(name = "MEMBER_ID"))
@Column(name="FOOD_NAME")
private Set<String> favor丄teFoods = new HashSet<String>();
@ElementCollection
@CollectionTable(
name = "ADDRESS”,
joinColumns = @JoinColumn(name = "MEMBER_ID"))
private List<Address> addressHistory = new ArrayList<Address>();
//...
}
@Embeddable
public class Address {
@Column
private String city;
private String street;
private String zipcode
//...
}
FavoriteFoods는 기본값 타입인 String을 컬렉션으로 가진다.
이것은 데이터베이스 테이블로 매핑해야 하는데 관계형 데이터베이스의 테이블은 컬럼 안에 컬렉션을 포함할 수 없다.
따라서 별도의 테이블을 추가하고 @CollectionTable를 사용해서 추가한 테이블을 매핑 해야 한다.
값 타입 컬렉션의 제약사항
- 값 타입 컬렉션에 변경 사항이 발생하면, 값 타입 컬렉션이 매핑된 테이블의 연관된 모든 데이터를 삭제하고, 현재 값 타입 컬렉션 객체에 있는 모든 값을 데이터베이스에 다시 저장한다.
- 값 타입 컬렉션의 매핑된 테이블에 데이터가 많다면 값 타입 대신 일대다 관계를 고려해야 한다.
- 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본 키를 구성해야 한다. 따라서 데이터베이스 기본 키 제약조건으로 인해 null을 입력할 수 없고, 같은 값을 중복해서 저장할 수 없는 제약도 있다.
- 이러한 문제를 해결하려면 값 타입 컬렉션 대신 새로운 엔티티를 만들어서 일대다 관계로 설정하고 cascade + orphan remove 기능을 적용하면 값 타입 컬렉션처럼 사용할 수 있다.
'스터디 > 자바 ORM 표준 JPA 프로그래밍' 카테고리의 다른 글
[JPA] 예외 처리와 엔티티 비교 (1) | 2024.01.25 |
---|---|
[JPA] 스프링 데이터 JPA (2) (0) | 2023.12.14 |
[JPA] 객체지향 쿼리와 JPQL (1) | 2023.11.09 |
[JPA] 복합키에서 equals () 및 hashCode () 구현 (0) | 2023.10.05 |
Comments