Skip to content

Latest commit

 

History

History
133 lines (131 loc) · 9.31 KB

JPA#2.md

File metadata and controls

133 lines (131 loc) · 9.31 KB
  • 값 타입
ㅇ 기본값 타입
ㅇ 임베디드 타입 (복합값 타입) - 중요★
ㅇ 값 타입과 불변 객체
ㅇ 값 타입의 비교
ㅇ 값 타입 컬렉션 - 중요★
ㅇ 정리
  1. 기본값 타입 + 엔티티 VS 값 타입
    • 엔티티는 데이터가 변해도 식별자로 추적 가능 (@Entity)

    • 값타입은 식별자가 없고 값만 있으므로 추적 불가능 (int, Integer, String)

    • 값 타입 분류

      • 기본값 타입
        • 자바 기본 타입 (int,double)
        • 래퍼 클래스 (Integer,Long)
        • String
        • 생명 주기를 엔티티에 의존(★)
          • 회원을 삭제하면 이름, 나이 필드도 함께 삭제
        • 값 타입은 공유하면 X (★)
          • 회원 이름 변경 시 다른 회원의 이름도 함께 변경되면 안됨
        • int double 같은 기본타입(primitive type)은 절대 공유 X
        • 기본 타입은 항상 값이 복사함
        • Integer 같은 래퍼 클래스나 String 같은 특수한 클래스는 공유 가능한 객체지만 변경 X

  1. 임베디드 타입 (embedded type, 복합 값 타입)
    • 좌표 등(x와 y를 같이 묶어서 사용하고 싶음)
    • 새로운 값 타입을 직접 정의할 수 있음
    • 주로 기본 값 타입을 모아서 만들어서 복합 값 타입이라고도 함
    • int,String과 같은 값 타입
    • 회원 엔티티는 이름, 근무 시작일, 근무 종료일, 주소 도시, 주소 번지, 주소 우편번호를 가진다.
      • 근무 시작,종료일 / 주소 도시 ,번지,우편번호는 공통으로 쓸 수 있지 않을까?
    • 장점
      • 재사용
      • 높은 응집도
      • Period.isWork()처럼 해당 값 타입만 사용하는 의미있는 메소드를 만들 수 있음
      • 임베디드 타입을 포함한 모든 값 타입은, 값 타입을 소유한 엔티티에 생명 주기를 의존함
      • 객체와 테이블을 아주 세밀하게 매핑 하는 것이 가능해진다.
    • @AttributeOverrides / @AttributeOverride 를 사용하면 한 엔티티에서 같은 값 타입을 사용할 수 있다.
    • 임베디드 컬럼은 매핑한 컬럼 값은 모두 NULL

  1. 값 타입과 불변 객체
    • 값 타입은 복잡한 객체 세상을 조금이라도 단순화 하려고 만든 개념이다. 따라서 값 타입은 단순하고 안전하게 다룰 수 있어야한다.
    • 값 타입 공유 참조 (★)
      • 임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험함!! (한 곳이라도 값을 변경하면 다른 엔티티의 값도 변경됨) (★)
      • 부작용(side effect) 발생
      • 대신 값(인스턴스)을 복사해서 사용ㄱ
    • 객체 타입의 한계
      • 항상 값을 복사해서 사용하면 공유 참조로 인해 발생하는 부작용을 피할 수 있다.
      • 문제는 임베디드 타입처럼 직접 정의한 값 타입은 자바의 기본 타입이 아니라 객체 타입이다.
      • 자바 기본 타입에 값을 대입하면 값을 복사한다.
      • 객체 타입은 참조 값을 직접 대입하는 것을 막을 방법이 없다.
      • 객체의 공유 참조는 피할 수 없다.
    • 불변 객체
      • 객체 타입을 수정할 수 없게 만들면 부작용을 원천 차단
      • 값 타입을 불변 객체(immutable object)로 설계해야함
      • 불변 객체: 생성 시점 이후에 절대 값을 변경할 수 없는 객체
      • 생성자로만 값을 설정하고 수정자(Setter)를 만들지 않으면 됨 (임베디드 타입에)
      • 참고 : Integer,String은 자바가 제공하는 대표적인 불변 객체
      • 불변이라는 작은 제약으로 부작용이라는 큰 재앙을 막을 수 있다. ※ 임베디드 타입을 Setter를 지움 / Setter 접근 제한자를 private으로 변경함으로써 불변객체를 만들고 side effect를 없앤다. ※ 값을 변경하고 싶으면 새로운 인스턴스를 만들어서 다시 집어넣는다. ※ 전부 다 무조건 불변으로 만들어라 (★★★)

  1. 값 타입 비교
    • 동일성(identity) 비교 : 인스턴스의 참조 값을 비교 , ==사용
    • 동등성비(equivalence) 비교 : 인스턴스의 값을 비교, equals() 사용
    • 값 타입은 a.equals(b)를 사용해서 동등성 비교를 해야함
    • 값 타입은 equals() 메소드를 적절하게 재정의(주로 모든 필드 사용) - @Override equals를 사용해서 비교해야함

  1. 값 타입 컬렉션 (collection value type)
    • 값 타입 컬렉션이란?
      • 자바 컬렉션에 기본 값 타입이나 입베디드 타입을 넣을 수 있는 것
      • 자바에서는 컬렉션에 값 타입이나 임베디드 타입을 넣지만 디비에서는 그런 타입이 없음
        • 최근에서야 디비에 JSON 타입이 도입 됐지만 기본적으로는 컬럼 하나에 하나의 값이 들어감
        • 이를 해결하기 위해 리스트로 담을 타입은 테이블로 빼야함
        • EX) LIST[Address] -> MEMBER를 ADDRESS테이블로 뺌
        • 빼낸 DB에 값들을 전부다 묶어서 PK로 저장을 해야한다.
      • 값 타입을 하나 이상 저장할 때 사용
      • @ElementCollaction, @CollationTable을 사용
      • DB에는 컬렉션을 같은 테이블에 저장할 수 없다. (리스트이기 때문에)
      • 별도의 테이블이 필요하다 --------- + 값 타입 컬렉션 사용
      • 값 타입 저장 예제
        • 값 타입 컬렉션은 본인 스스로의 라이프 사이클이 없다. 엔티티에 의존해서 엔티티가 해당 컬렉션을 저장하면 값타입 컬렉션 테이블에 데이터가 저장된다.
      • 값 타입 조회
        • 값 타입 컬렉션은 기본적으로 지연 로딩이다!!!
      • 값 타입 수정
        • 값 타입 :(setCity,setStreet,setZipCode로 변경하면 전체 참조하는 게 다 바뀜) 해결: 새로운 객체를 넣어야한다.
        • 값 타입 컬렉션 : Set[String] 일 경우, findUser.getFavoriteFoods().remove("족발"); -> findUser.getFavoriteFoods().add("한식");으로 remove 후 add List[Address] 일 경우, findUser.getAddressHistory().remove(new Address("old1","street1","zipcode1")); -> findUser.getAddressHistory().add(new Address("newCity1","street","zipcode")); 으로 객체를 통으로 바꿔줘야한다. ※ 이때 Address entity에서 equals를 제대로 override해야한다. 안그럼 망한다!!!! 중요!!!!★★★ (remove가 override받은 equals를 사용하기 때문)
      • 값 타입 컬렉션은 영속성 전이(cascade) + 고아 객체 제거 기능을 필수로 가진다고 볼 수 있다.
      • 값 타입의 제약 사항 (★★★)
        • 값 타입은 엔티티와 다르게 식별자 개념이 없다.
        • 값은 변경하면 추적이 어렵다.
        • 값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다. (★★★)
        • 해결 : @OrderColumn을 사용해서 잡을 순 있지만 엄청 굉장히 위험하다!!! 원하지 않는 데이터가 들어올 수도 있고 중간에 하나 없어지면 null이 들어옴
        • 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본키를 구성해야함: null입력 x, 중복 저장 x
        • 웬만하면 값타입 컬렉션을 사용하지 않는 게 좋음!!!! (★)
      • 값 타입 컬렉션 대안
        • 실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 고려!!
        • 값 타입을 래핑해서 엔티티로 승급한 후 oneToMany로 일대다 관계를 만들어서 사용한다. (★)
        • 값 타입을 oneToMany로 엔테테로 한 번 래핑해서 값타입을 엔티티로 승급해서 사용
        • 실제로 실무에서는 이 방법을 많이 사용함 (영한님)
        • ex) addressEntity
      • 값 타입 컬렉션을 언제 사용하느냐?
        • 셀렉트 박스에 (치킨,햄버거,짜장면,피자 등)을 여러가지 선택할 수 있을 때
        • 값이 단순할 때.(선호도?)
        • 값이 바뀌어도 업데이트 칠 필요가 업을 떄
        • 값을 추적하지 않아도 될 때
        • 주소 이력 같은건 전부 다 엔티티임!!

  1. 정리
    • 엔티티 타입의 특징
      • 식별자 O
      • 생명 주기 관리
      • 공유
    • 값 타입의 특징
      • 식별자 X
      • 생명주기를 엔티티에 의존
      • 공유하지 않는 것이 안전(복사해서 사용)
      • 불변 객체로 만드는 것이 안전
    • 주의사항
      • 값 타입은 정말 값 타입이라 판단 될 때만 사용!! ( EX.포지션(X,Y좌표))
      • 엔티티와 값 타입을 혼동해서 엔티티를 값 타입으로 만들면 안됨
      • 식별자가 필요하고, 지속해서 값을 추적, 변경해야한다면 그것은 값타입이 아닌 엔티티