요 며칠 한참을 고민한 문제가 바로
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());
어설픈 구조에 어설픈 방식이겠지만 일단...어찌어찌 구현완료.... 정말 돌아돌아돌아 쉽게(?) 허무하게 해서 뭔가.... 그렇다. 코드만 보면 뭐이리 다 쉬운데 그전엔 모르니까 어려운지.. 그래도 하나 더 알았다!
액션플랜
이걸로 추가 기능 구현 뭐 할지 생각해보고 적용해보자!
'개발 관련 학습 및 문제해결' 카테고리의 다른 글
Jpa repository save 는 왜 null 일까? 1[20221103 TIL] (0) | 2022.11.03 |
---|---|
ManyToOne, OneToMany 를 쓰지않고 DTO에 List 속성 넣어주기[20221102 TIL] (0) | 2022.11.02 |
데이터베이스에 배열 넣기?[20221031-TIL] (0) | 2022.10.31 |
게시판 프론트 엔드 구현하기[20221030-TIL] (0) | 2022.10.30 |
프로젝트 기간 시간 및 작업량 관리하는 법[20221029 TIL] (0) | 2022.10.29 |
댓글