문제 발생
코드 리팩토링으로 할일 조회에 날짜를 기준으로 검색을 할 수 있도록 코드를 짰다.
@GetMapping("/todos")
public ResponseEntity<Page<TodoResponse>> getTodos(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String weather,
@RequestParam(required = false)@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
@RequestParam(required = false)@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate
) {
return ResponseEntity.ok(todoService.getTodos(page, size, weather,startDate,endDate));
}
public Page<TodoResponse> getTodos(int page, int size, String weather, LocalDate startDate,LocalDate endDate) {
Pageable pageable = PageRequest.of(page - 1, size);
Page<Todo> todos;
if(weather != null && !weather.isEmpty()) {
if(startDate != null && endDate != null){
todos = todoRepository.findAllByWeatherAndDate(pageable,weather,startDate,endDate);
}
todos = todoRepository.findAllByWeather(pageable,weather);
}else {
if(startDate != null && endDate != null){
todos = todoRepository.findAllByDate(pageable,startDate,endDate);
}
todos = todoRepository.findAllByOrderByModifiedAtDesc(pageable);
}
return todos.map(todo -> new TodoResponse(
todo.getId(),
todo.getTitle(),
todo.getContents(),
todo.getWeather(),
new UserResponse(todo.getUser().getId(), todo.getUser().getEmail()),
todo.getCreatedAt(),
todo.getModifiedAt()
));
}
이렇게 @RequestParam으로 입력받는 것으로 짰는데, 에러가 발생하였다.
2024-10-03T18:37:17.878+09:00 ERROR 11468 --- [spring-plus] [nio-8080-exec-2] org.example.expert.config.JwtFilter : Internal server error
jakarta.servlet.ServletException: Request processing failed:
org.springframework.dao.InvalidDataAccessApiUsageException: Argument [2024-10-02] of type [java.time.LocalDate] did not match parameter type [java.time.LocalDateTime (n/a)]
보니 입력하는 타입과 저장된 데이터간에 type차이로 인한 에러로 보여졌다.
원인
entity에는 작성 시간을 LocalDateTime으로 생성하고,
조회시 입력하는 @RequestParam에는 시간까지 넣는건 매우 귀찮을 것 같아 LocalDate로 타입을 만들어서
LocalDateTime과 LocalDate 타입차이로 인한 에러인것으로 생각된다.
해결
LocalDateTime startDateTime = startDate != null ? startDate.atStartOfDay() : null;
LocalDateTime endDateTime = endDate != null ? endDate.atTime(23, 59, 59) : null;
해당 코드를 서비스단 초반에 삽입하여 입력받은 날짜를 LocalDateTime과 같은 형식으로 맞춰줬다.
시작날짜는 atStartOfDay로 그날의 00시00분00초로 변환되고,
끝날짜는 atTime(23, 59, 59) 그날의 23시59분59초로 변환되어 다음 로직으로 진행
public Page<TodoResponse> getTodos(int page, int size, String weather, LocalDate startDate,LocalDate endDate) {
Pageable pageable = PageRequest.of(page - 1, size);
Page<Todo> todos;
LocalDateTime startDateTime = startDate != null ? startDate.atStartOfDay() : null;
LocalDateTime endDateTime = endDate != null ? endDate.atTime(23, 59, 59) : null;
if(weather != null && !weather.isEmpty()) {
if(startDate != null && endDate != null){
todos = todoRepository.findAllByWeatherAndDate(pageable,weather,startDateTime,endDateTime);
}
todos = todoRepository.findAllByWeather(pageable,weather);
}else {
if(startDate != null && endDate != null){
todos = todoRepository.findAllByDate(pageable,startDateTime,endDateTime);
}
todos = todoRepository.findAllByOrderByModifiedAtDesc(pageable);
}
return todos.map(todo -> new TodoResponse(
todo.getId(),
todo.getTitle(),
todo.getContents(),
todo.getWeather(),
new UserResponse(todo.getUser().getId(), todo.getUser().getEmail()),
todo.getCreatedAt(),
todo.getModifiedAt()
));
}
@Query("SELECT t from Todo t where (t.weather in :weather) AND (t.modifiedAt BETWEEN :startDate and :endDate)")
Page<Todo> findAllByWeatherAndDate(Pageable pageable,
@Param("weather") String weather,
@Param("startDate") LocalDateTime startDateTime,
@Param("endDate") LocalDateTime endDateTime);
@Query("select t from Todo t where t.modifiedAt BETWEEN :startDate and :endDate ")
Page<Todo> findAllByDate(Pageable pageable, @Param("startDate") LocalDateTime starDateTime,@Param("endDate") LocalDateTime endDateTime);
수정 후 정상 작동하여 할일이 조회가 되었다.

이것땜에 검색하면서 추가적으로 알게된 사실
@Query("select t from Todo t where t.modifiedAt BETWEEN :startDate and :endDate ")
Page<Todo> findAllByDate(Pageable pageable,
@Param("startDate") LocalDateTime startDateTime,
@Param("endDate") LocalDateTime endDateTime);
repository에서 JPQL 문 작성시 @Param의 괄호 뒤 (" ") 내용이 @RequestParam 에서 입력받는 것과 같은 이름을 쓰고
@Query 에도 똑같이 매핑해줘야한다고 생각했는데,
@Param 뒤 (" ")는 그냥 뒤에 오는 LocalDateTime startDateTime 을 뭐라고 할것인지 명명해주는 것이고 명명된 이름이 @Query의 :startdate와 매칭되는것이었다.
'java 배우기 > TIL' 카테고리의 다른 글
| 기술 면접 준비하기-1 (0) | 2024.10.10 |
|---|---|
| N+1 문제 해결해보기 (0) | 2024.10.03 |
| 포크해온 코드 분리하기 (0) | 2024.10.02 |
| CI/CD란 (0) | 2024.10.02 |
| aws EC2 instances 삭제 (0) | 2024.09.27 |