본문 바로가기

JPA

2월 6일 JPA 값타입과 불변객체

값 타입은 복잡한 객체 세상을 조금이라도 단순하게 하려고 만든 개념이다.

따라서 값 타입은 단순하고 안전하게 다룰 수 있어야 한다.

 

값 타입 공유 참조

-임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험하다.

-부작용(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 해주면 된다,