Entity 연관관계

DB에서는 어떤 테이블을 기준으로 하든 원하는 정보를 JOIN을 사용하여 조회할 수 있다.
이처럼 DB 테이블간의 관계에서는 방향의 개념이 없지만, Entity에서는 단방향 또는 양방향 연관관계를 설정하여 조회를 할 수 있거나 하지 못하게 될 수 있다.

DB테이블간 연관관계

JPA Entity에서의 연관관계

JPA Entity에서는 조회를 하기 위해서는 단방향 또는 양방향으로 관계를 맺어야 한다. 이때 고객 Entity에서는 음식에 대한 정보가 Collumn으로 나올 필요가 없기 때문에 @Collumn으로 열 추가를 하지 않는다, 음식 Entity의 경우 고객의 id 정보가 나와야 하기 때문에 @JoinCollumn으로 열을 추가한다. (이래야만 고객 Entity에서 음식 Entity를 조회하는게 가능하기 때문)

<정리>
DB 테이블에서는 테이블 사이의 연관관계를 FK(외래 키)로 맺을 수 있고 방향 상관없이 조회가 가능
Entity에서는 상대 Entity를 참조하여 Entity 사이의 연관관계를 맺을 수 있다.
하지만 상대 Entity를 참조하지 않고 있다면 상대 Entity를 조회할 수 있는 방법이 없다.
따라서 Entity에서는 DB 테이블에는 없는 방향의 개념이 존재합니다.
이때 양방향 관계의 경우 외래키의 주인이 아닌 곳에서 (mappedBy = "") 으로 지정을 한다.
Ex. 음식 Entity가 주인일 경우 고객 Entity에서 mappedBy로 지정을 해야한다.

1대1 관계 (@OneToOne 어노테이션)

1:1 관계를 맺어주는 역할을 함

단방향 관계

Entity에서 외래 키의 주인은 일반적으로 N(다)의 관계인 Entity 이지만, 1 대 1 관계에서는 외래 키의 주인을 직접 지정해야합니다.

외래 키 주인만이 외래 키 를 등록, 수정, 삭제할 수 있으며, 주인이 아닌 쪽은 오직 외래 키를 읽기만 가능합니다.

@JoinColumn()은 외래 키의 주인이 활용하는 애너테이션 -> 컬럼명, null 여부, unique 여부 등을 지정할 수 있다.

양방향 관계

양방향 설정
양방향 관계에서 외래 키의 주인을 지정해 줄 때 mappedBy 옵션을 사용합니다.
mappedBy의 속성값은 외래 키의 주인인 상대 Entity의 필드명을 의미한다.

관계 설정 방법에 대한 정리.

단방향이라면 외래 키의 주인만 상대 Entity 타입의 필드를 가지면서 @JoinColumn()을 활용하여 외래 키의 속성을 설정.

양방향이라면 외래 키의 주인은 상대 Entity 타입의 필드를 가지면서 @JoinColumn()을 활용하여 외래 키의 속성을 설정.

그리고 상대 Entity는 외래 키의 주인 Entity 타입의 필드를 가지면서 mappedBy 옵션을 사용하여 속성 값으로 외래 키의 주인 Entity에 선언된 @JoinColumn()으로 설정되고 있는 필드명을 넣어주면 된다.

※mappedBy의 속성 값은 외래키의 주인인 상대 Entity에 있는 필드(JoinColumn으로 설정)명을 의미한다.

1:1 관계에서는
@JoinColumn을 생략해도 default값으로 설정이 되고, DB에 칼럼명도 "필드명_id" 로 설정이 된다.

하지만 이후 1대 다 관계에서 외래키의 주인 Entity가 @JoinColumn을 생략하면 JPA가 외래키를 저장할 칼럼을 파악할 수 없어서 의도치 않은 중간 테이블을 생성하게 된다.

따라서 @JoinColimn을 생략할 수 있지만, 왠만해서는 직접 선언하여 활용하는 것이 좋다.

마찬가지로 양방향 관계에서 mappedBy를 생략할 경우 JPA가 외래키의 주인 Entity를 파악할 수 없어서 의도치 않는 중간테이블이 생성될 수 있다.

Entity에서 주인이 아닌 쪽에서 주인인 Entity를 저장하는 방법

외래 키 저장 실패 -> 성공

엔티티 주인인 쪽 Food에서 처음엔 User에 대한 객체가 생성되지 않았으므로 user_id를 가질 수 없었다. 이후 DB에 저장하기 전 User 객체가 생성되었고 이후 addfood 매서드를 통해서 food 객체에 생성된 User를 set해서 주입을 진행

이제 Food 쪽에서 User 엔티티에 대한 객체를 담고 있으므로 userRepository와 foodRepository에 각 객체들을 save 매서드를 통해 저장한다.

DB를 확인하면 정상적으로 Food 테이블의 user_id 컬럼에 User 엔티티의 id 값이 반영된 것을 확인할 수 있다.

주인 Entity에서 아닌쪽의 Entity의 저장하는 방법

Food가 연관관계의 주인이므로 먼저 User 엔티티의 객체를 생성하고 값을 set매서드를 통해 정한다. Food 엔티티의 객체를 생성하고 User엔티티를 set매서드를 통해서 엔티티의 값을 받아온다.

UserRepository와 FoodRepostory에 각각 엔티티의 객체들을 save매서드로 저장한다.

N대 1관계

단방향 관계

외래키의 주인쪽에 @ManyToOne의 어노테이션을 설정하여 단방향 N:1 관계를 설정하면 된다.
일반적으로는 N:1 관계에서는 N쪽이 외래키의 주인이다.


양방향 관계

마찬가지로 음식 Entity가 N의 관계로 외래 키의 주인이다.


여기서 고객 엔티티의 (Only Entity)표현은 고객 엔티티에 Java의 컬렉션이 있어도 실제 DB에는 표현이 되지 않음을 의미한다.

음식 Entity는 외래키의 주인이므로 @ManyToOne 어노테이션을 사용한다. 반대로 외래키의 주인이 아닌 고객 Entity는 N의 관계를 가지는 음식 Entity를 표현하기 위해 List 컬렉션을 사용하고, mappedBy (외래키 주인 설정) 을 해야한다.

외래키 저장 실패 예시


DB의 Food 엔티티에 user_id 값이 null인 것으로 확인할 수 있다.

외래키 저장 성공 예시

  1. 외래키의 주인이 아닌 Entity에서 해당 메서드에 외래키(연관 관계) 설정 -> 외래키의 주인이 아닌 곳에서 설정하기 위해서는 추가 매서드를 만들어서 설정을 해줘야 한다.

  1. 외래키의 주인인 Entity에서 외래 키 (관계 설정) 설정 -> 외래키의 주인 쪽에서 주인이 아닌 쪽의 Entity를 주입한다.

외래키 조회

profile
안녕하세요~

0개의 댓글

Powered by GraphCDN, the GraphQL CDN