본문 바로가기

TIL

240527 TIL 1대1 관계, N대1관계, 1대N관계, N대M관계

연관관계 다중성

다중성 종류

1대1 관계 : One To One

N대 1관계 : Many To One

1대 N 관계 : One To Many

 N대 M 관계 : Many To Many

 

1. 1대 1 관계

@OneToOne 애노테이션은 1대1 관계를 맺어주는 역할을 한다

 

고객 Entity와 음식 Entity가 1대1관계라 가정하여 관계를 맺어보자

 

단방향관계

- 외래 키의 주인 정하기

  • Entity에서 외래 키의 주인은 일반적으로 N(다)의 관계인 Entity 이지만 1 대 1 관계에서는 외래 키의 주인을 직접 지정해야함
  • 외래 키 주인만이 외래 키 를 등록, 수정, 삭제할 수 있으며, 주인이 아닌 쪽은 오직 외래 키를 읽기만 가능
  • @JoinColumn()은 외래 키의 주인이 활용하는 애너테이션입니다.
    • 컬럼명, null 여부, unique 여부 등을 지정할 수 있습니다.

음식 Entity가 외래키의 주인인 경우

 

음식

@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @OneToOne
    @JoinColumn(name = "user_id")
    private User user;
}

 

고객

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}

 

고객 Entity가 외래키의 주인인 경우

 

고객에

@OneToOne
@JoinColumn(name = "food_id")
private Food food;

이렇게 적어주면 된다

 

 

양방향 관계

- 양방향 설정

  • 양방향 관계에서 외래 키의 주인을 지정해 줄 때 mappedBy 옵션을 사용
    • mappedBy의 속성값은 외래 키의 주인인 상대 Entity의 필드명을 의미
  • 관계 설정 방법에 대해 정리
    • 단방향이라면 외래 키의 주인만 상대 Entity 타입의 필드를 가지면서 @JoinColumn()을 활용하여 외래 키의 속성을 설정해주면됩니다.
    • 양방향이라면 외래 키의 주인은 상대 Entity 타입의 필드를 가지면서 @JoinColumn()을 활용하여 외래 키의 속성을 설정을 해줍니다.
      • 그리고 상대 Entity는 외래 키의 주인 Entity 타입의 필드를 가지면서 mappedBy 옵션을 사용하여 속성 값으로 외래 키의 주인 Entity에 선언된 @JoinColumn()으로 설정되고 있는 필드명을 넣어주면 됩니다.

 

음식 Entity가 외래 키의 주인인 경우!

 

음식

@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @OneToOne
    @JoinColumn(name = "user_id")
    private User user;
}

 

고객

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToOne(mappedBy = "user")
    private Food food;
}

 

고객 Entity가 외래키의 주인인 경우

음식에서

@OneToOne(mappedBy = "food")

private User user;

 

고객에서

@OneToOne

@JoinColumn(name = "food_id")

private Food food;

이렇게 해주면 된다

 

2. N대 1관계

@ManyToOne 애너테이션은 N대 1관계를 맺어주는 역할

 

음식 Entity와 고객 Entity가 N대 1관계라 가정

 

단방향 관계

.

음식 Entity가 N의 관계로 외래 키의 주인

음식

@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

 

고객

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}

 

양방향 관계일 경우

 

음식

@ManyToOne
@JoinColumn(name = "user_id")
private User user;

 

고객

@OneToMany(mappedBy = "user")
private List<Food> foodList = new ArrayList<>();

 

 

3. 1대 N 관계

@OneToMany 애너테이션은 1대 N관계를 맺어주는 역할

 

단방향 관계

- 외래 키를 관리하는 주인은 음식 Entity이지만 실제 외래 키는 고객 Entity가 가지고 있습니다.

- 1 : N에서 N 관계의 테이블이 외래 키를 가질 수 있기 때문에 외래 키는 N 관계인 users 테이블에 외래 키 컬럼을 만들어 추가하지만 외래 키의 주인인 음식 Entity를 통해 관리

 

음식

@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @OneToMany
    @JoinColumn(name = "food_id") // users 테이블에 food_id 컬럼
    private List<User> userList = new ArrayList<>();
}

 

고객

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}

외래 키를 음식 Entity가 직접 가질 수 있다면 INSERT 발생 시 한번에 처리할 수 있지만 실제 DB에서 외래 키를 고객 테이블이 가지고 있기 때문에 추가적인 UPDATE가 발생된다는 단점이 존재

 

1 대 N 관계에서는 일반적으로 양방향 관계가 존재하지 않는다

 

4. N대 M 관계

@ManyToMany 애너테이션은 N대 M 관계를 맺어주는 역할

 

단방향 관계

N : M 관계를 풀어내기 위해 중간 테이블(orders)을 생성하여 사용

 

음식 Entity가 외래 키의 주인

 

음식

@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @ManyToMany
    @JoinTable(name = "orders", // 중간 테이블 생성
    joinColumns = @JoinColumn(name = "food_id"), // 현재 위치인 Food Entity 에서 중간 테이블로 조인할 컬럼 설정
    inverseJoinColumns = @JoinColumn(name = "user_id")) // 반대 위치인 User Entity 에서 중간 테이블로 조인할 컬럼 설정
    private List<User> userList = new ArrayList<>();
}

 

고객

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}

생성되는 중간 테이블을 컨트롤하기 어렵기 때문에 추후에 중간 테이블의 변경이 발생할 경우

문제가 발생할 가능성이 있습니다.

 

양방향 관계

 

음식 Entity가 외래 키의 주인

 

음식

@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @ManyToMany
    @JoinTable(name = "orders", // 중간 테이블 생성
    joinColumns = @JoinColumn(name = "food_id"), // 현재 위치인 Food Entity 에서 중간 테이블로 조인할 컬럼 설정
    inverseJoinColumns = @JoinColumn(name = "user_id")) // 반대 위치인 User Entity 에서 중간 테이블로 조인할 컬럼 설정
    private List<User> userList = new ArrayList<>();
}

 

고객

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @ManyToMany(mappedBy = "userList")
    private List<Food> foodList = new ArrayList<>();
}

 

반대 방향인 고객 Entity에 @ManyToMany 로 음식 Entity를 연결하고 mappedBy 옵션을 설정하여 외래 키의 주인을 설정하면 양방향 관계 맺음이 가능합니다.

 

'TIL' 카테고리의 다른 글