값 타입은 복잡한 객체 세상을 조금이라도 단순하게 하려고 만든 개념이다.
따라서 값 타입은 단순하고 안전하게 다룰 수 있어야 한다.
값 타입 공유 참조
-임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험하다.
-부작용(side Effect)발생
여러객체에서 이 값을 변경해버리면 변경된 값이 저장되어 버리기 때문
임베디드 타입 공유
Address address = new Address("city" , "street" , "10000");
Member member =new Member();
member.setHomeAddress(address);
em.persist(member);
Member member2 = new member()
member2.setHomeAddress(address);
em.persist(member2);
만약 위와같이 각각의 엔티티가 하나의 임베디트(Address)를 사용하고 있을경우
하나의 엔티티에서 임베디드의 값을 변경할 경우
member.getHomeAddress.setCity("new city")
임베디드의 값이 변경되어 버린다.
위 경우는 임베디드 객체르 1개만 생성해서 각 엔티티가 사용한 경우
만약 값타잆 하나를 바꾸어서 다른 모든 엔티티가 값이 변경되는 위 사이트이펙트 같은 효과를 의도하고 사용한거라면
임베디드 타입을 쓰는게 아니라 값타입을 사용해야한다,
값타입의 복사
그래서 위와같이
-값 타입의 실제 인스턴스 값을 공유하는것은 위험하다
-대신 값(인스턴스)를 복사해서 사용한다.
임베디드 값을 복사해서 사용
Address address = new Address("city" , "street" , "10000");
Member member = new Member();
member.setHomeAddress(address);
em.persist(member);
Address copyAddress = new Address("city" , "street" , "10000");
// 같은 임베디드를 하나 더 만드는것 이것을 임베디드 복사 라 한다,
Member member1 = new Member();
member1.setHomeAddress(copyAddress);
em.persist(member1);
이후
member.getHomeAddress().setCity("new city");
임베디드의 값을 변경하게 되면
그에 해당하는 임베디드의 값만 변경되게 된다.
그런데 이 값 복사 방법에 문제와 한계가 존재한다.
객체 타입의 한계
-항상 값을 복사해서 사용하면 "공유 참조"로 인해 발생하는 부작용을 피할 수 있다.
-문제는 임베디드 타입처럼 직접 정의한 값 타입은 자바의 기본타입이 아니라 "객체 타입"이다.
-자바 기본타입에 값을 대입하면 값을 복사한다.
-객체 타입은 참조값을 직접 대입하는것을 막을 방법이 없다.
-객체의 "공유 참조"는 피할 수 없다.
객체는 타입만 맞으면 그냥 값이 들어가버려서 "공유 참조"를 막을수가 없다,
기본타입(primitive type)
int a = 10;
int b = a; // 자바 기본타입은 값을 복사한다.
b = 4;
자바 기본타입은 값만 복사하기 때문에 한쪽의 값을 바꾸어도 원본은 영향이 없다 (얕은복사)
객체타입
Address a = new Address("old");
Address b = a; // 객체 타입은 참조를 전달
b.setCity("new");
객체에 값복사는 주소값을 복사해서 서로가 같은 객체를 바라보게 된다,
그래서 값을 변경하면 전체에 영향을 준다.
불변객체
-객체 타입을 수정할 수 없게 만들면 부작용을 완전 차단 가능
-값타입을 불변객체(immitable Obejct)로 설계해야 한다.
-불변객체 : 생성시점 이후 절대 값을 변경할 수 없는 객체
-생성자로만 값을 설정하고 수정자(setter)를 임베디드 객체 자체에 만들어주지 않으면 된다.
-Integer , String은 자바가 제공하는 대표적인 불변객체 또는 set을 private로 만들면 된다,
불변객체의 값 변경
set이 안되기 떄문에 다음 방법을 사용해서 값을 변경한다,
Address address = new Address("city" , "street" , "10000");
member.setHomeAddress(address);
Address newAddress = new Address("newCity" , address.getStreet(), address.getZipcode())
member.setHomeAddress(newAddress),
임베디드타입을 다시생성해서 원하는 값을 바꾼뒤 member에 임베디드 타입을 다시 set 해주면 된다,
'JPA' 카테고리의 다른 글
| 2월 7일 JPA 값타입 컬렉션 저장@ElementCollection ,@CollectionTable (0) | 2023.02.07 |
|---|---|
| 2월 6일 JPA 값타입 비교 (0) | 2023.02.06 |
| 2월 3일 JPA 임베디드 속성의 재정의 (0) | 2023.02.03 |
| 2월 3일 JPA 임베디드 클래스 실사용 (0) | 2023.02.03 |
| 2월 3일 JPA 임베디드 타입class와 테이블을 매핑 (0) | 2023.02.03 |