java 배우기/TIL

date 타입 불일치로 인한 에러

checkuu 2024. 10. 3. 19:27

 

문제 발생

 

 

코드 리팩토링으로 할일 조회에 날짜를 기준으로 검색을 할 수 있도록 코드를 짰다.

@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