본문 바로가기
자바/JPA

[JPA/Java] 값 타입 1 (기본 값, 임베디드(복합 값) 타입)

by drCode 2023. 3. 6.
728x90
반응형

JPA는 ORM 방식의 기술로 객체를 테이블에 매핑시켜서 데이터를 관리한다.

 

객체를 필드로 넣는다고 가정할 때,

 

DB에 데이터를 넣을 때 필드로 넣은 객체에 종속된 필드를 테이블에 같이 넣을 수 있다.

 

그에 대한 설명에 앞서, JPA의 데이터 타입 분류는 아래와 같다.

 

JPA의 데이터 타입 분류

(1) 엔티티 타입

     - @Entity로 정의하는 객체

     - 데이터가 변해도 식별자로 지속해서 추적이 가능하다.

     - 예) 회원 엔티티의 키나 나이 값을 변경해도 식별자로 인식이 가능하다.

(2) 값 타입

     - int, integer, String 처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체

     - 식별자가 없고 값만 있으므로 변경시 추적 불가

     - 예) 숫자 100을 200으로 변경하면 완전히 다른 값으로 대체 한다.

 

값 타입 분류

(1) 기본 값 타입

    - 자바 기본 타입(int, double)

    - 래퍼 클래스(Integer, Long)

    - String

(2) 임베디드 타입(embedded type, 복합 값 타입)

(3) 컬렉션 값 타입(collection value type)

 

기본 값 타입은 생명주기를 엔티티에 의존한다.

 - 예를 들어, 회원을 삭제하면 이름, 나이 필드도 함께 삭제된다.

 

값 타입은 공유하면 안된다.

 - 예를 들어, 회원 이름 변경 시 다른 회원의 이름이 함께 변경되는 경우가 있기 때문에 가급적 자제해야한다.

 

참고로, 자바의 기본 탕비은 절대 공유하면 안된다.

 - int, double 같은 기본 타입(primitibe type)은 절대 공유하면 안된다

 - 기본 타입은 항상 값을 복사한다.

 - Integer 같은 래퍼 클래스나 String 같은 특수한 클래스는 공유 가능한 객체이지만 변경이 불가능하다.

 

임베디드 타입

 - 새로운 값 타입을 직접 정의할 수 있다.

 - JPA는 임베디드 타입(embedded type)이라고 한다.

 - 주로 기본 값 타입을 모아 만들어서 복합 값 타입이라고도 한다.

 - int, String과 같은 값 타입

 

회원 엔티티는 이름, 근무 시작일, 근무 종료일, 주소, 도시, 주소번지, 주소 우편번호를 가진다.

Member

위 테이블을 기간과 주소와 같은 성격을 가진 변수들을 공통으로 묶을 수 있다.

 

회원 엔티티는 이름, 근무 기간, 집 주소를 가진다.

기본 값 타입을 임베디드 화
임베디드 타입 변수에 대한 상세, 복합 값 타입이다.

 

임베디드 타입 사용법은 아래와 같다.

 - @Embeddable : 값 타입을 정의하는 곳에 표시

 - @Embedded : 값 타입을 사용하는 곳에 표시

 - 기본 생성자는 필수이다.

 

임베디드 타입의 장점

 - 재사용성

 - 높은 응집도

 - Period.isWrok() 처럼 해당 값 타입만 사용하는 의미있는 메소드를 만들 수 있다.

 - 임베디드 타입을 포함한 모든 값 타입은 값 타입을 소유한 엔티티에 생명주기를 의존한다.

 

임베디드 타입과 테이블 매핑

임베디드 타입을 테이블에 매핑한 결과

임베디드 타입은 엔티티의 값일 뿐이다.

임베디드 타입을 사용하기 전과 후에 매핑하는 테이블은 같다.

객체와 테이블을 아주 세밀하게(find-grained) 매핑하는 것이 가능하다

잘 설계한 ORM 애플리케이션은 매핑한 테이블 수보다 클래스의 수가 더 많다.

 

임베디드 타입과 연관관계

 

한 엔티티에 같은 값을 사용하면?

컬럼명이 중복되는데, 

@AttributeOverrides, @AttributeOverride 를 사용해서 컬럼명, 속성을 재정의하면 된다.

 

임베디드 타입의 값이 null이면 매핑한 컬럼 값은 모두 null이다.

 

Member.java

@Entity
public class Member {

	/**
    	중략
    */
	
    // 기간 Period
    @Embedded
    private Period workPeriod;

    // 주소
    @Embedded
    private Address homeAddress;
    
    /**
    	중략
    */
}

 

만약 homeAddress와 동일한 타입으로 workAddress를 사용한다면?

 

Member.java

    // 기간 Period
    @Embedded
    private Period workPeriod;

    // 주소
    @Embedded
    private Address homeAddress;

    // 중복 속성 발생으로 오류 발생
    // 쓸거면 AttributeOverrides 속성 사용해야함
    // 주소
    @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_ZIP_CODE"))
    })
    private Address workAddress;

 

위처럼 @AttributeOverrides를 사용해야 한다

 

 

Address.java

@Embeddable
public class Address {

    private String city;
    private String street;
//    @Column(name="ZIPCODE")
    private String zipCode;

    public Address() {}

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

 

Period.java

@Embeddable
public class Period {
    private LocalDateTime startDate;
    private LocalDateTime endDate;

    public Period() {}

    public Period(LocalDateTime startDate, LocalDateTime endDate) {
        this.startDate = startDate;
        this.endDate = endDate;
    }
}

 

 

728x90
반응형

댓글