JPA 기본 | 데이터 타입(1) - 기본 값과 임베디드 값 타입

2024. 7. 14. 18:42· 인프런 김영한 강의 정리/자바 ORM 표준 JPA 프로그래밍 기본편
목차
  1. 1. 기본값 타입
  2. 2. 임베디드 값 타입(복합 값 타입)
  3. 2-1) 임베디드 값 타입 사용법
  4. 2-2) @AttributeOverride (속성 재정의)
  5. 2-3) 임베디드 값 타입 특징
  6. 2-4) 임베디드 값 타입 비교
728x90

JPA의 데이터 타입

1. 기본값 타입

  • 생명주기를 엔티티에 의존
  • 값 타입은 공유되지 않는다. (변경시 다른 값도 변경되면 안된다.)
  • 래퍼 클래스나 String같은 클래스는 공유가능한 객체지만 변경안됨.

2. 임베디드 값 타입(복합 값 타입)

재사용 가능한 값 타입 객체를 정의하여 엔티티의 일부분으로 포함시킨다.

 

2-1) 임베디드 값 타입 사용법

✅임베디드 값 타입 사용 예시

임베디드 값 타입 사용 예시

위 그림을 차근차근 설명해보자면,

✔️ 멤버 엔티티는 이름, 근무 시작일(startDate), 근무 종료일(endDate), 주소 도시(city), 주소 번지(street), 주소 우편번호(zipcode)를 가진다.

근무 시작일, 근무 종료일은 기간으로 묶을 수 있다.

주소 도시, 주소 번지, 주소 우편번호는 주소로 묶을 수 있다.

✔️ @Embeddable 애노테이션을 사용한 Period, Address 클래스를 만들어준다. (새로운 값 타입 직접 정의)

✔️ 멤버 엔티티에 @Embedded 애노테이션을 사용해서 Period, Address 값 타입을 넣어준다.

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

 

✅임베디드 값 타입 정의 코드

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

    public Period() {
    }

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



@Embeddable
@Getter
@Setter
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;
    }
}
  • @Embeddable 을 사용하여 임베디드 값 타입을 정의한다.
  • 기본 생성자가 필수다.

✅Member 엔티티

@Entity
@Getter
@Setter
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를 붙인다.

✅main 메서드

public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            Member member = new Member();
            member.setUsername("ururuwave");
            member.setHomeAddress(new Address("city","street","10000"));
            member.setWorkPeriod(new Period(LocalDateTime.of(2024, 1, 1,9,0),LocalDateTime.of(2024,7,1,9,0)));

            em.persist(member);

            tx.commit();
        }catch (Exception e){
            tx.rollback();
            e.printStackTrace(); //예외 출력
        }finally {
            em.close();
        }
    }
  • 단순히 멤버 인스턴스 생성해서 값 입력하는 코드다.

✅DB 확인

  • 임베디드 타입은 엔티티의 값일 뿐이다.
  • Period, Address 값 타입을 그대로 필드명으로 쓰는게 아니라 임베디드 값 타입 안에 있는 것들을 필드명으로 사용한다. -> 그래서 임베디드 타입을 사용하기 전과 후에 매핑하는 테이블이 동일하다.

2-2) @AttributeOverride (속성 재정의)

  • 한 엔티티에서 같은 값 타입을 사용하면 컬럼명이 중복되기때문에 오류가 난다.
  • @ AttributeOverrides, @AttributeOverride를 사용해서 컬럼명 속성을 재정의한다. 

✅예시

@Embedded
    private Address homeAddress;

@Embedded
@AttributeOverrides({
        @AttributeOverride(name = "city", column = @Column(name = "WORK_CITY")),
        @AttributeOverride(name = "street", column = @Column(name = "STREET_CITY")),
        @AttributeOverride(name = "zipcode", column = @Column(name = "ZIPCODE_CITY"))})
	private Address workAddress;

 

  • Address 값 타입을 중복 사용하고 있다.
  • 속성을 재정의해서 컬럼명이 중복되지 않도록 해준다.

 

2-3) 임베디드 값 타입 특징

✔️여러 엔티티에서 재사용할 수 있다

- 코드 중복을 줄이고 일관성 유지를 할 수 있다.

 

✔️ 독립적인 생명 주기가 없다.

-임베디드 값 타입은 포함된 엔티티와 함께 생성, 수정, 삭제된다. 

 

✔️ null 가능

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

 

✔️ JPA 스펙의 제한 사항때문에 임베디드 값 타입 필드에 not null 제약조건을 거는 것이 불가능하다. 

🤔Q. JPA 스펙에서 기능을 막아둔 이유가 있지 않을 까? 왜 이렇게 만들었을까?

 

💡A1. 단점이 있다.

- 임베디드 값 타입이 여러 엔티티에 사용될 때, 각각의 엔티티에 일관된 제약 조건을 관리하는 것이 어렵다.

- 일관성 문제로 개발자의 실수나 데이터 불일치로 이어질 수 있다.

임베디드 값 타입은 독립적인 엔티티가 아니라, 특정 필드가 NOT NULL 조건을 가질 경우 값 타입의 모든 필드가 올바르게 초기화되지 않으면 엔티티를 저장할 수 없다.

 

💡A2. 하지만! 특정 상황에서 NOT NULL 제약 조건이 필요하다면 우회해서 사용할 수 있다.

- @AttributeOverride를 사용하여 임베디드 값 타입 필드를 포함하는 엔티티에서 개별 필드에 대해 속성을 재정의한다.

 

2-4) 임베디드 값 타입 비교

인스턴스가 달라도 그 안에 값이 같으면 같은 것으로 봐야한다.

객체를 == 비교를 하면 인스턴스의 참조값을 비교하기 때문에 인스턴스 안의 값이 같아도 false를 반환한다.

값 타입 안에 equals(), hashCode()를 오버라이드해야한다.

intelliJ에서 'Alt+Insert'를 눌러서 equlas(), hashCode()를 자동 생성해주면 된다.

 

💡참고로 equals() 메서드를 오버라이드할 때, hashCode() 메서드를 같이 오버라이드 해야한다.

왜냐하면, equlas()에 의해 동등하다고 판단되면 두 객체의 hashCode()값도 반드시 같아야하기 때문이다.

그래서 equals()와 hashCode() 메서드는 일관되게 동작해야한다.

 

💡임베디드 값 타입 뿐만 아니라 String, Integer와 객체 타입 값들도 모두 equals()로 비교해줘야한다.

Java의 기본 제공 클래스는 Java 표준 라이브러리에서 이미 equals()메서드를 적절히 오버라이드 하고 있어서 재정의할 필요없다.

 

✅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(city, address.city) &&
                Objects.equals(street, address.street) &&
                Objects.equals(zipcode, address.zipcode);
    }

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

 

✅equals()로 비교하기

public class ValueMain {
    public static void main(String[] args) {

        int a = 10;
        int b = 10;
        System.out.println("a == b: " + (a == b)); //true

        //address1과 address2는 인스턴스의 값이 같다.
        Address address1 = new Address("city", "street", "10000");
        Address address2 = new Address("city", "street", "10000");

        //'==' 비교는 인스턴스의 참조값을 비교한다.
        System.out.println("address1 == address2: " + (address1 == address2)); //fasle
        //'equals'는 인스턴스의 값을 비교한다. **값 타입에서 equals()메소드를 재정의해야함.
        System.out.println("address1 equals address2: " + (address1.equals(address2))); //true
    }
}

 

 

728x90

'인프런 김영한 강의 정리 > 자바 ORM 표준 JPA 프로그래밍 기본편' 카테고리의 다른 글

JPA 기본 | 데이터 타입(3) - 값 타입 컬렉션  (0) 2024.07.14
JPA 기본 | 데이터 타입(2) - 값 타입 공유와 불변객체  (0) 2024.07.14
JPA 기본 | 영속성 전이(CASCADE)와 고아 객체  (0) 2024.07.13
JPA 기본 | 즉시 로딩과 지연 로딩  (0) 2024.07.13
JPA 기본 | 프록시 (즉시 로딩, 지연 로딩을 이해하기 위한)  (0) 2024.07.13
  1. 1. 기본값 타입
  2. 2. 임베디드 값 타입(복합 값 타입)
  3. 2-1) 임베디드 값 타입 사용법
  4. 2-2) @AttributeOverride (속성 재정의)
  5. 2-3) 임베디드 값 타입 특징
  6. 2-4) 임베디드 값 타입 비교
'인프런 김영한 강의 정리/자바 ORM 표준 JPA 프로그래밍 기본편' 카테고리의 다른 글
  • JPA 기본 | 데이터 타입(3) - 값 타입 컬렉션
  • JPA 기본 | 데이터 타입(2) - 값 타입 공유와 불변객체
  • JPA 기본 | 영속성 전이(CASCADE)와 고아 객체
  • JPA 기본 | 즉시 로딩과 지연 로딩
백엔드 개발자 - 젤리곰
백엔드 개발자 - 젤리곰
오늘도 배움이 있는 하루가 되길 바라는 개발자
백엔드 개발자 - 젤리곰
backend-gummyBear
백엔드 개발자 - 젤리곰
전체
오늘
어제
  • 분류 전체보기 (144)
    • 인프런 김영한 강의 정리 (60)
      • 스프링 핵심원리 기본편 (12)
      • 모든 개발자를 위한 HTTP 웹 기본 지식 (10)
      • 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 (3)
      • 자바 ORM 표준 JPA 프로그래밍 기본편 (28)
      • 실전! Querydsl (6)
    • Spring (2)
    • 프로젝트일지 (6)
    • 프로그래밍 언어 (20)
      • Java (17)
      • JavaScript (3)
      • Python (0)
    • 데이터베이스 (4)
      • Oracle (2)
      • ORM (1)
      • SQL 튜닝 (1)
    • 형상관리 (1)
      • Git (0)
    • 알고리즘&자료구조 (34)
      • Algorithm (31)
      • Data Structure (1)
    • CS지식 (4)
    • Cloud (5)
    • 일기 (7)
      • 공부 일기 (3)
      • 독서 일기 (2)
      • 마음 일기 (2)

블로그 메뉴

  • 홈
  • 태그

공지사항

인기 글

태그

  • LeetCode200번
  • 프론트엔드역사
  • dfs알고리즘
  • LeetCode17번
  • 객체지향의사실과오해
  • 커스텀annotation
  • 객체지향방법론
  • ORM프레임워크
  • 업캐스팅
  • 다운캐스팅
  • SublimeText단축키
  • 프론트엔드개발자업무
  • 클라이언트서버통신
  • 인프콘
  • 인터페이스
  • #{}와${}의차이
  • jquery와javascript
  • 힙자료구조
  • 데이터베이스정규화
  • 스프링컨텍스트

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
백엔드 개발자 - 젤리곰
JPA 기본 | 데이터 타입(1) - 기본 값과 임베디드 값 타입
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.