Entity Relationship

wjd15sheep·2024년 4월 14일
0

Spring Boot

목록 보기
5/19

다수의 엔티티는 관계를 가진다.

예를 들어 유저에 엔티티에서는 상품 주문의 엔티티와 연결이 되고 상품 주문의 엔티티는 상품의 엔티티와 연관이 되어 유저가 상품을 선택했을때 엔티티의 관계를 통해서 관련 데이터를 찾아서 사용자에게 정보를 반환해 준다.

그럼 스프링 부트에서는 엔티티의 관계를 어떻게 정의할까?

스프링에서는 연관관계를 정의하는 방법은 3가지만 고려하면 된다.

  • 다중성 : N:M 관계 정의
    • @OneToMany ↔ @ManyToOne
    • @OneToOne ↔ @OneToOne
    • @ManyToMany ↔ @ManyToMany
  • 방향 : 단방향, 양방향 → 연관관계를 갖는 두 객체 중 어디에 다중성을 표기할까?
  • 연관관계의 주인 : 양방향일때, 연관 관계에서 관리 주체 → 주인만 mappedBy를 갖는다.

예) User 엔티티

엔티티를 보면 칼럼은

기본키는 user_id, user_name, email, password, user_image를 가진다.

그 밑에 있는 @OneToMany의 어노테이션은 다른 테이블과의 관계를 보여준다.

관계를 나타내는 맵핑

 @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
 List<Review> reviewList = new ArrayList<>();

@OneToMany : 1:N 관계 유저 테이블이 하나일때 Review 테이블은 여러개라는 의미

mappedBy : 연관관계의 주인에게 적는 것이다. 주인은 user라고 명명 한 것이다.

casscade : 제약사항으로 부모를 삭제하면 자식도 삭제할지에 대한 제약사항이다.

List 명칭 = new ArrayList<>(); : user 필드에서 어떻게 불러올 것인가에 정의한 것


방향 : 단방향 / 양방향

위에서 언급했듯이 테이블의 관계는 단방향 양방향으로 나누어진다.

테이브은 외래키 하나로 양쪽 테이블 조인이 가능하지만 객체는 참조를 위한 객체 필드가 있어야지 양쪽 객체간 참조가 가능하며, 양쪽 객체에 모두 다중성의 대칭성을 적용하면 양방향, 한쪽 객체(연관관계의 주인)에만 정의 하면 단방향

연관관계의 주인 : mappedBy 정의

@Entity
@Getter
public class User {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "user_id")
  private Long id;

  @Column(nullable = false)
  private String username;

  @Column(nullable = false)
  private String email;

  @Column(nullable = false)
  private String password;

  @Column(nullable = false)
  private String userImage;

  @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
  List<Review> reviewList = new ArrayList<>();

  @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
  List<Likes> likesList = new ArrayList<>();

  @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
  List<AffectionPost> affectionPostList = new ArrayList<>();

  @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
  List<TogetherPost> togetherPostList = new ArrayList<>();
}

연관관계 주인이 아님 @JoinColumn 정의

  @Entity
@Setter
@Getter
public class Review {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "review_id")
    private Long reviewId;

    @CreatedDate // 엔티티가 생성된 날짜를 나타내는 필드를 선언
    private LocalDateTime write_at;

    @Column(nullable = false)
    private String content;

    // 외래키 리뷰 작성한 User_id
    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "user_id")
    private User user;


    // 외래키 게시글 id
    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "post_id")
    private Post post;

}

연관 관계의 주인은 자식이 누구인지에 대해서 DB 테이블의 칼럼으로 나오지 않는다.

그러나 자식은 부모가 누구인지 테이블의 칼럼에 나와 정의해 주어야 한다.

부모는 자식 몰라도 됨, 자식은 부모가 누구인지 알려줘야함

단방향은 mappedBy를 적어주지 않고 한쪽 필드에서만 @JoinColumn을 적어주면 된다.

FetchType = EAGER / LAZY

  • EAGER DB에서 연관관계를 가진 테이블을 조회할때 필요한 테이블이 있을때마다 JOIN을 하지만 객체는 그 자체로 연관관계를 가진 객체들을 이미 가지고 있기에 연관관게를 많이 가진 객체를 DB에서 가져올때 강제로 수많은 JOIN된 엄청 큰 감자뿌리가 나온다.
  • LAZY 가져오고자하는 객체만 먼저 가져오고, 해당 객체와 연관관계를 가진 객체들은 모두 프록시 객체로 가져온다. 가져오려는 오청이 있을때 하나씩 가져오는 방식

@JoinColumn

외래키를 갖는 테이블에 @JoinColumn을 설정하기에 사용

@ManyToOne(fetch = LAZY)
@JoinColumn(name = "user_id")
private Post post;

예시로 Rivew 필드에 칼럼명을 정의를 user_id로 합니다.
그럼 DB 테이블에 칼럼에 user_id가 생긴 모습을 볼 수 있다.

profile
성장 위해 노력하는 웹 개발자 주니어

0개의 댓글