🥕
TIL
  • [TIL] Studying tech / computer science knowledge
  • KeyMap
  • 알고리즘
    • 복잡도 계산 ( Computational Complexity )
    • DisjointSet-unionFind
    • Bellman-ford Algorithm
    • Dijkstra's Algorithm
    • DP ( Dynamic Programming , 동적 계획법 )
    • 플로이드-워셜 알고리즘 (Floyd-Warshall algorithm)
    • Kruskal's Algorithm
    • 최장 증가 수열 (Longes Increasing Subsequence)
    • Prim's Algorithm
    • 정렬
    • 시간복잡도 와 공간복잡도 ( Time Complexity & Space Complexity )
    • Topological Sort (위상 정렬)
  • 책 읽고난 후 요약
    • 프로그래밍 대회에서 배우는 알고리즘 문제해결 전략
    • cleancode
    • 도메인 주도 설계로 시작하는 마이크로서비스 개발
    • 오브젝트
  • CDC
    • debzium
    • kafka
  • 개발 상식
    • asciidoctor
    • 컴파일러
    • ELK 스택
    • 엔디안
    • git
    • Gitmoji
    • 테스트 종류
    • 라이브러리와 프레임워크
    • 정규 표현식
    • REST API
    • 동기와 비동기 / Blocking과 NonBlocking
    • Transaction Script와 Domain Model
    • 디자인 패턴
      • 행동 패턴
      • 객체 생성 패턴
        • 추상 팩토리 패턴
        • 빌더 패턴
        • 팩토리 메서드 패턴
        • [생성 패턴] 프로토 타입 (Prototype Parttern)
        • 싱글톤
      • 구조 패턴
        • 어댑터 패턴
        • 브릿지 패턴
        • 컴포짓(Composite) 패턴
        • 데코레이터
        • 프록시
    • refactoring
      • 중복 코드
      • 전역 데이터
      • 긴 함수
      • 긴 매개변수 목록
      • 가변 데이터
      • 이해하기 힘든 이름
  • 자료구조
    • AVL Tree
    • Splay Tree
    • aaTree
    • array-list
    • 자료구조 시간/공간 복잡도
    • 그래프
    • 힙
    • Red Black Tree
    • stack-queue
    • 트리 ( Tree )
  • DevOps
    • MSA
    • Kubernetes
      • AccessingAPI
      • controller
      • dashboard
      • kubernetes
      • object
      • pod
      • service
      • volume
  • Java
    • 어노테이션
    • 제어문
    • 데이터 타입
    • Enum
    • jvm
    • 연산자
    • thread
    • Java8
      • CompletableFuture
      • Date/Time
      • 어노테이션과 메타스페이스
      • 인터페이스
      • 람다식
      • Optional
      • 스트림
  • JavaScript
    • moduleProject
    • webpack-babel
    • 코어 자바스크립트
      • array
      • 함수 바인딩
      • 데코레이터와 포워딩
      • Class
      • 비교 연산자
      • Date 내장 객체
      • destructuring-assignment
      • function
      • 함수의 prototype 프로퍼티
      • 가비지 컬렉션 ( Garbage Collection )
      • JSON (JavaScript Object Notation)
      • map-set
      • 내장 프로토타입
      • new연산자와 생성자 함수
      • 객체
      • Object.keys, values, entries
      • 옵셔널 체이닝 '?.'
      • 프로퍼티 플래그
      • 프로퍼티 종류
      • 프로토 타입
      • 호출 스케줄링 ( scheduling a call )
      • scope
      • this
      • type-conversions
      • type
      • 함수의 자료형
      • var_let_const
  • Linux
    • 기본 명령어
    • 파일 종류
    • 리눅스
  • 네트워크
    • 응용 계층 ( Application Layer )
    • 오류 검출과 오류 정정
    • Http
    • Http Header
    • 컴퓨터 네트워크란
    • 네트워크 계층
    • 네트워크 제어 영역
    • 전송 계층 ( Transport Layer )
  • PHP
    • Facade
    • composer
    • scopeResolutionOperator
    • Laravel
      • SocialProvider
      • architecture
      • blade
      • controller
      • db
      • dbArchitecture
      • debug
      • eloquent
      • email
      • event
      • exceptionHandling
      • middleware
      • model
      • modelFactory
      • pagingLoading
      • queryBuilder
      • route
      • scout
      • seeding
      • tntsearch
      • validate
      • view
  • React
    • Next.js
    • React 란?
  • Spring
    • Controller
    • 요청이 들어왔을때 스프링이 처리하는 방법 ( 내부구조 )
    • ConfigurationProperties
    • Entity / DTO / VO
    • Maven
    • Repository와 DAO
    • 스프링 빈
    • Spring Framework
    • MVC 패턴
    • 도메인 입력값 검증
    • Spring Cloud
      • Spring Cloud
      • Eureka
    • Spring Data
      • JPA
      • JPA 어노테이션
      • 엔티티 비교
      • 복합 키와 식별 관계 매핑
      • JPA 예외처리
      • 객체지향 쿼리
      • EntityManagerFactory와 EntityManager
      • JPA 최적화
      • 프록시와 연관관계 맵핑
      • 연관관계
      • 상속관계 맵핑
      • 트랜잭션 범위와 영속성 컨텍스트
      • 데이터 타입
      • MySQL 연결
      • Pageable
    • Spring Project들과 library
      • Custom Serialize
      • Elasticsearch Index API
      • Spring HATEOAS
      • lombok (롬복)
      • Model Mapper
      • Object Mapper
      • Representation Model
      • Spring REST Docs
      • Spring Boot
    • Spring Security
      • Spring Security
      • Authentication
      • Authentication Filter
      • Authorization Filter
      • Filter Chain
      • SecurityContext
      • Spring OAuth2.0
    • Spring Test
      • AssertJ
      • Junit5
      • JunitParams
      • Mock Object
  • DataBase
    • ALIAS
    • CONCAT
    • CTE
    • Group By
    • HAVING
    • IFNULL
    • 인덱스
    • JOIN
    • ORDER BY
    • ROLLUP
    • SELECT
    • SELECT DISTINCT
    • SQL
    • WHERE
  • Web 상식
    • OAuth
    • WAS
    • HTTP통신 기반 인증
    • 브라우저
    • CSR 과 SSR
    • HTTPS
    • Web
Powered by GitBook
On this page
  • 복합 키를 지원하기 위한 방법
  • 1. IdClass
  • 2. EmbeddedClass
  • 주의할 점
  • 식별 관계
  • 1. IdClass
  • 2. EmbeddedId
  • 일대일 식별 관계
  • 비 식별 관계
  • 필수적 비식별 관계
  • 선택적 비식별 관계
  • 식별관계와 비식별관계에 관하여
  • 조인 테이블
  • 1. 조인 컬럼 사용 (@JoinColumn)
  • 2. 조인 테이블 사용 (@JoinTable)
  • 하나의 엔티티로 여러개의 테이블 매핑
  • Reference
  1. Spring
  2. Spring Data

복합 키와 식별 관계 매핑

복합 키를 매핑하는데 외래키가 기본 키에 포함되는지 여부에 따라 두가지 방법(식별관계, 비식별관계)이 존재한다.

복합 키를 지원하기 위한 방법

복합키를 사용하기 위해 별도의 식별자 클래스를 생성해주어야 하는데 이때 equals와 hashcode를 필수적으로 생성해주어야 한다. 자바의 모든 클래스는 Object클래스를 상속받는데 이 클래스가 제공하는 기본 equals는 인스턴스 참조 값 비교인 ==비교를 하기 때문에 아래와 같이 같은 키여도 영속성 컨텍스트는 다르게 인식하여 동등성이 지켜지지 않기 때문이다.

ParentId id1 = new ParentId();
id1.setId("1");
id1.setId("2");

ParentId id2 = new ParentId();
id2.setId("1");
id2.setId("2");

id1.equals(id2); //false 일 수 있다.

1. IdClass

관계형 데이터베이스에 가까운 방법

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

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

@NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode
public class ParentId implements Serializable{
    private String id1;
    private String id2;
}

식별자 클래스의 필드명과 엔티티에서 사용하는 식별자의 필드명이 같아야 하고 아래와 같이 저장할 수 있다.

Parent parent = new Parent();
parent.setId1("1");
parent.setId2("2");
parent.setName("홍길동");
em.persist(parent);

2. EmbeddedClass

객체지향에 가까운 방법

@Entity
public class Parent{
    @EmbeddedId
    private ParentId id;

}

@Embeddable @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode
public class ParentId implements Serializable{

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

식별자 클래스에 기본키를 직접 매핑하는 방법이며, 아래와 같이 저장을 수행할 수 있다.

Parent parent = new Parent();
ParentId parentId = new ParentId("1","2");
parent.setId(parentId);
parent.setName("홍길동");
em.persist(parent);

주의할 점

예를들어 EmbeddedId를 가지고있는 엔티티를 B, 이 엔티티를 연관관계를 갖는 한 엔티티를 A라고 하자.

A를 통해 B를 저장하려고 할때 A를 보통 @JoinColumns로 지정해 컬럼을 맵핑해 저장하는데 이때 맵핑된 정보가 아닌 JoinColumns의 JoinColumn가 선언된 순서로 저장되는 문제가 발생하게 된다.

이를 해결하기 위해서는 @JoinColumn내부에 referenceColumnName속성으로 지정을 해주어야 제대로된 컬럼에 맵핑이 된다.

식별 관계

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

1. IdClass

참조하는 객체를 @Id를 이용하여 맵핑하면 된다.

2. EmbeddedId

참조하는 객체를 @MapsId를 이용하여 맵핑하면 되고 MapsId는 외래키와 맵핑한 연관간계를 기본 키에도 매핑하겠다는 뜻이다. 해당 어노테이셔의 속성값으로 @EmbeddeId를 사용한 식별자 클래스의 기본 키 필드를 지정하면 된다.

일대일 식별 관계

부모 테이블의 기본키를 이용하여 자식 테이블의 키 그대로 사용하기 때문에, 복합키를 구성하지 않아도 되고 @MapsId를 참조하는 객체에 붙여주고 속성값은 아무것도 명시 하지 않음으로써, 자기 자신의 Id와 외래키를 맵핑하겠다고 선언해주면 된다.

@Entity
public class Parent{
    @Id @GeneratedValue @JoinColumn(name="PARENT_ID")
    private Long id;

    @OneToOne(mappedBy = "board")
    private parentDetail parentDetail;
}

@Entity
public class ParentDetail{
    @Id
    private Long parentDetailId;

    @MapsId
    @OneToOne
    @JoinColumn(name="PARENT_ID")
    private Parent parent;
}

비 식별 관계

부모 테이블의 기본 키를 받아 자식 테이블의 외래키로만 사용하는 관계

필수적 비식별 관계

외래키에 NULL을 허용하지 않는 관계

선택적 비식별 관계

외래키에 NULL을 허용하는 관계

이는 복합키를 사용하지 않아도 되기 때문에 일반 연관관계 연결하듯이 하면 된다.

식별관계와 비식별관계에 관하여

비즈니스가 확장되어 기본 키 컬럼이 늘어날 수도 있기 때문에 확장성과 유연성이 좋은 비식별관계가 더 많이 선호 되며, JPA에는 GeneratedValue라는 대리키 생성 전략을 쉽게 제공한다.

하지만, 식별관계는 인덱스 없이도 기본키 인덱스만을 가지고 빠르게 조회가 가능한 장점이 있으니 필요한곳에 적절하게 사용해야 한다.

또한, 대리키를 사용할때는 Integer가 아닌 Long을 사용하는 것이 안전하고 비식별 관계를 사용할때는 필수적 비식별 관계를 사용하는 것이 좋다. (Integer는 20억개 정도, Long은 920경)

조인 테이블

1. 조인 컬럼 사용 (@JoinColumn)

외래키를 사용하여 조인할 수 있지만, 외래키에 null값을 허용해야하고 inner join을 사용시 관계가 없는 컬럼들은 조회가 되지 않는다. 처음 컬럼 생성시 대부분의 FK는 null로 저장된다.

2. 조인 테이블 사용 (@JoinTable)

별도의 테이블을 사용해서 연관관계를 관리하는 방법으로 사용이 단순하고 쉬우나 테이블을 하나 더 관리해야 하기 때문에 부담이 늘어나며, 조인 시에 2개가 아닌 연관관계를 관리하는 테이블까지 추가해서 3개의 테이블을 조인 해야 한다.

기본은 조인 컬럼으로 사용하고 필요시에 조인 테이블을 이용하자. (주로 조인 테이블은 다대다 / 다대일 관계에 사용된다.)

하나의 엔티티로 여러개의 테이블 매핑

@Entity
@Table(naem="PARENT")
@SecondaryTalbe(naem = "PARENT_DETAIL",
    pkJoinColumns = @PrimaryKeyJoinColumns(name = "PARENT_DETAIL_ID"))
public class Parent{
    @Id @GenreatedValue
    @Column(name = "PARENT_ID")
    private Long id;

    private String name;

    @Column(table = "PARENT_DETAIL")
    private String address;
}

하나의 클래스(Entity)에서 @Table과 @SecondaryTable을 통해 두개의 테이블과 매핑시킬 수 있고, @Column의 table 필드를 지정하면 해당 테이블에 매핑되며 지정하지 않는다면 기본인 @Table로 명시된 테이블에 매핑이 된다.


Reference

자바 ORM 표준 JPA 프로그래밍 책 (김영한 저)

Previous엔티티 비교NextJPA 예외처리

Last updated 3 years ago

Stack overflow의 사례