JPA

Embedded Type

lby132 2022. 10. 19. 23:10

엔티티객체를 만들다보면 

@Entity
public class Member extends BaseEntity {

    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
    private String name;
    private String city;
    private String street;
    private String zipcode;
    private LocalDateTime startDate;
    private LocalDateTime endDate;

이렇게 뭔가 공통적인걸 묶을 수 있을것 같은걸로 만들때가 있는데

예를 들면 city, street, zipcode 와 startDate, endDate를 각각 묶을수 있을것 같은 느낌이든다.

그때 사용하는게 Embedded 이다.

예시로는 

@Embeddable
public class Address {

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

    private LocalDateTime startDate;
    private LocalDateTime endDate;

}

이렇게 공통으로 묶을 수 있는 객체를 만들어서 @Embeddable를 써주고

@Entity
public class Member {

    @Id   
    @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

    @Embedded
    private Period workPeriod;

    @Embedded
    private Address homeAddress;

@Embedded를 사용하므로써 공통된건 따로따로 묶어주면 객체 하나로 관리 할 수 있게 하는 방법도 있다.

EmbeddedType은 기본타입의 집합체이다. 하지만 하나로보면 객체타입이다. 기본타입은 값을 대입하면 복사가 되지만 객체타입은 값을 공유하면 같은걸 참조하게 된다. 즉 객체는 공유참조는 피할수가 없다.

예를들어 

final Address address = new Address("city", "street", "100");

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

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

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

이렇게 address를 하나 생성해서 member과 member2에 넣어주고 member에 city값만 변경해준다면 member만 변경되는게 아니라 member2에 city값도 당연히 같이 변경될 것이다. 대체 방법은 set메서드는 없애는 등으로 Embedded로 설정한 객체를 불변객체로 만들던지 

final Address address = new Address("city", "street", "100");

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

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

final Member member2 = new Member();
member2.setUsername("member2");
member2.setHomeAddress(copyAddress);
em.persist(member2);

이런 식으로 두개의 참조값을 생성해서 각자 넣어주어야 한다. 잘못사용하면 정말 위험한..

마지막으로 Embedded Type은 equals()를 재정의 해주는게 좋다.

@Embeddable
public class Address {

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Address address = (Address) o;
        return Objects.equals(city, address.city) && Objects.equals(street, address.street) && Objects.equals(zipcode, address.zipcode);
    }

    @Override
    public int hashCode() {
        return Objects.hash(city, street, zipcode);
    }
}

'JPA' 카테고리의 다른 글

Merge와 변경감지  (0) 2022.11.26
Join Fetch  (0) 2022.10.21
테이블 전략  (0) 2022.10.18
mappedBy  (0) 2022.10.18
IDENTITY전략  (0) 2022.10.17