Spring/Spring Boot

[Spring] JPA 매핑 연관관계 - 게시글에 댓글 달기

민돌v 2021. 12. 3. 00:06
728x90

연관관계

엔티티(Entity)들은 서로 관계를 맺고 있습니다.

게시글(Post)에 댓글(Comment)를 달 수 있고, 하나의 게시글은 여러개의 댓글을 갖질 수 있습니다.

이러한 관계를 1대N의 관계라 하며 각각의 엔티티들이 어떤 연관관걔를 맺는지 파악하는 것은 중요합니다.

예시

JPA의 경우는 Entitiy 클래스의 어노테이션을 설정해 주는 것만으로도 엔티티간의 연관관계를 형성할 수 있습니다.

 

 

용어

1) 방향

단방향 관계 : 두 엔티티가 관계를 맺을 때, 한 쪽의 엔티티만을 참조하는 것

양방향 관계 : 두 엔티티가 관계를 맺을 때, 양 쪽이 서로 참조하고 있는 것

 

데이터 모델링에서는(Mysql) 관계를 맺어주기만 하면 자동으로 양방향 관계로 서로 참조하지만, 객체지향 모델링에서는 구현하고자 하는 서비스에 따라 단방향인지 양방향인지 과계를 선택해야 한다고 합니다.

 

사실은 양방향 관계는 서로 다른 단뱡향 2개를 어플리케이션 로직으로 잘 묶어서 양방향인 것처럼 보이게 할 뿐, 양방향 연관 관계는 존재하지 않은다고 할 수 있다고 합니다.

 

2) 연관관계의 주인( Owner)

연관관계에서 주인을 결정합니다.

두 테이블에 대해서 외래키를 갖는 테이블이 연관 관계의 주인이 됩니다.

 

 

 

1. @ManyToOne - 단방향

@Entity
@Getter
@Setter
@NoArgsConstructor
@DynamicInsert
@Table(name = "post")
public class Post extends Timestamped {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long idx;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    private String content;

    @Column
    private String img;

  

@Getter
@Setter
@NoArgsConstructor
@Entity
public class PostComment extends Timestamped {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long idx;

    @Column(nullable = false)
    private String comment;


    @ManyToOne
    @JoinColumn(name = "post_id")
    private Post post;

    public PostComment(PostCommentRequsetDto postCommentRequsetDto, Post post, User user){
        this.post = post;
        this.user = user;
        this.comment = postCommentRequsetDto.getComment();

    }

@ManyToOne 

@ManyToOne 어노테이션은 이름 그대로 다대일( N : 1 ) 관계 매핑 정보입니다.

댓글 입장에서는 게시글과 다대일 관계이므로 @ManyToOne이 됩니다.

연관관계를 매핑할 때 이렇게 다중성을 나타내는 어노테이션(@ManyToMany, @OneToOne 등…)은 필수로 사용해야 하며, 엔티티 자신을 기준으로 다중성을 생각해야 합니다.

 

@JoinColumn(name="post_id") 

@JoinColumn 어노테이션은 외래 키를 매핑 할 때 사용합니다. 

name 속성에는 매핑 할 외래 키 이름을 지정합니다. 

PostComment 엔티티의 경우 Post 엔티티의 id 필드를 외래 키로 가지므로, post_id를 작성하면 됩니다.

 

@JoinColumn 어노테이션을 생략하면 아래와 같은 전략에 따라 외래 키를 매핑합니다.

필드명 +  “_” + 참조하는 테이블의 기본 키(@Id) 컬럼명

 

 

 

이제 게시글(Post)에서 댓글 정보를 가져오기 위해서는 양방향 관계를 맺어줘야 합니다.

 

 

2. @OnetoMany로 양방향 맺기

@Entity
@Getter
@Setter
@NoArgsConstructor
@DynamicInsert
@Table(name = "post")
public class Post extends Timestamped {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long idx;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    private String content;

    @Column
    private String img;

    @JsonIgnore
    @OneToMany(mappedBy = "post")
    private List<PostComment> comments = new ArrayList<PostComment>();

 

Post는 PostComment을 List로 가지며, @OneToMany 어노테이션에 mappedBy 속성을 추가했습니다.

 

연관관계의 주인을 정하는 방법은 mappedBy 속성을 사용하는 것입니다.

-  주인은 mappedBy 속성을 사용하지 않습니다.

-  주인이 아니면 mappedBy 속성을 사용해서 속성의 값으로 연관관계의 주인을 정할 수 있습니다.

 

주인은 mappedBy 속성을 사용할 수 없으므로 주인이 아닌 Post 엔티티의 Postcomment 필드에 mappedBy 속성을 사용하여 주인이 아님을 JPA에게 알려줍니다.

@OneToMany( mappedBy = "post“ )

private List<Postcomment> comments = new ArrayList<Postcomment>();

 

Post 엔티티에서 PostComment 엔티티의 정보를 가져오기 위해서 적어준 저 한줄의 필드(컬럼)이 Post 엔티티에서 얻어오는 정보가 아닌, Postcomment에서 정보를 얻어와 Post 엔티티에 매핑됨을 암시합니다.

 

 

@Jsonignore

필드 레벨에서 무시 될 수 있는 속성을 표시하는데 사용합니다.

위와 같은 양방향 통신에서, Request요청으로 데이터를 호출할 때, 참조된 엔티티의 데이터를 불러오면,

또다시 참조된 엔티티에서 양방향 통신중인 엔티티의 데이터를 호출 해서 2번의 Response가 일어납니다.

 

한 번의 Request에는 한번의 Response.

아래는 해당 에러의 내용입니다.

 

send err : https://thalals.tistory.com/227

 

 

끝!

 

 

 

 

 

*참고

JPA 연관관계 (너무 많은 내용을 가져옴,,, 이분 최고): https://victorydntmd.tistory.com/208

 

반응형