값 타입2(임베디드)

Mina Park·2022년 9월 12일
0

1. 기본개념

  • 새로운 값 타입을 직접 정의
  • JPA에서는 임베디드 타입이라고 명명
  • 주로 기본값 타입을 모아서 만들기 때문에 "복합값 타입"이라고도 부름
  • int, String 과 같은 값 타입(엔티티X, 변경시 추적 불가)
  • 예시)

2. 사용법

  • @Embeddable: 값 타입을 정의하는 곳에 표시
  • @Embedded: 값 타입을 사용하는 곳에 표시
  • 기본생성자 필수

3. 장점

  • 재사용 가능
  • 높은 응집도
  • Period.isWork()처럼 해당 값 타입만 사용하는 의미 있는 메소드 생성 가능
  • 임베디드 타입을 포함한 모든 값 타입은, 값 타입을 소유한 엔티티에 생명주기를 의존함
  • validation 같은 공통 룰도 편리하게 한번에 적용
@Embeddable
public class Address {

    //컬럼길이 지정 같은 공통룰 적용도 편리
    @Column(length = 10)
    private String city;
    @Column(length = 20)
    private String street;
    @Column(length = 5)
    private String zipcode;

    //값타입은 의미있는 메소드 생성 가능
    public String fullAddress() {
        return getCity() + getStreet() + "-" + getZipcode();
    }

    //값타입이므로 불변객체로 만들기 위해 setter는 private으로 생성
    public String getCity() {
        return city;
    }

    private void setCity(String city) {
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    private void setStreet(String street) {
        this.street = street;
    }

    public String getZipcode() {
        return zipcode;
    }

    private void setZipcode(String zipcode) {
        this.zipcode = zipcode;
    }

    //equals, hashcode 오버라이드
    @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(getCity(), address.getCity()) && Objects.equals(getStreet(), address.getStreet()) && Objects.equals(getZipcode(), address.getZipcode());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getCity(), getStreet(), getZipcode());
    }
}

4. 임베디드 타입과 테이블 맵핑

@Entity
public class MemberMapping extends BaseEntity {

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

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

    //임베디드타입 Period
    @Embedded
    private Period workPeriod;

    //임베디드타입 Address
    @Embedded
    private Address homeAddress;

    @ManyToOne(fetch = FetchType.LAZY) //지연로딩 사용해서 프록시로 조회
    @JoinColumn(name = "TEAM_ID")
    private TeamMapping team;

    @OneToOne
    @JoinColumn(name = "LOCKER_ID")
    private Locker locker;

    @OneToMany(mappedBy = "member")
    private List<MemberProduct> memberProductList = new ArrayList<>();
    
    //...getter,setter
}
@Embeddable
public class Address {
    private String city;
    private String street;
    private String zipcode;

    public Address() {
    } //기본생성자 필수

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

    //...getter,setter
}
@Embeddable
public class Period {
    private LocalDateTime startDate;
    private LocalDateTime endDate;

    public Period() {
    } //기본생성자 필수

    public Period(LocalDateTime startDate, LocalDateTime endDate) {
        this.startDate = startDate;
        this.endDate = endDate;
    }
	
    //...getter,setter
}
  			MemberMapping member = new MemberMapping();
            member.setUsername("hello!!!");
            member.setHomeAddress(new Address("Seoul", "star-ro","1000"));
            member.setWorkPeriod(new Period());
            em.persist(member);

            tx.commit();

  • 임베디드 타입은 사실 엔티티의 값일 뿐
  • 임베디드 타입 사용 전/후 맵핑하는 타이블은 같음!!!
  • 객체와 테이블을 아주 세밀하게 맵핑할 수 있음
  • 잘 설계한 ORM 애플리케이션은 맵핑한 테이블의 수 < 클래스의 수

5. 임베디드 타입과 연관관계

  • 한 엔티티 안에서 값은 값 타입 사용 => 컬럼명 중복 => @AttributeOverrides, @AttributeOverride로 컬럼명 속성 재정의
@Entity
public class MemberMapping extends BaseEntity {

    ....

    //임베디드타입 Period
    @Embedded
    private Period workPeriod;

    //임베디드타입 Address
    @Embedded
    private Address homeAddress;
    
    //한 엔티티에 안에서 같은 값 타입을 사용하면 컬럼명이 중복되므로 @AttributeOverrides, @AttributeOverride로 컬럼명 속성 재정의
    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "city", column = @Column(name = "WORK_CITY")),
            @AttributeOverride(name = "street", column = @Column(name = "WORK_STREET")),
            @AttributeOverride(name = "zipcode", column = @Column(name = "WORK_ZIPCODE")),
    })
    private Address workAddress;

    //...getter,setter
}

6. 임베디드 타입과 null

  • 임베디드 타입의 값이 null => 맵핑한 컬럼값도 모두 null

0개의 댓글