본문 바로가기
개발 관련 학습 및 문제해결

자바 DTO의 속성값에 배열넣어주기[20221101-TIL]

by 날파리1 2022. 11. 1.

요 며칠 한참을 고민한 문제가 바로

DTO에 배열을 넣어주는 문제였다.

 

여태까지는 

객체DTO를 만들어서 

그 객체가 속성값으로 String 이나 Long 을 가지고 있고 그것들을 List<DTO> 형태로 보내주어서 JSON 타입으로 받았는데

 

리스트 안의 DTO가 속성으로 List<객체>를 들고 있으니 바로 에러가 떠버린다.

 

사실 게시글을 작성할때  게시물이 댓글을 들고 있다거나 해쉬태그를 들고있다거나 하나의 객체가 같은 속성이지만 복수의 속성을 들고 있는 경우는 매우 많은 것 같은데 이게 구현이 잘 안됬다.

 

시도한 것

1. 자꾸 데이터측면에서 접근함

데이터에서 어떻게 나누어야 잘나눌까를 고민하다가 실패

 

2. List<List<원하는 속성값>> 으로 넣어주기

위와 같이 원하는 속성값들을 배열로만든 후 DTO로 변환후 다시 배열 DTO로 변환하려고 했는데 저 속성값들이 참조하는 모델(즉 댓글이면 댓글들을 남긴 게시물 모델, 해쉬태그면 해쉬태그들이 달린 게시물 모델 등)을 찾아오기가어려워 포기...(저거 구현자체로도 머리가 복잡하다.) 

 

ManyToOne , OneToMany 어노테이션 이용하기

위 어노테이션을 이용하면 반환하려는 DTO에 List<객체> 형태가 들어가도 된다. 

스터디 모임을 모집하는 게시물을 만들고 싶어서 스터디라는 클래스를 만들었고 스터디라는 클래스는 속성값으로 복수의 해쉬태그를 지닌다.(List<HashTag>)

 

그리고 OneToMany라른 어노테이션을 지정해주고 해당 클래스에 "study"라는 이름으로 맵핑된다고 지정해준다.(해당 클래스 HashTag에서도 저 이름과 똑같이 맞춰주어야한다.)

 

@JsonMangeedReference는 순환참조를 방지해준다는데 저게 없으면 작동이 안되어서 붙였는데 또 제거하거니 작동이 되기도해서 다음에 정리를 하겠다.

그리고 

@OneToMany(mappedBy = "article", fetch = FetchType.LAZY)

처럼 게으른 불러오기? 라는 것도 있는데 이것도 아직은 필요하지 않아서 다시 정리하도록 하겠다.

@Entity
public class Study {
  @Id
  @GeneratedValue
  private Long id;
  private String writer;
  private String title;
  private String content;
  private Long views;
  private Long likes;

  @JsonManagedReference
  @OneToMany(mappedBy = "study")
  private List<HashTag> hashTags = new ArrayList<>();

  public Study(Long id,
               String writer,
               String title,
               String content,
               Long views,
               Long likes,
               List<HashTag> hashTags) {
    this.id = id;
    this.writer = writer;
    this.title = title;
    this.content = content;
    this.views = views;
    this.likes = likes;
    this.hashTags = hashTags;
  }

 

다시 반대로 ManyToOne을 써줄 즉 하나의 객체에 달릴 복수의 객체들의 클래스에

 

@ManyToOne  을 해준후 칼럼을 조인시켜준다.

Study 의 study 라고 했기때문에 mappedBy= "study" 라고 했다.

@Entity
public class HashTag {
  @Id
  @GeneratedValue
  private Long id;
  private String tag;
  @JsonBackReference
  @ManyToOne
  @JoinColumn(name = "study_id")
  private Study study;

  public HashTag() {
  }

  public HashTag(Long id, String tag, Study study) {
    this.id = id;
    this.tag = tag;
    this.study = study;
  }

 양방향 참조를 하지 않고도 게시물에 해쉬태그를 하려면 단방향으로 OneToMany 만 사용해도 된다고하는데 차후에 해쉬태그를 가지고 게시물에 접근할 일이 있을 것 같아서 양방향으로 했다.

 

그리고 컨트롤러에서 다음과 같이 DTO를 만들어주면된다! ( List<HastTag> 해당하는 속성을 다시 List<HasgTagDto>로 변환을 안해줘도 된다는게 좋았다. 이걸로 엄청 고민했는데.....)

List<StudyDto> studyDtos =
    studyService.list(page)
        .stream()
        .map(Study::toDto)
        .collect(Collectors.toList());

 

어설픈 구조에 어설픈 방식이겠지만 일단...어찌어찌 구현완료.... 정말 돌아돌아돌아 쉽게(?) 허무하게 해서 뭔가.... 그렇다.  코드만 보면 뭐이리 다 쉬운데 그전엔 모르니까 어려운지.. 그래도 하나 더 알았다!

 

액션플랜

이걸로 추가 기능 구현 뭐 할지 생각해보고 적용해보자!

댓글