[문제]
400번 대이든 500번 대이든 오류 났다는 메시지가 뜨면 그나마 코드를 잘못 썼다고 짐작할 수 있는데, 200 OK 메시지와 다르게 입력한 값이 제대로 반영되지 않으면 더 골치 아팠다. null도 문제였으나, 수정됐다면서 일정 수정 날짜인 updatedAt의 값이 그대로인 점이 더 골치 아팠다. 도대체 원인이 뭔지 추측조차 못 한 채, '코드 또 전부 다 뜯어고쳐야겠구나.' 해탈한 심정으로 튜터님께 찾아갔다.
[원인]
package com.example.plan.plan.dto.request;
import lombok.Getter;
// 일정 수정 요청에 해당하는 request DTO
@Getter
public class UpdatePlanRequestDto {
// (1) 속성
private final String newUsername;
private final String newTitle;
private final String newTask;
// (2) 생성자
public UpdatePlanRequestDto(
String newUsername,
String newTitle,
String newTask
) {
this.newUsername = newUsername;
this.newTitle = newTitle;
this.newTask = newTask;
}
// (3) 기능
}
원인은 일정 수정 요청에 해당하는 request DTO 클래스(class)에서 속성에 해당하는 변수 이름과 실제로 요청할 때 쓴 이름이 다른 데에 있었다. 원인을 발견한 직후, 입을 꾹 다문 채 다짐했다. 이름을 다 기억할 자신이 없다면, 쓸데없이 'new'를 붙이지 말자고. 가뜩이나 대문자로 바꿔서 쓰기도 번거로우니까.
[해결]
package com.example.plan.plan.dto.request;
import lombok.Getter;
// 일정 수정 요청에 해당하는 request DTO
@Getter
public class UpdatePlanRequestDto {
// (1) 속성
private final String title;
private final String task;
// (2) 생성자
public UpdatePlanRequestDto(
String title
, String task
) {
this.title = title;
this.task = task;
}
// (3) 기능
}
우선 일정 수정 요청 시 이름을 잘못 쓰는 일이 없도록 UpdatePlanRequestDto 클래스의 변수 이름을 다른 클래스의 변수 이름과 똑같이 지었다. 그다음으로는 일정만 수정하도록 작성자 이름을 속성에서 제외했다.
package com.example.plan.plan.service;
import com.example.plan.plan.dto.response.PlanResponseDto;
import com.example.plan.plan.entity.Plan;
import com.example.plan.plan.repository.PlanRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/*
일정(Plan)의 service layer
PlanService 인터페이스(interface)를 오버라이딩했다.
*/
@Service
@RequiredArgsConstructor
public class PlanServiceImpl implements PlanService {
// 속성
private final PlanRepository planRepository;
// 기능 [1/5] 일정 저장
@Override
public PlanResponseDto save(
String username
, String title
, String task
) {
Plan planToSave = new Plan(
username
, title
, task
);
Plan savedPlan = planRepository.save(planToSave);
return new PlanResponseDto(
savedPlan.getId()
, savedPlan.getUsername()
, savedPlan.getTitle()
, savedPlan.getTask()
);
}
// 기능 [2/5] 일정 목록 찾기
@Override
public List<PlanResponseDto> findAll() {
List<PlanResponseDto> allPlans = new ArrayList<>();
allPlans = planRepository.findAll()
.stream()
.map(PlanResponseDto::toDto)
.toList();
return allPlans;
}
// 기능 [3/5] 일정 단건을 id로 찾기
@Override
public PlanResponseDto findById(Long id) {
Plan foundPlan = planRepository.findByIdOrElseThrow(id);
return new PlanResponseDto(
foundPlan.getId()
, foundPlan.getUsername()
, foundPlan.getTitle()
, foundPlan.getTask()
);
}
// 기능 [4/5] 일정 단건 수정
@Transactional
@Override
public PlanResponseDto updatePlan(
Long id
, String title
, String task
) {
Plan planToUpdate = planRepository.findByIdOrElseThrow(id);
planToUpdate.update(
title
, task
);
return new PlanResponseDto(
planToUpdate.getId()
, planToUpdate.getUsername()
, planToUpdate.getTitle()
, planToUpdate.getTask()
);
}
// 기능 [5/5] 일정 단건 삭제
@Override
public void delete(Long id) {
Plan foundPlan = planRepository.findByIdOrElseThrow(id);
planRepository.delete(foundPlan);
}
}
변수 이름을 모두 통일한 다음에는 일정 생성 날짜와 일정 수정 날짜는 반환하지 않는 쪽으로 코드를 수정했다. 이번에 스프링(Spring)을 공부하면서 새롭게 배운 @Transactional 어노테이션(annotation)을 사용하고 싶었는데, 두 날짜까지 포함되면 시차가 발생했다. 데이터베이스(database)에 각 날짜와 시간이 잘 저장된다면 굳이 반환하지 않아도 된다는 튜터님의 말씀에 과감하게 제외했다. @Transactional을 쓰지 않는다면 데이터베이스와 한 번 더 소통해서 해결할 수 있다고 저번에 트러블슈팅(troubleshooting)을 정리하면서 알았으니까. 이렇게 문제 하나를 해결했다.
'Troubleshooting: 무엇이 문제였는가? > 본캠프 3주 차: 일정 관리 앱 Develop' 카테고리의 다른 글
2단계: "MySQL Error 1049: Unknown database" (0) | 2024.12.15 |
---|---|
1단계: "not-null property references a null or transient value" (0) | 2024.12.13 |