タイトル: エラー一覧
SEOタイトル: Spring Framework のよくあるエラー一覧と対処法 — Bean / Autowire / Hibernate ほか
| この記事の要点 |
|
Spring エラーの全体像
Spring のエラーは大きく以下に分類できます:
- 起動時 (Bean 生成): BeanCreationException、NoSuchBeanDefinitionException、循環依存
- リクエスト処理時: HttpMessageNotReadableException、MethodArgumentNotValidException
- セキュリティ: AccessDeniedException、AuthenticationException
- データアクセス: DataIntegrityViolationException、LazyInitializationException
- 設定: ConfigurationPropertiesBindException、UnsatisfiedDependencyException
1. BeanCreationException / UnsatisfiedDependencyException
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'userService':
Unsatisfied dependency expressed through constructor parameter 0:
No qualifying bean of type 'com.example.UserRepository' available
原因: 依存する Bean が DI コンテナに存在しない。
// ❌ UserRepository に @Repository / @Component が無い
public interface UserRepository extends JpaRepository<User, Long> { ... }
// ✅ Spring Data JPA なら自動検出されるが、@EnableJpaRepositories のスキャン範囲を確認
@SpringBootApplication
@EnableJpaRepositories(basePackages = "com.example.repository") // 明示
public class App { ... }
// ❌ コンストラクタ注入で型が間違っている
@Service
public class UserService {
public UserService(UserRepository repo) { ... } // UserRepository が DI 対象になっているか
}
2. NoSuchBeanDefinitionException
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'com.example.MyService' available:
expected at least 1 bean which qualifies as autowire candidate
対処:
@Service/@Component/@Repositoryアノテーションが付いているか- コンポーネントスキャンの対象パッケージか (
@SpringBootApplicationのパッケージとサブ) @Configuration+@Beanでの明示登録なら戻り値型が期待型と一致しているか
3. BeanCurrentlyInCreationException (循環依存)
BeanCurrentlyInCreationException: Error creating bean with name 'a':
Requested bean is currently in creation: Is there an unresolvable circular reference?// ❌ A と B がコンストラクタで相互依存 → 起動失敗
@Service class A { public A(B b) {} }
@Service class B { public B(A a) {} }
// ✅ 対処1: @Lazy で遅延注入
@Service class A {
public A(@Lazy B b) { this.b = b; }
}
// ✅ 対処2: setter 注入に変更
@Service class A {
private B b;
@Autowired public void setB(B b) { this.b = b; }
}
// ✅ 対処3: そもそも設計を見直す (中間サービスを抽出)
Spring Boot 2.6+ では循環依存がデフォルトで禁止されます。許可する場合は spring.main.allow-circular-references=true を設定しますが、根本的な設計修正を推奨。
4. NoUniqueBeanDefinitionException
NoUniqueBeanDefinitionException: No qualifying bean of type
'com.example.PaymentService' available: expected single matching bean
but found 2: stripePaymentService, paypalPaymentService// ❌ 同じ型の Bean が複数 → どれを注入すべきか分からない
@Service class StripePaymentService implements PaymentService { ... }
@Service class PaypalPaymentService implements PaymentService { ... }
@Service
public class OrderService {
public OrderService(PaymentService p) { ... } // どっち?
}
// ✅ 対処1: @Qualifier で指定
public OrderService(@Qualifier("stripePaymentService") PaymentService p) { ... }
// ✅ 対処2: @Primary で優先順位を付ける
@Service @Primary
class StripePaymentService implements PaymentService { ... }
// ✅ 対処3: List で全部取る
public OrderService(List<PaymentService> services) { ... }
5. HttpMessageNotReadableException
HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type
`java.time.LocalDate` from String "2026/05/17": Failed to deserialize
JSON のフォーマット不正・型不一致。
// ✅ 対処: @JsonFormat で受信フォーマット指定
public class Request {
@JsonFormat(pattern = "yyyy/MM/dd")
private LocalDate birthDate;
}
// グローバル設定
@Configuration
public class JacksonConfig {
@Bean public Jackson2ObjectMapperBuilderCustomizer customize() {
return b -> b.simpleDateFormat("yyyy/MM/dd");
}
}
6. MethodArgumentNotValidException / BindException
// @Valid で起きるバリデーションエラー
@PostMapping("/users")
public User create(@RequestBody @Valid UserDto dto) { ... }
// グローバルハンドリング
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidation(MethodArgumentNotValidException e) {
Map<String, String> errors = new HashMap<>();
e.getBindingResult().getFieldErrors().forEach(err ->
errors.put(err.getField(), err.getDefaultMessage())
);
return ResponseEntity.badRequest().body(errors);
}
}
7. AccessDeniedException (Spring Security)
org.springframework.security.access.AccessDeniedException: Access is denied
原因: 認可エラー。@PreAuthorize や SecurityFilterChain の設定でアクセス拒否。
// ✅ ハンドラー
@ControllerAdvice
public class SecurityExceptionHandler {
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<?> handle(AccessDeniedException e) {
return ResponseEntity.status(403).body(Map.of("error", "Forbidden"));
}
}
8. ConfigurationPropertiesBindException
Failed to bind properties under 'app.timeout' to java.time.Duration:
Reason: failed to convert java.lang.String to java.time.Duration# ❌ application.yml
app:
timeout: 30
# ✅ Duration 形式
app:
timeout: 30s # または PT30S
9. LazyInitializationException (Hibernate)
org.hibernate.LazyInitializationException:
could not initialize proxy [com.example.Order#1] - no Session
原因: Entity の Lazy 関連を、トランザクション外(Controller やテンプレート)で参照した。
// ❌ Service で取得した User の orders を Controller で参照 → 例外
@Transactional(readOnly = true)
public User findUser(Long id) {
return userRepo.findById(id).orElseThrow();
}
// Controller では Transaction が閉じている → user.getOrders() で爆発
// ✅ 対処1: JOIN FETCH
@Query("SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :id")
User findUserWithOrders(Long id);
// ✅ 対処2: @EntityGraph
@EntityGraph(attributePaths = "orders")
Optional<User> findById(Long id);
// ✅ 対処3: DTO に詰めて返す (推奨)
public UserDto findUser(Long id) {
User u = userRepo.findById(id).orElseThrow();
return new UserDto(u.getId(), u.getName(), u.getOrders().stream()...);
}
10. ClassNotFoundException / 起動失敗
Caused by: java.lang.ClassNotFoundException: javax.servlet.Filter
Spring Boot 3.x で javax.* → jakarta.* に変わったため、古いライブラリが原因のことが多いです。依存ライブラリを Spring Boot 3 対応版に更新します。
FAQ
Q: スタックトレースが長すぎて読めない
A: 下から読むのがコツ。 Caused by: 連鎖の最深部に真の原因があります。Spring 起動ログには「Action:」セクションで対処策が書かれていることも多いです。
Q: @Autowired と コンストラクタ注入、どちらを使う?
A: コンストラクタ注入を推奨。final にできて不変・テスタブル・循環依存を早期検知。Lombok @RequiredArgsConstructor で簡潔に書けます。
Q: 開発時に詳細ログを出したい
A: application.yml に logging.level.org.springframework=DEBUG を追加。Auto Configuration の決定理由も --debug オプションで見られます。