2023-06-20 Daily Post
Daily TODO
- Answer CRUD 구현 완성
- 추가 - User CRUD 구현
- CRD 구현완료, Update 내일 구현 예정
- Update, Comment Entity까지 구현 필요함
- JWT 이용한 login & logout 구현
- OAuth 구현
- H2 말고 MySQL이랑 연결 (영구적인 데이터베이스)
- 테스트 데이터도 생성하면 더 좋지 않을까 생각함!!
- 금요일에 AWS 써서 배포까지 할 수 있으면 좋을 거 같다
메모 & TIL:
Pre-project
- 하면서 이상하게 자꾸 patchAnswer에서 오류가 났다 (이거만 한 6시간 본 듯)
- 자꾸 널포인터 오류가 난대서 매핑의 문제인줄로 알았으나…… 전혀 아니었다!
- 결론부터 보자면 Repository에서 가져온 객체는 여기에(Answer) 매핑된 객체(Vote)가 초기화 안됐을수도 있으니까 그부분 처리를 해줘야 했음 (근데 왜 매핑된 객체를 옵셔널 바인딩으로 하면 처리가 잘 안되는지 모르겟음)
public Answer updateAnswer(Answer answer, Long answerId, Long voteCnt) {
Answer findAnswer = findVerifiedAnswer(answerId);
Optional.ofNullable(answer.getContent())
.ifPresent(content -> findAnswer.setContent(content));
Optional.ofNullable(answer.getAccepted())
.ifPresent(accepted -> findAnswer.setAccepted(accepted));
if (findAnswer.getVote() == null) {
findAnswer.setVote(new Vote());
}
findAnswer.setVoteCount(findAnswer.getVoteCount() + voteCnt);
findAnswer.setModifiedAt(LocalDateTime.now()); // 최종 수정시간 현재 시간으로 변경
return answerRepository.save(findAnswer);
}
- 그리고 dto에서 엔티티로 변환한 객체에서 식별자(Id) 가져오려고 하면 안되서 (지금 생각해보니 dto에 id를 안 받게 만들었으니 당연함 ㅎㅎ 머쓱…) updateAnswer 메소드에 직접 파라미터로 넣어줬다. voteCnt도 마찬가지!
@PatchMapping("/{answer-id}")
public ResponseEntity patchAnswer(@PathVariable("answer-id") @Positive long answerId,
@Valid @RequestBody AnswerPatchDto answerPatchDto){
Answer answer = answerService
.updateAnswer(mapper.answerPatchDtoToAnswer(answerPatchDto),
answerId,
answerPatchDto.getVoteCnt());
return new ResponseEntity<>(
new SingleResponseDto<>(mapper.answerToAnswerResponseDto(answer)), HttpStatus.OK);
}
- 그리고 객체 여러개 엮여잇으니까 매핑해주자.
public interface AnswerMapper {
...
@Mapping(target = "vote.voteCnt", source = "voteCnt")
Answer answerPatchDtoToAnswer(AnswerPatchDto answerPatchDto);
}
Answer
업데이트할때 매핑된 객체(Vote
)의 필드 변수 값voteCnt
도 같이 업데이트하고 싶어요~ 할때 이런식으로 매핑해주면 된다.
유사한 기능이 있다면 제너릭을 활용하자
- Vote 객체가 질문과 답변 객체 둘 다에 쓸거라 고민하다가 제너릭을 도입해서 아주 사알짝 리팩토링을 했다.
package com.codestates.PreProject.vote;
import com.codestates.PreProject.answer.entity.Answer;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
@Getter
@Setter
@NoArgsConstructor
@Entity
public class Vote <T> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long voteId;
@Column(nullable = false)
public Long voteCnt = 0L;
// @OneToOne
// @JoinColumn(name = "ANSWER_ID")
// private Answer answer;
@OneToOne
// mapping은 각 구현체에서...
private T content;
// public void setAnswer(Answer answer){
// this.answer = answer;
// }
public void setContent(T content){
this.content = content;
}
}
- 기존 코드에서 Answer이 잇던 부분을 제너릭으로 바꿨다. 바꿔도 정상작동한다. 다만 구현체는 만들어줘야 한다
package com.codestates.PreProject.vote;
import com.codestates.PreProject.answer.entity.Answer;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.OneToOne;
@Entity
@Getter
@Setter
@NoArgsConstructor
public class AnswerVote extends Vote<Answer>{
@OneToOne
private Answer answer;
}
이런 식으로… 구현체의 클래스도 만들어주면 기존이랑 똑같이 요청 날려도 정상적으로 수행된다!
Leave a comment