1. 문제
2025-02-17T20:33:21.451+09:00 WARN 2680 --- [demo] [main] ConfigServletWebServerApplicationContext :
Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'todoController':
Unsatisfied dependency expressed through field 'service':
Error creating bean with name 'todoService':
Unsatisfied dependency expressed through field 'repository':
Error creating bean with name 'todoRepository' defined in com.example.demo.repository.TodoRepository
defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration:
Could not create query for public abstract java.util.List com.example.demo.repository.TodoRepository.findByUserId(java.lang.String);
Reason: Line 1:7 extraneous input '*' expecting {'(', '[', ':', '{', '?', ID, VERSION, ...}
spring을 실행시킨 후 해당 에러를 내뱉었는데, 위에서 가장 핵심이 되는 곳은
'Could not create query for public abstract java.util.List com.example.demo.repository.TodoRepository.findByUserId(java.lang.String);'
위 에러이다. findByUserId(String userId) 메서드가 잘못된 문법을 포함하고 있다는 것인데 책이라 그냥 써놓고 실행하니까 될 줄 알았는데 에러가 발생해서 당황했다.
TodoRepository -> TodoService -> TodoController 까지 연속적으로 에러가 엮이다 보니까 파악하기 힘들어서 chat gpt에게 부탁해서 아래에 써놓았다. 그리고 이클립스가 생각보다 Console에 출력되는 에러가 읽기 더 힘든 것 같다.
1. 오류 원인 분석
해당 에러 메시지를 단계별로 분석하면 다음과 같다.
- Spring Boot 애플리케이션 실행 중 ConfigServletWebServerApplicationContext가 초기화 실패
- Exception encountered during context initialization - cancelling refresh attempt
- 애플리케이션이 시작하는 과정에서 Bean을 제대로 생성하지 못해 실행이 중단됨.
- UnsatisfiedDependencyException (의존성 주입 실패)
- Error creating bean with name 'todoController': Unsatisfied dependency expressed through field 'service'
- TodoController의 todoService 필드에서 의존성을 주입하지 못함.
- 의존성 전달 문제 (todoService → todoRepository)
- Error creating bean with name 'todoService': Unsatisfied dependency expressed through field 'repository'
- todoService의 todoRepository 필드에서 의존성을 주입하지 못함.
- JPA Repository (todoRepository) 생성 실패
- Error creating bean with name 'todoRepository'
- Spring Data JPA에서 todoRepository를 인식하지 못함.
- 쿼리 메서드 오류 (findByUserId의 문법 문제)
- Could not create query for public abstract java.util.List com.example.demo.repository.TodoRepository.findByUserId(java.lang.String);
- findByUserId(String userId) 메서드가 잘못된 문법을 포함하고 있음.
→ 결과적으로 todoService, todoController까지 연쇄적으로 영향을 받아 실행이 중단됨.
@Repository
public interface TodoRepository extends JpaRepository<TodoEntity, String> {
// ?1은 메서드의 매개변수의 순서 위치이다.
@Query("SELECT * FROM TODO t WHERE t.userID = ?1")
List<TodoEntity> findByUserId(String userId);
}
내 스프링 부트 버전은 3.4.2이고 책이 쓰여진 스프링 버전은 2.5.0이다. chat gpt가 말하길 Spring 2.5.1은 2007년에 출시된 매우 오래된 버전으로 JPA 기능을 기본 제공하지 않아 위 코드가 동작하지 않았을 것이라는데,,, 우선 에러는 해결하고 나중에 책 한 번 더 돌릴 때 다시 봐야 겠다.
2. 문제 원인
@Query("SELECT * FROM TODO t WHERE t.userID = ?1")
위 JPQL(Query) 문법이 잘못되었기 때문에 발생했다.
1. JPQL 문법 오류
- SELECT * FROM 구문은 JPQL에서 허용되지 않는다.
- JPQL에서는 엔티티를 직접 선택해야 하며, 테이블 이름이 아니라 엔티티 클래스명을 사용해야 한다.
2. 엔티티 클래스명 사용
- JPQL에서는 SQL과 다르게 테이블이 아니라 엔티티 이름을 사용해야 한다.
- 엔티티 이름은 @Entity가 선언된 클래스명이며, 일반적으로 TodoEntity처럼 CamelCase 형태로 사용된다.
3. 필드명 문제
- userID 필드가 TodoEntity에서 userId로 선언되어 있을 가능성이 높다.
- JPQL에서는 엔티티 클래스의 필드명을 사용해야 한다. (DB 컬럼명이 아니라 필드명)
즉, * (wild card) 기호도 잘못되었고, TODO가 테이블 명이고 TodoEntity가 엔티티 명인데 이 부분도 잘못되었고 아무튼 위에 잘못된 부분이 한 가지가 아니다.
3. 문제 해결
@Repository
public interface TodoRepository extends JpaRepository<TodoEntity, String> {
@Query("SELECT t FROM TodoEntity t WHERE t.userId = ?1")
List<TodoEntity> findByUserId(String userId);
}
위와 같이 바꿔주니 잘 동작한다.
'React.js, 스프링 부트, AWS로 배우는 웹 개발 101' 카테고리의 다른 글
[TIL] 25/02/16, 서비스 개발 및 실습(2) (0) | 2025.02.18 |
---|---|
[TIL] 25/02/16, 서비스 개발 및 실습(1) (0) | 2025.02.17 |
[TIL] 25/01/29, 퍼시스턴스 레이어 : 스프링 데이터 JPA (0) | 2025.01.29 |
[TIL] 25/01/28, Service Layer : Business Logic (0) | 2025.01.29 |
[TIL] 25/01/27, REST API (0) | 2025.01.28 |