JPA/JPA 기본

33. 값타입과 불변 객체

sdafdq 2023. 10. 29. 20:13

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

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

 

 

우리가 int, String 같은 건 써도 크게 신경을 안쓰지만,

객체는 신경쓴다.

 

왜냐하면 객체는 주소를 넘기는 것 이기 때문에.

 

 

근데, 앞서 봤겠지만, 임베디드는 자바입장에서는 클래스임. 그래서 사실 공유가 가능하게 됨.

 

그래서 이 임베디드를 여러 엔티티에서 공유하게 될 수도 있어서 위험함.

 

Address address = new Address("city1", "street1", "zip1");
Member member1 = new Member();
member1.setName("memberA");
member1.setHomeAddress(address);
member1.setPeriod(new Period());
em.persist(member1);

Member member2 = new Member();
member2.setName("memberB");
member2.setHomeAddress(address);
member2.setPeriod(new Period());
em.persist(member2);

member1.getHomeAddress().setZipcode("zip2");

tx.commit();

뭐 예를 들어, member1과 member2는 같은 동네 사람들이라 저렇게 똑같이 했다가,

zip 코드만 바꾸게끔 하고 싶어서 했는데,

 

이게 클래스는 주소로 넘어가는 거라서 member1가 가리키는 address랑 member2가 가리키는 address 둘이 같아서 member1의 address를 조금 바꾸면 member2의 adress도 바뀜.

 

자바 입장에서는 객체임.

 

뭐 예를 들어 가족이라서 주소가 같아서 공유하고 싶은 거라면, 엔티티로 바꿔서 사용해야 함.

 

근데 일단은, 값타입의 실제 인스턴스를 공유하는 것은 위험함. 

복사해서 사용해야 함.

 

Address address = new Address("city1", "street1", "zip1");
Member member1 = new Member();
member1.setName("memberA");
member1.setHomeAddress(address);
member1.setPeriod(new Period());
em.persist(member1);

Address copyAddress  =new Address(address.getCity(), address.getStreet(), address.getZipcode());

Member member2 = new Member();
member2.setName("memberB");
member2.setHomeAddress(copyAddress);
member2.setPeriod(new Period());
em.persist(member2);

member1.getHomeAddress().setZipcode("zip2");

tx.commit();

이렇게 copyAddress 처럼

 

 

근데.. 만약 실수로 아까처럼 둘다 homeAddress를 address로 집어 넣으면,

이런 것 들은 컴파일 단계에서 막기 힘들다.

 

기본타입은 값이 복사되어 넘어가는데..

 

 

이를 위해 할 수 있는 방법 중 하나는

객체타입을 수정불가하게 만들 면 됨.

값타입은 불변객체로 설계 해야 함.

불변객체란 생성 시점 이후에는 절대 값을 변경할 수 없는 객체.

 

생성자로만 값을 설정할 수 있고, setter는 만들지 않으면 됨.

 

Integer, String이 자바에서 제공하는 대표적인 불변객체임.

 

 

@Embeddable
public class Address {
    private String city;
    private String street;
    private String zipcode;

    public Address() {
    }
    public Address(String city, String street, String zip) {
        this.city = city;
        this.street = street;
        this.zipcode = zip;
    }

    public String getCity() {
        return city;
    }
    public String getStreet() {
        return street;
    }
    public String getZipcode() {
        return zipcode;
    }
}

이렇게 setter 다 지움.

 

아니면 내부적으로 쓰고 싶으면 private로 만들어도 되고.

 

 

여튼, 값타입은 이런 식으로 불변 객체로 설계하셈.

 

 

 

 

'JPA > JPA 기본' 카테고리의 다른 글

35. 값타입 컬렉션  (0) 2023.10.29
34. 값타입 비교  (0) 2023.10.29
32. 임베디드 타입  (0) 2023.10.29
31. 기본값 타입  (0) 2023.10.29
30. 실전 연관관계 관리  (0) 2023.10.29