📖
Kyu9's Repo
  • Library of mameil
  • 이슈 경험
    • 20230220_트랜잭션
    • 20230306_캐싱이슈
    • 20230722_테스트코드에서 @Transactional
    • 20230807_deadlock
  • 인턴 스터디
    • Gradle
    • Stream, Optional, 람다식
    • JVM의 메모리 구조, Garbage Collector
    • RESTful API
    • Microservice Architecture
    • HTTP
    • 웹서버란 무엇인가
    • Git Branch
    • TDD
    • Redis을 이용한 캐시
    • Thymeleaf
    • 정리가 필요한 자료들
    • SpringBoot Management
    • 테스크 코드 분할
  • 동아리 스터디
    • 기본 SQL 공부
      • SQL의 기본 개념
      • SELECT 문장을 이용하여 원하는 데이터 출력하기
        • 집합 연산자 사용하기
        • where절에 비교 연산자를 사용해보기
        • SELECT_EX
        • 산술 연산자 사용해보기
      • 단일 행 함수 사용
        • lower/upper 함수 사용하기
        • length함수 사용하기
        • concat함수 사용
        • substr/mid/substring 함수 사용
        • instr함수 사용하기
        • lpad/rpad 함수 사용하기
        • trim/ltrim/rtrim 함수 사용하기
        • replace 함수 사용하기
        • round 함수 사용하기
        • truncate 함수 사용하기
        • mod함수 사용하기
        • ceil함수 사용하기
        • floor함수 사용하기
        • power 함수 사용하기
        • Date fn(날짜 함수)
        • 형 변환 함수
        • 일반함수란
    • a-ha 실습
    • 혼자서 만들어본 게시판
    • AWS 강의
  • 학교 나머지 공부 자료
    • 웹프레임워크(Spring)
      • Spring이란?
      • Webframework1-1
      • Webframework1-2
      • SpringBoot의 특징
      • SpringBoot 생성 방법
      • Spring Data JPA
      • SpringBoot Security
      • SpringBoot HATEOAS
  • 공부 자료들
  • WS 온라인 자바 스터디
    • Week1(JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.)
    • Week2(자바 데이터 타입, 변수 그리고 배열)
    • Week3(연산자)
    • Week4(제어문)
    • Week5(클래스)
    • Week6(상속)
    • Week7(패키지)
    • Week8(인터페이스)
    • Week9(예외처리)
    • Week10(멀티쓰레드 프로그래밍)
    • Week11(Enum)
    • Week12(Annotation)
    • Week13(I/O)
    • Week14(Generic)
    • Week15(람다식)
  • 백준문제
    • 입출력과 사칙연산
      • We love kriii(10718)
      • 고양이(10171)
      • 개(10172)
      • A+B(1000)
      • A-B(1001)
      • AxB(10998)
      • A/B(1008)
      • 사칙연산(10869)
      • 나머지(10430)
      • 곱셈(2588)
    • for문
      • 구구단(2739)
      • A+B - 3(10950)
      • 합(8393)
      • 빠른 A+B(15552)
      • N 찍기(2741)
      • 기찍 N(2742)
      • A+B - 7(11021)
      • A+B - 8(11022)
      • 별 찍기 - 1(2438)
      • 별 찍기 - 2(2439)
      • X보다 작은 수(10871)
    • if문
      • 두 수 비교하기(1330)
      • 시험 성적(9498)
      • 윤년(2753)
      • 사분면 고르기(14681)
      • 알람 시계(2884)
      • 오븐 시계(2525)
      • 주사위 세개(2480)
      • 영수증(25304)
    • While문
      • A+B - 5(10952)
      • A+B - 4(10951)
      • 더하기 사이클(1110)
    • 1차원 배열
      • 최소, 최대(10818)
      • 최댓값(2562)
      • 숫자의 개수(2577)
      • 나머지(3052)
      • 평균(1546)
      • OX퀴즈(8958)
      • 평균은 넘겠지(4344)
    • 함수
      • 정수N개의 합(15596)
      • 셀프 넘버(4673)
      • 한수(1065)
    • 문자열
      • 아스키코드(11654)
      • 숫자의 합(11720)
      • 알파벳 찾기(10809)
      • 문자열 반복(2675)
      • 단어 공부(1157)
      • 단어의 개수(1152)
      • 상수(2908)
      • 다이얼(5622)
      • 크로아티아 알파벳(2941)
      • 그룹 단어 체커(1316)
    • 기본수학-1
      • 손익분기점(1712)
      • 벌집(2292)
      • 분수찾기(1193)
      • 달팽이는 올라가고 싶다(2869)
      • ACM 호텔(10250)
      • 부녀회장이 될테야(2775)
      • 설탕 배달(2839)
      • 큰 수 A+B(10757)
      • Fly me to the Alpha Centauri(1011)
    • 기본수학-2
      • 소수 찾기(1978)
      • 소수(2581)
      • 소인수분해(11653)
      • 소수 구하기(1929)
      • 베르트와 공존(4948)
    • 재귀
      • 하노이 탑 이동 순서(11729)
      • 피보나치 수 5(10870)
      • 별 찍기(2447)
    • 브루트 포스
      • 블랙잭(2798)
      • 분해합(2231)
      • 덩치(7568)
      • 체스판 다시 칠하기(1018)
      • 영화감독 슘(1436)
    • 집합과 맵
      • 숫자 카드(10815)
      • 문자열 집합(14425)
      • 숫자 카드2(10816)
      • 듣보잡(1764)
      • 대칭 차집합(1269)
      • 서로 다른 부분 문자열 갯수(11478)
    • 정렬
      • 수 정렬하기(2750)
      • 수 정렬하기 2(2751)
      • 수 정렬하기 3(10989)
      • 통계학(2108)
      • 소트인사이드(1427)
      • 좌표 정렬하기(11650)
      • 좌표 정렬하기2(11651)
      • 단어 정렬(1181)
      • 나이순 정렬(10814)
      • 커트라인(25305)
      • 좌표압축(18870)
    • 백트래킹
      • N과 M - 1(15649)
      • N과 M - 2(15650)
      • N과 M - 3(15651)
      • N과 M - 4(15652)
      • N-Queen(9663)
      • 스도쿠(2580)
      • 연산자 끼워넣기(14888)
      • 스타트와 링크(14889)
    • 이분 탐색
      • 수 찾기(1920)
    • 동적계획법
      • 피보나치 함수(1003)
      • 신나는 함수 실행(9184)
      • 01타일(1904)
      • 파도반 수열(9461)
      • RGB거리(1149)
      • 정수 삼각형(1932)
      • 계단 오르기(2579)
      • 1로 만들기(1463)
      • 쉬운 계단 수(10844)
      • 포도주 시식(2156)
      • 가장 긴 증가하는 부분 수열(11053)
      • 가장 긴 바이토닉 부분 수열(11504)
      • 전깃줄(2565)
      • LCS(9251)
      • 연속합(1912)
      • 평범한 배낭(12865)
      • 더하기(9095)
    • DFS와 BFS
      • 미로탐색(2178)
      • 바이러스(2606)
      • DFS와 BFS(1260)
      • 단지번호붙이기(2667)
      • 전쟁 - 전투(1303)
      • 숨바꼭질(1697)
      • 데스 나이트(16948)
      • 나이트의 이동(7562)
      • 녹색 옷 입은 애가 젤다지?(4485)
      • 음식물 피하기(1743)
      • A->B (16953)
      • 숨바꼭질 3(13549)
      • 숨바꼭질 2(12851)
    • 구현
      • 치즈(2636)
  • 프로그래머스 문제
    • SQL
      • Animal Table - Oracle
      • Animal Table - MySQL
      • Animal Table2 - Oracle
      • Animal Table 3,4 - Oracle
    • Lv1
      • 두 개 뽑아서 더하기
      • 제일 작은 수 제거하기
      • 문자열 내 p와 y의 개수
      • 예산
      • 자릿수 더하기
      • 두 정수 사이의 합
      • 같은 숫자는 싫어
      • 가운데 글자 가져오기
      • 수박수박수박수박수박수?
      • 나누어 떨어지는 숫자 배열
      • 2016년
      • 폰캣몬
      • 서울에서 김서방 찾기
      • 문자열을 정수로 바꾸기
      • 소수 만들기
      • 문자열 다루기 기본
      • 소수 찾기(에라토스테네스의 체)
      • 숫자 문자열과 영단어
      • 이상한 문자 만들기
      • 없는 숫자 더하기
      • 문자열 내림차순으로 배치하기
      • 문자열 내 마음대로 정렬하기
      • 약수의 개수와 덧셈
      • 콜라츠 추측
      • 자연수 뒤집어 배열로 만들기
      • 신규 아이디 추천
      • 비밀지도
      • 크레인 인형뽑기 게임
      • 실패율
      • 로또의 최고 순위와 최저 순위
      • 키패드 누르기
      • 정수 내림차순으로 배치하기
    • Lv2
      • 행렬의 곱셈
      • 영어 끝말잇기
      • 영어 끝말잇기
      • N개의 최소 공배수
      • 피보나치 수
      • 124 나라의 숫자
      • 짝지어 제거하기
      • 프린터
      • 다음 큰 숫자
      • 최댓값과 최솟값
      • 최소값 만들기
      • 숫자의 표현
      • JadenCase 문자열 만들기
      • 오픈채팅방
      • 영어 끝말잇기
      • 멀쩡한 사각형
      • 올바른 괄호
      • 위장
      • 기능개발
      • 더 맵게
      • 스킬트리
    • 완전탐색
      • 모의고사(Lv1)
      • 카펫(Lv2)
      • 소수 찾기(Lv2)
    • 정렬(Sorting)
      • K번째 수(Lv1)
      • 가장 큰 수(Lv2)
      • H-Index(Lv2)
    • 해시(Hash)
      • 완주하지 못한 선수(Lv1)
      • 전화번호 목록(Lv2)
    • 탐욕법(Greedy)
      • 체육복(Lv1)
      • 큰 수 만들기(Lv2)
      • 구명보트(Lv2)
    • 동적계획법(DP)
      • 정수 삼각형(Lv3)
    • 깊이/너비 우선 탐색(DFS/BFS)
      • 타겟 넘버(Lv2)
      • 네트워크(Lv3)
      • 단어 변환(Lv3)
  • 스프링부트 책
    • Day 1
    • Day 2
    • Day 3
    • Day 4
    • Day 5
    • Day 6
    • Day 7
    • Day 8
    • Day 9
    • Day 10
    • Day 11
    • Day 12
    • Day 13
    • Day 14
    • Day 15
    • Day 16
    • Day 17
  • JPA 책
    • 프로젝트 세팅 및 기본설정
    • 영속성 관리 개념
    • 엔티티 매핑
      • 실습 예제
    • 연관관계 매핑 기초
      • 실습 예제
    • 다양한 연관관계 매핑
      • 다대일, 일대다 관계
      • 일대일, 다대다 관계
      • 실습 예제
    • 고급 매핑
      • 상속 관계 매핑
      • @MappedSuperclass
      • 복합 키와 식별 관계 매핑
      • 조인 테이블
    • 프록시와 연관관계 관리
      • 프록시
      • 즉시 로딩과 지연 로딩
      • 영속성 전이, 고아 객체
    • 값 타입
      • 임베디드 타입
      • 값 타입과 불변 객체
      • 값 타입의 비교, 컬렉션
    • 객체지향 쿼리 언어
      • JPQL part1
      • JPQL part2
      • JPQL part3
      • QueryDSL
      • NativeSQL
      • 객체지향 쿼리 심화
    • 응용 애플리케이션
      • 엔티티 설정
    • 스프링 데이터 JPA
      • 공통 인터페이스
  • Kotlin In Action
    • 코틀린의 특징
    • 코틀린의 기초
    • 함수 정의와 호출
    • 클래스, 객체, 인터페이스
    • 람다 방식
    • 코틀린 타입 시스템
    • 연산자 오버로딩과 기타 관례
    • 고차함수
    • 제네릭스
    • 애노테이션과 리플렉션
    • 코루틴
  • Oracle
    • Oracle 기본
    • Oracle 심화
  • SQL_연습
    • Revising the Select Query
    • Basic Select
    • Advanced Select
    • Basic Select 2
  • SQL 첫걸음(책)
    • Day 1
    • Day 2
    • Day 3
    • Day 4
    • Day 5
    • Day 6
    • Day 7
    • Day 8
    • Day 9
    • Day 10
    • Day 11
    • Day 12
    • Day 13
    • Day 14
    • Day 15
    • Day 16
    • Day 17
    • Day 18
    • Day 19
    • Day 20
    • Day 21
    • Day 22
    • Day 23
    • Day 24
    • Day 25
    • Day 26
    • Day 27
    • Day 28
    • Day 29
    • Day 30
  • 더 자바 코드를 조작하는 다양한 방법
    • JVM 이해하기
    • 바이트코드 조작
    • 리플렉션
    • 다이나믹 프록시
    • 애노테이션 프로세서
  • 더 자바, 애플리케이션을 테스트하는 다양한 방법
    • JUnit5
    • Mockito
    • 도커와 테스트
    • 성능, 운영이슈, 아키텍처 테스트
  • 이펙티브 자바
    • item1 - 생성자 대신 정적 팩토리 메소드를 고려하라
    • item2 - 생성자에 매개변수가 많다면 빌더를 고려하라
    • item3 - 생성자나 열거타입으로 싱글턴임을 보증하라
    • item4 - 인스턴스화를 막기 위해선 private 생성자를 사용하라
    • item5 - 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
    • item6 - 불필요한 객체 생성을 피하라
    • item7 - 다 쓴 객체 참조를 해제하라
    • item8 - finalizer와 cleaner 사용을 피하라
    • item9 - try-finally 보다 try-with-resources을 사용하라
    • item10 - equals는 일반 규약을 지켜 재정의하라
    • item11 - equals을 재정의하려면 hashCode도 재정의하라
    • item12 - toString을 항상 재정의하라
    • item13 - clone 재정의는 주의해서 진행하라
    • item14 - Comparable을 구현할지 고민하라
  • Elastic Search
    • 강의 Summary
    • Elastic Summary 개념 정리
    • Elastic Summary 적용 정리
  • 토비의 스프링 강의
    • 스프링부트 살펴보기
    • 독립 실행형 서블릿 애플리케이션
  • k8s
    • minikube 설치
    • jenkins 추가
  • Article
    • Choosing the Right MessageBroker
Powered by GitBook
On this page

Was this helpful?

  1. JPA 책
  2. 고급 매핑

복합 키와 식별 관계 매핑

복합 키와 식별 관계 매핑

식별 관계 VS 비 식별 관계

단순하게 생각해보면 외래 키가 기본 키에 포함되고 있는지에 대한 여부에 따라서 구분된다.

식별 관계 - 식별 관계는 부모 테이블의 기본 키를 내려받아서 자식 테이블의 기본 키 + 외래 키로 사용하는 관계이다

비식별 관계 - 부모 테이블의 기본 키를 받아서 자식 테이블에서 단지 외래 키로만 사용하는 관계

  • 필수적 비식별 관계 - 외래 키에 null을 허용하지 않는 경우이기 때문에 연관관계를 필수적으로 맺어야함

  • 선택적 비식별 관계 - 외래 키에 null을 허용한 경우이기 때문에 연관관계를 맺든 안맺는 선택

복합 키에서 비식별 관계를 매핑하는 방법

단순하게 기본 키가 하나면 @Id를 사용해서 적용해주면 되지만, 만약에 2개 이상으로 기본 키가 이루어진 복합 기본 키인 경우에는 @Id를 2개 써야하나? 근데 당연히 에러가 나오겠지여

일단 JPA는 영속성 컨텍스트에 엔티티를 보관할 때 엔티티의 식별자를 키로 사용한다. 그리고 그 식별자를 구분하기 위해서 사용하는 것이 equals, hashCode 이렇게 2가지를 사용해서 동등성을 비교한다. 자 그럼 만약에 식별자 필드가 2개 이상이면 어떻게 해야하나 → 당연히 equals, hashCode를 새로 구현을 해줘야한다.

그럼 JPA에서 지원해주는 복합 키 구현 방식으로는 → @IdClass, @EmbeddedId 이렇게 2가지의 방법을 제공해주고 있다.

@IdClass

이건 그래도 관계형 데이터베이스에 가까운 방법

package com.example.jpa_project.ch07Example;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import java.io.Serializable;
import java.util.Objects;

public class MultiId_IdClass {

    @Entity
    @IdClass(ParentId.class)
    public class Parent{
        @Id
        @Column(name = "PARNET_ID")
        private String id;

        @Id
        @Column(name = "PARENT_ID2")
        private String id2;
    }

    public class ParentId implements Serializable{
        private String id1;
        private String id2;

        public ParentId() {
        }

        public ParentId(String id1, String id2) {
            this.id1 = id1;
            this.id2 = id2;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ParentId parentId = (ParentId) o;
            return Objects.equals(id1, parentId.id1) && Objects.equals(id2, parentId.id2);
        }

        @Override
        public int hashCode() {
            return Objects.hash(id1, id2);
        }
    }
}

@Id를 모든 복합 기본 키에 붙혀주고 대신 엔티티 클래스에 @IdClass를 붙혀주되,

식별자 클래스(ParentId)를 만들어주어야 한다. 이 식별자 클래스에는 충족해야 하는 조건들이 존재함

  • 식별자 클래스의 속성명과 엔티티에서 사용하는 식별자의 속성명이 같아야 한다.

  • Serializable 인터페이스를 구현해야 한다.

  • equals, hashCode를 구현해야 한다.

  • 기본 생성자가 있어야 하고

  • 클래스의 접근 타입은 public 이어야 한다.

이렇게 만들고 자식 클래스

package com.example.jpa_project.ch07Example;

import javax.persistence.*;

public class MultiId_IdClass_Child {
    @Entity
    public class Child {
        @Id
        private String id;

        @ManyToOne
        @JoinColumns({
                @JoinColumn(name = "PARENT_ID1", referencedColumnName = "PARENT_ID1"),
                @JoinColumn(name = "PARENT_ID2", referencedColumnName = "PARENT_ID2")
        })
        private MultiId_IdClass_Parent.Parent parent;
    }
}

부모 테이블의 기본 키가 복합 키이기 때문에 자식 테이블의 외래 키도 복합키로 가져와야 하고 이렇게 가져오는 방식은 @JoinColumns으로 매핑해주고 내부에는 @JoinColumn으로 구현해준다. 만약 @JoinColumn의 name속성과 referencedColumnName이 같다면 뒤의 referencedColumnName은 생략할 수 있다.

@EmbeddedId

이건 객체지향에 가까운 방법

package com.example.jpa_project.ch07Example;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import java.io.Serializable;
import java.util.Objects;

public class MultiId_EmbeddedClass_Parent {
    
    @Entity
    public class Parent{
        @EmbeddedId
        private ParentId id;
        
        private String name;
    }
    
    @Embeddable
    public class ParentId implements Serializable {
        @Column(name = "PARENT_ID1")
        private String id1;
        @Column(name = "PARENT_ID2")
        private String id2;

        public ParentId() {
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ParentId parentId = (ParentId) o;
            return Objects.equals(id1, parentId.id1) && Objects.equals(id2, parentId.id2);
        }

        @Override
        public int hashCode() {
            return Objects.hash(id1, id2);
        }
    }
}

진짜 단순하게 Parent에서 그냥 식별자 클래스로 적용해주고 @EmbeddedId을 붙혀준다.

그리고 @Embeddable으로 해당 아이디를 받아서 구현해줘야 한다. 구현할 때 조건

  • 구현해야 하는 클래스에 @Embeddable을 붙히자

  • Serializable 인터페이스를 구현

  • equals, hashCode를 구현

  • 기본 생성자 필요

  • 식별자 클래스는 public이여야 함

equals(), hashCode()

영속성 컨텍스트는 엔티티의 식별자로 키를 사용해서 엔티티를 관리한다. 그리고 해당 식별자를 비교할 때 equals(), hashCode()를 사용해서 비교하게 된다. 만약 이것을 정의하지 않게 되면 구별이 불분명해져 엔티티에 대한 접근에 문제가 생기게 된다.

그리고 식별자 클래스의 equals()와 hashCode()는 모든 필드를 사용해서 구현한다.

여기서 만약 하나의 자식이 더 추가된다면...?

@IdClass

package com.example.jpa_project.ch07Example;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Objects;

public class MultiId_IdClass_Family {
    @Entity
    public class Parent{
        @Id
        @Column(name = "PARENT_ID")
        private String id;

        private String name;
    }

    @Entity
    @IdClass(ChildId.class)
    public class Child{
        @Id
        @ManyToOne
        @JoinColumn(name = "PARENT_ID")
        public Parent parent;
        
        @Id
        @Column(name = "CHILD_ID")
        public String childId;
        
        private String name;
    }

    public class ChildId implements Serializable{
        private String parent;
        private String childId;

        public ChildId() {
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ChildId childId1 = (ChildId) o;
            return Objects.equals(parent, childId1.parent) && Objects.equals(childId, childId1.childId);
        }

        @Override
        public int hashCode() {
            return Objects.hash(parent, childId);
        }
    }
    
    @Entity
    @IdClass(GrandChildId.class)
    public class GrandChild{
        @Id
        @ManyToOne
        @JoinColumns({
                @JoinColumn(name = "PARENT_ID"),
                @JoinColumn(name = "CHILD_ID")
        })
        private Child child;
        
        @Id
        @Column(name = "GRANDCHILD_ID")
        private String id;
    }
    
    public class GrandChildId implements Serializable{
        private ChildId child;
        private String id;

        public GrandChildId() {
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            GrandChildId that = (GrandChildId) o;
            return Objects.equals(child, that.child) && Objects.equals(id, that.id);
        }

        @Override
        public int hashCode() {
            return Objects.hash(child, id);
        }
    }
}

자식의 자식같은 경우에도 구현은 같지만 항상 자신보다 바로 하나 위의 부모의 키를 가져와서 구현해야 한다는 점? 이정도? 구현자체는 비슷하다고 본다.

@EmbeddedId의 구성으로 확인

구조는 같지만 @MapsId를 사용하는 점이 다른점이라고 보인다.

package com.example.jpa_project.ch07Example;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Objects;

public class MultiId_EmbeddedClass_Family {
    
    @Entity
    public class Parent{
        @Id
        @Column(name = "PARENT_ID")
        private String id;
        private String name;
    }
    
    @Entity
    public class Child{
        @EmbeddedId
        private ChildId id;
        
        @MapsId("parentId")
        @ManyToOne
        @JoinColumn(name = "PARENT_ID")
        public Parent parent;
        
        private String name;
    }
    
    @Embeddable
    public class ChildId implements Serializable{
        private String parentId;
        
        @Column(name = "CHILD_ID")
        private String id;

        public ChildId() {
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ChildId childId = (ChildId) o;
            return Objects.equals(parentId, childId.parentId) && Objects.equals(id, childId.id);
        }

        @Override
        public int hashCode() {
            return Objects.hash(parentId, id);
        }
    }
    
    @Entity
    public class GrandChild{
        @EmbeddedId
        private GrandChildId id;
        
        @MapsId("childId")
        @ManyToOne
        @JoinColumns({
                @JoinColumn(name = "PARENT_ID"),
                @JoinColumn(name = "CHILD_ID")
        })
        private Child child;
        
        private String name;
    }
    
    @Embeddable
    public class GrandChildId implements Serializable{
        private ChildId childId;
        
        @Column(name = "GRANDCHILD_ID")
        private String id;

        public GrandChildId() {
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            GrandChildId that = (GrandChildId) o;
            return Objects.equals(childId, that.childId) && Objects.equals(id, that.id);
        }

        @Override
        public int hashCode() {
            return Objects.hash(childId, id);
        }
    }
}

기존과의 차이는 @MapsId를 @Id대신에 넣어줬다는 것이다. @MapsId는 외래키와 매핑한 연관관계를 기본 키에다가도 매핑하겠다는 의미이다.

비식별 관계로 구현하는건 더더더더더욱 단순한다. 단순하게 Serializable을 가지고 있는 복합 키 클래스를 만들지 않아도 매핑이 가능하다는 점..!

그래서 식별, 비식별 관계의 장단점

결과적으로는 비식별 관계를 많이 사용한다네요 왜와이

  • 식별관계는 자식 테이블로 갈 수록 기본 키 컬럼이 점점 늘어나면 사고가 되어간다.

  • 식별 관계는 2개 이상의 컬럼을 합해서 복합 기본 키를 만들어야 하는 경우가 있다.

  • 식별 관계를 맺어두면 나중에 변경사항이 있을 때 힘들다는점?

  • 식별 관계는 자식 테이블에서 부모 테이블의 기본 키를 가져와서 사용하기 때문에 테이블 구조가 유연하지 않다.

이렇게나 단점이 많으면 그럴만도하다

그럼 왜 비식별 관계를 더 많이 사용하냐

  • 그냥 식별 함수를 만들지 않아도 괜찮기 때문에 무조건 단순하니까

  • 비식별 관계의 기본 키는 주로 대리 키를 사용하게 되는데, 여기서는 JPA에서는 @GeneratedValue를 사용해서 대리 키를 많이 사용하기 때문에 편리하게 사용할 수 있다. - 대부분 Long 타입의 대리 키를 사용한다.

Previous@MappedSuperclassNext조인 테이블

Last updated 3 years ago

Was this helpful?