본문으로 바로가기

값 타입과 불변 객체

category Spring/Spring JPA 2024. 3. 22. 23:11

값 타입 공유 참조

  • 임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험함
  • 부작용 발생

예제

Main.java

Address address = new Address("city", "street", "10000");

Member member = new Member();
member.setUsername("member1");
member.setHomeAddress(address);
em.persist(member);

Member member2 = new Member();
member2.setUsername("member1");
member2.setHomeAddress(address);
em.persist(member2);

member.getHomeAddress().setCity("newCity");

tx.commit();

 

  • member의 city 를 newCity 로 변경했는데 member2도 같이 변경되는 오류 발생함!!

실행 결과

 

  • 값 타입의 실제 인스턴스인 값을 공유하는 것은 위험
  • 대신 값(인스턴스)를 복사해서 사용

예시

Main.java

Address address = new Address("city", "street", "10000");

Member member = new Member();
member.setUsername("member1");
member.setHomeAddress(address);
em.persist(member);

Address copyAddress = new Address(address.getCity(), address.getStreet(), address.getZipcode());
Member member2 = new Member();
member2.setUsername("member1");
member2.setHomeAddress(copyAddress);
em.persist(member2);

member.getHomeAddress().setCity("newCity");

tx.commit();

 

실행결과

 

객체 타입의 한계

  • 항상 값을 복사해서 사용하면 공유 참조로 인해 발생하는 부작용을 피할 수 있다.
  • 문제는 임베디드 타입처럼 직접 정의한 값 타입은 자바의 기본 타입이 아니라 객체 타입이다.
  • 자바 기본 타입에 값을 대입하면 값을 복사한다.
  • 객체 타입은 참조 값을 직접 대입하는 것을 막을 방법이 없다.
  • 객체의 공유 참조는 피할 수 없다.

 

불변 객체

  • 객체 타입을 수정할 수 없게 만들면 부작용을 원천 차단
  • 값 타입은 불변 객체로 설계해야함
  • 불변 객체 : 생성 시점 이후 절대 값을 변경할 수 없는 객체
  • 생성자로만 값을 설정하고 수정자(Setter) 를 만들지 않으면 됨
  • 참고 : Integer, String 은 자바가 제공하는 대표적인 불변 객체

예시

Address.java

@Embeddable
@Getter
public class Address {

    private String city;
    private String street;
    private String zipcode;

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

    public Address() {
    }
}

 

변경 하려 하면 오류가 난다.

 

 

근데 setter 를 다 없애버려서 member만 있을 경우에도 변경이 안되는 문제가 발생한다.

만약 값을 변경하고 싶은 경우에는 어쩔 수 없이 새로운 객체를 다시 생성해서 넣어줘야된다.

 

예제

Main.java

Address address = new Address("city", "street", "10000");

Member member = new Member();
member.setUsername("member1");
member.setHomeAddress(address);
em.persist(member);

Address newAddress = new Address("NewCity", address.getStreet(), address.getZipcode());
member.setHomeAddress(newAddress);


tx.commit();

 

 

 

'Spring > Spring JPA' 카테고리의 다른 글

값 타입 컬렉션  (0) 2024.03.29
값 타입의 비교  (0) 2024.03.29
임베디드 타입  (0) 2024.03.22
값 타입  (0) 2024.03.22
실습 5 - 연관관계 관리  (0) 2024.03.20