JPA의 데이터 타입 - 값 타입, 엔티티 타입(3)

2022. 3. 26. 20:36JPA 기초

값타입과 불변객체
값 타입은 복잡하고 어지러운 객체세상을 조금이라도 단순화하기위해 사용한다.

임베디드 타입 같은 값타입은 여러 엔티티에서 공유가 가능하다. 임베디드 타입은 값 타입임에도 불구하고, 임베디드 타입의 값을 변경하면 이를 공유하고 있는 여러 엔티티에서 전부 값이 변경된다.   
첫번째 멤버의 embedded 타입인 도시를 변경하였는데 업데이트 쿼리는 두번 전송된다.

 

            Address address = new Address("Seoul", "mapo", "100");
            Member member1 = new Member();
            member1.setUsername("Kim");
            member1.setHomeAddress(address);

            em.persist(member1);

            Member member2 = new Member();
            member2.setUsername("Lee");
            member2.setHomeAddress(address);

            em.persist(member2);

            member1.getHomeAddress().setCity("NewCity");

위의 코드처럼 member1의 city값을 변경하면?

member2의 도시도 NewCity로 변경되었다.

 

임베디드 타입 같은 값 타입은 여러 엔티티에서 공유하면 매우 위험하다. 공유하고 싶다면 address를 Entity로 설정하는 것이 옳다.

혹은 값(인스턴스)을 복사해서 사용하면 해결할 수 있다.

 

            Address modifyCity = new Address("NewCity", address.getStreet(), address.getZipcode());
            member1.setHomeAddress(modifyCity);

이런 방식으로 새로 만든 객체로 갈아끼우면 member2에는 아무런 영향이 없다.

 

근데 사람은 실수인지라 이처럼 일일이 복사를 안하고 넣는 경우가 있을 것이다..

항상 값 복사 후 사용하면 공유 참조로 인한 부작용은 피할 수 있다.  

 

임베디드 타입처럼 직접 정의한 값 타입은 기본타입이 아닌 객체타입이다. 객체 타입은 복사가 아니라 참조 값을 직접 대입한다. 따라서 객체의 공유 참조는 피할 수 없는 것이다.

애초에 객체 타입을 수정할 수 없게 만든다면???? 부작용을 원천 봉쇄할 수 있다. 따라서 값 타입은 불변객체(immutable object)로 설계해야 한다. 
불변객체: 생성 시점 이후 절대 값을 변경할 수 없는 객체를 말한다. 

생성자로만 값을 설정하고, setter를 만들지 않으면 된다. 


Integer나 String이 대표적인 불변객체다.

내 코드의 경우에는 
Address 클래스 내의 setter 메서드를 전부 지우면 되겠다. 

그리하면 setCity()의 호출을 원천 봉쇄 가능하다~

 

값을 변경하고 싶다면 

            Address modifyCity = new Address("NewCity", address.getStreet(), address.getZipcode());
            member1.setHomeAddress(modifyCity);

이 코드블럭처럼 새로 객체를 생성한 뒤 완전히 갈아끼우자.