Skip to content

よくあるエラーとトラブルシューティング

よくあるエラーとトラブルシューティング

Section titled “よくあるエラーとトラブルシューティング”

Spring Boot開発でよく遭遇するエラーとその解決方法について、実践的な対処法を解説します。

エラー1: パッケージが見つからない

Section titled “エラー1: パッケージが見つからない”

エラーメッセージ:

package com.example does not exist

原因:

  • パッケージ構造が正しくない
  • インポート文が間違っている

解決方法:

// 正しいパッケージ宣言
package com.example.myapp.service;
// 正しいインポート
import com.example.myapp.model.User;
import com.example.myapp.repository.UserRepository;

確認事項:

  • ファイルのパスがパッケージ名と一致しているか
  • src/main/java/com/example/myapp/service/UserService.javapackage com.example.myapp.service;

エラー2: シンボルが見つからない

Section titled “エラー2: シンボルが見つからない”

エラーメッセージ:

cannot find symbol: class UserRepository

原因:

  • クラスが存在しない
  • インポートが不足している
  • Lombokのアノテーションが正しく処理されていない

解決方法:

// 1. インポートを確認
import com.example.myapp.repository.UserRepository;
// 2. Lombokを使用している場合、IDEでアノテーション処理を有効化
// IntelliJ IDEA: Settings → Build → Compiler → Annotation Processors → Enable annotation processing
// 3. Maven/Gradleでクリーンビルド
// Maven
./mvnw clean compile
// Gradle
./gradlew clean build

エラー3: Beanが見つからない(NoSuchBeanDefinitionException)

Section titled “エラー3: Beanが見つからない(NoSuchBeanDefinitionException)”

エラーメッセージ:

No qualifying bean of type 'com.example.myapp.service.UserService' available

原因:

  • @Service@Componentなどのアノテーションが不足
  • コンポーネントスキャンの対象外
  • プロファイルが一致しない

解決方法:

// 1. アノテーションを追加
@Service // または @Component
public class UserService {
// ...
}
// 2. コンポーネントスキャンの範囲を確認
@SpringBootApplication
@ComponentScan(basePackages = "com.example.myapp")
public class MyAppApplication {
public static void main(String[] args) {
SpringApplication.run(MyAppApplication.class, args);
}
}
// 3. プロファイルを確認
@Profile("dev") // プロファイルが一致しているか確認
@Service
public class DevUserService {
// ...
}

エラー4: 循環依存(Circular Dependency)

Section titled “エラー4: 循環依存(Circular Dependency)”

エラーメッセージ:

The dependencies of some of the beans in the application context form a cycle

原因:

  • クラスAがクラスBに依存し、クラスBがクラスAに依存している

解決方法:

// 悪い例: 循環依存
@Service
public class UserService {
@Autowired
private OrderService orderService; // UserService → OrderService
}
@Service
public class OrderService {
@Autowired
private UserService userService; // OrderService → UserService(循環)
}
// 解決方法1: コンストラクタインジェクション + @Lazy
@Service
public class UserService {
private final OrderService orderService;
public UserService(@Lazy OrderService orderService) {
this.orderService = orderService;
}
}
// 解決方法2: インターフェースを使用
public interface UserServiceInterface {
User findById(Long id);
}
@Service
public class UserService implements UserServiceInterface {
// ...
}
@Service
public class OrderService {
private final UserServiceInterface userService; // インターフェースに依存
public OrderService(UserServiceInterface userService) {
this.userService = userService;
}
}
// 解決方法3: アーキテクチャの見直し(推奨)
// 共通のサービス層を作成するか、イベント駆動アーキテクチャを使用

エラー5: トランザクションが機能しない

Section titled “エラー5: トランザクションが機能しない”

エラーメッセージ:

Transaction is not active

原因:

  • @Transactionalが適用されていない
  • 同じクラス内のメソッド呼び出し
  • 例外がキャッチされている

解決方法:

// 悪い例: 同じクラス内のメソッド呼び出し
@Service
public class UserService {
public void createUser(UserCreateRequest request) {
saveUser(request); // @Transactionalが効かない
}
@Transactional
public void saveUser(UserCreateRequest request) {
userRepository.save(new User());
}
}
// 解決方法1: メソッドを統合
@Service
public class UserService {
@Transactional
public void createUser(UserCreateRequest request) {
userRepository.save(new User());
}
}
// 解決方法2: 自己注入(非推奨)
@Service
public class UserService {
@Autowired
private UserService self; // プロキシ経由で呼び出す
public void createUser(UserCreateRequest request) {
self.saveUser(request); // プロキシ経由なので@Transactionalが効く
}
@Transactional
public void saveUser(UserCreateRequest request) {
userRepository.save(new User());
}
}
// 解決方法3: 例外を再スロー
@Service
public class UserService {
@Transactional
public void createUser(UserCreateRequest request) {
try {
userRepository.save(new User());
} catch (Exception e) {
log.error("Error", e);
throw e; // 例外を再スローしないとロールバックされない
}
}
}

エラー6: テーブルが見つからない

Section titled “エラー6: テーブルが見つからない”

エラーメッセージ:

Table 'mydb.users' doesn't exist

原因:

  • テーブルが作成されていない
  • ddl-auto設定が間違っている
  • マイグレーションが実行されていない

解決方法:

application.properties
# 開発環境: 自動でテーブルを作成
spring.jpa.hibernate.ddl-auto=create-drop
# 本番環境: マイグレーションツールを使用
spring.jpa.hibernate.ddl-auto=validate
# Flywayを使用する場合
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration
// エンティティクラスを確認
@Entity
@Table(name = "users") // テーブル名を明示的に指定
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// ...
}

エラー7: カラムが見つからない

Section titled “エラー7: カラムが見つからない”

エラーメッセージ:

Column 'user_name' doesn't exist

原因:

  • カラム名の不一致
  • @Columnアノテーションの設定ミス

解決方法:

@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// カラム名を明示的に指定
@Column(name = "user_name", nullable = false, length = 100)
private String name;
// スネークケースとキャメルケースの変換設定
// application.properties
// spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
}

エラーメッセージ:

Connection refused. Check that the hostname and port are correct

原因:

  • データベースサーバーが起動していない
  • 接続情報が間違っている
  • ファイアウォールの設定

解決方法:

# 接続情報を確認
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=myuser
spring.datasource.password=mypassword
# 接続タイムアウトを設定
spring.datasource.hikari.connection-timeout=30000
Terminal window
# データベースサーバーの状態を確認
# PostgreSQL
pg_isready -h localhost -p 5432
# MySQL
mysqladmin ping -h localhost -u root -p

エラーメッセージ:

404 Not Found

原因:

  • URLパスが間違っている
  • コントローラーのマッピングが間違っている
  • コンテキストパスの設定

解決方法:

// コントローラーのマッピングを確認
@RestController
@RequestMapping("/api/users") // ベースパス
public class UserController {
@GetMapping("/{id}") // GET /api/users/{id}
public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
// ...
}
}
// application.propertiesでコンテキストパスを確認
server.servlet.context-path=/api

デバッグ方法:

@RestController
@RequestMapping("/api/users")
@Slf4j
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
log.info("GET /api/users/{} called", id); // ログで確認
// ...
}
}

エラーメッセージ:

400 Bad Request

原因:

  • リクエストボディの形式が間違っている
  • バリデーションエラー
  • 必須パラメータが不足

解決方法:

// バリデーションエラーの詳細を確認
@RestController
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationException(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error -> {
errors.put(error.getField(), error.getDefaultMessage());
});
ErrorResponse errorResponse = new ErrorResponse(
"Validation failed", errors);
return ResponseEntity.badRequest().body(errorResponse);
}
}
// DTOクラスでバリデーションを確認
public class UserCreateRequest {
@NotBlank(message = "名前は必須です")
@Size(max = 100, message = "名前は100文字以内で入力してください")
private String name;
@NotBlank(message = "メールアドレスは必須です")
@Email(message = "有効なメールアドレスを入力してください")
private String email;
}

エラーメッセージ:

500 Internal Server Error

原因:

  • 未処理の例外
  • NullPointerException
  • データベースエラー

解決方法:

// グローバル例外ハンドラーを実装
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception ex) {
log.error("Unexpected error occurred", ex);
ErrorResponse errorResponse = new ErrorResponse(
"Internal server error",
ex.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(errorResponse);
}
@ExceptionHandler(NullPointerException.class)
public ResponseEntity<ErrorResponse> handleNullPointerException(
NullPointerException ex) {
log.error("NullPointerException occurred", ex);
ErrorResponse errorResponse = new ErrorResponse(
"Null pointer exception",
"A required value is null");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(errorResponse);
}
}

エラーメッセージ:

java.lang.OutOfMemoryError: Java heap space

原因:

  • メモリ不足
  • 大量のデータ処理
  • メモリリーク

解決方法:

Terminal window
# JVMのメモリ設定を変更
java -Xms512m -Xmx2048m -jar myapp.jar
# または、application.propertiesで設定(Spring Boot)
spring.jvm.arguments=-Xms512m -Xmx2048m
// 大量データの処理を最適化
@Service
public class UserService {
// 悪い例: 全件取得
public List<User> getAllUsers() {
return userRepository.findAll(); // メモリ不足の原因
}
// 良い例: ページネーション
public Page<User> getAllUsers(Pageable pageable) {
return userRepository.findAll(pageable);
}
// 良い例: ストリーム処理
@Transactional(readOnly = true)
public void processAllUsers() {
try (Stream<User> users = userRepository.findAllStream()) {
users.forEach(this::processUser);
}
}
}

# デバッグ用にログレベルを変更
logging.level.com.example.myapp=DEBUG
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
@Service
@Slf4j
public class UserService {
public User createUser(UserCreateRequest request) {
log.debug("Creating user: {}", request); // ブレークポイントを設定
// 変数の値を確認
User user = new User();
user.setName(request.getName());
return userRepository.save(user);
}
}
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception ex) {
// スタックトレースをログに出力
log.error("Exception occurred", ex);
// 開発環境ではスタックトレースを含める
String message = ex.getMessage();
if (isDevEnvironment()) {
message += "\n" + getStackTrace(ex);
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ErrorResponse("Error", message));
}
}

Jakarta EE(旧Java EE)への移行に伴うエラーと解決方法について解説します。

エラー13: パッケージjavaxが見つからない

Section titled “エラー13: パッケージjavaxが見つからない”

エラーメッセージ:

package javax.persistence does not exist
package javax.validation does not exist
package javax.servlet does not exist

原因:

  • Spring Boot 3.x以降では、javax.*パッケージがjakarta.*に変更された
  • 古いコードやライブラリがjavax.*を使用している
  • 依存関係のバージョンがJakarta EEに対応していない

解決方法:

1. インポート文を修正(javax → jakarta):

// ❌ 古いコード(javax.*)
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.validation.constraints.NotNull;
import javax.servlet.http.HttpServletRequest;
// ✅ 新しいコード(jakarta.*)
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.GeneratedValue;
import jakarta.validation.constraints.NotNull;
import jakarta.servlet.http.HttpServletRequest;

2. 主なパッケージ名の変更:

旧パッケージ(javax.*)新パッケージ(jakarta.*)
javax.persistence.*jakarta.persistence.*
javax.validation.*jakarta.validation.*
javax.servlet.*jakarta.servlet.*
javax.annotation.*jakarta.annotation.*
javax.transaction.*jakarta.transaction.*
javax.enterprise.*jakarta.enterprise.*

3. 依存関係の更新:

pom.xml
<dependencies>
<!-- Spring Boot 3.x以降は自動的にJakarta EEを使用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.1.0</version>
</dependency>
<!-- JPA(Jakarta Persistence) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>3.1.0</version>
</dependency>
<!-- Validation(Jakarta Validation) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web:3.1.0'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.1.0'
implementation 'org.springframework.boot:spring-boot-starter-validation:3.1.0'
}

エラー14: クラスが見つからない(NoClassDefFoundError)

Section titled “エラー14: クラスが見つからない(NoClassDefFoundError)”

エラーメッセージ:

java.lang.NoClassDefFoundError: javax/persistence/Entity
java.lang.NoClassDefFoundError: javax/validation/constraints/NotNull

原因:

  • 実行時にJakarta EEのクラスが見つからない
  • クラスパスにJakarta EEのライブラリが含まれていない
  • 古いバージョンのライブラリが混在している

解決方法:

1. 依存関係の確認:

Terminal window
# Maven: 依存関係ツリーを確認
./mvnw dependency:tree | grep -i jakarta
./mvnw dependency:tree | grep -i javax
# Gradle: 依存関係を確認
./gradlew dependencies | grep -i jakarta
./gradlew dependencies | grep -i javax

2. 古いライブラリの除外:

<!-- Maven: 古いjavax.*を使用するライブラリを除外 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>old-library</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
</exclusion>
</exclusions>
</dependency>

3. クリーンビルド:

Terminal window
# Maven
./mvnw clean install
# Gradle
./gradlew clean build

エラー15: アノテーションが見つからない

Section titled “エラー15: アノテーションが見つからない”

エラーメッセージ:

cannot find symbol: @Entity
cannot find symbol: @NotNull
cannot find symbol: @Valid

原因:

  • インポート文がjavax.*のまま
  • Jakarta EEの依存関係が不足している
  • IDEのキャッシュが古い

解決方法:

1. インポート文を修正:

// ❌ 古いコード
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import javax.validation.Valid;
// ✅ 新しいコード
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.Valid;
@Entity
public class User {
@Id
private Long id;
@NotNull
private String name;
}

2. IDEのキャッシュをクリア:

IntelliJ IDEA:

File → Invalidate Caches / Restart → Invalidate and Restart

Eclipse:

Project → Clean → Clean all projects

3. 依存関係の確認:

<!-- Maven: Jakarta Persistence API -->
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- Jakarta Validation API -->
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.2</version>
</dependency>

エラー16: Spring Boot 2.xから3.xへの移行エラー

Section titled “エラー16: Spring Boot 2.xから3.xへの移行エラー”

エラーメッセージ:

The package javax.persistence is accessible from more than one module

原因:

  • Spring Boot 2.xと3.xの依存関係が混在している
  • モジュールパスでjavax.*とjakarta.*が競合している

解決方法:

1. Spring Bootのバージョンを統一:

pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version> <!-- 3.x系に統一 -->
</parent>

2. 移行チェックリスト:

// ✅ 移行が必要な主な変更点
// 1. インポート文の変更
// javax.* → jakarta.*
// 2. アノテーションの変更
// @javax.persistence.Entity → @jakarta.persistence.Entity
// @javax.validation.NotNull → @jakarta.validation.NotNull
// 3. 設定ファイルの変更
// javax.persistence.* → jakarta.persistence.*
// 4. 依存関係の更新
// spring-boot-starter-web:2.7.x → 3.1.0
// spring-boot-starter-data-jpa:2.7.x → 3.1.0

3. 自動移行ツールの使用:

Terminal window
# OpenRewriteを使用した自動移行
# https://docs.openrewrite.org/recipes/java/spring/boot3/upgradespringboot_3_0
# Maven
./mvnw org.openrewrite.maven:rewrite-maven-plugin:run \
-Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0

エラー17: バリデーションアノテーションが動作しない

Section titled “エラー17: バリデーションアノテーションが動作しない”

エラーメッセージ:

@NotNull annotation is not recognized
@Valid annotation is not recognized

原因:

  • javax.validation.*からjakarta.validation.*への移行が不完全
  • バリデーションの依存関係が不足している

解決方法:

1. インポート文を修正:

// ❌ 古いコード
import javax.validation.constraints.NotNull;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Email;
import javax.validation.Valid;
// ✅ 新しいコード
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Email;
import jakarta.validation.Valid;
public class UserCreateRequest {
@NotNull
@NotBlank
private String name;
@Email
private String email;
}

2. 依存関係の確認:

<!-- Maven: Jakarta Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.1.0</version>
</dependency>

3. コントローラーでの使用:

@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public ResponseEntity<UserDTO> createUser(
@Valid @RequestBody UserCreateRequest request) { // @Validはjakarta.validation.Valid
// ...
}
}

エラー18: JPAエンティティが認識されない

Section titled “エラー18: JPAエンティティが認識されない”

エラーメッセージ:

Not a managed type: class com.example.User

原因:

  • javax.persistence.*からjakarta.persistence.*への移行が不完全
  • エンティティのアノテーションが古いパッケージを使用している

解決方法:

1. エンティティクラスのインポートを修正:

// ❌ 古いコード
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Column;
// ✅ 新しいコード
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Column;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
}

2. application.propertiesの確認:

# JPA設定(Jakarta Persistence)
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

Jakarta EEへの移行時に確認すべき項目:

  • すべてのjavax.*インポートをjakarta.*に変更
  • Spring Boot 3.x以降を使用しているか
  • 依存関係がJakarta EEに対応しているか
  • IDEのキャッシュをクリアしたか
  • クリーンビルドを実行したか
  • テストが正常に動作するか

主な変更点の一覧:

変更前(javax.*)変更後(jakarta.*)
javax.persistence.Entityjakarta.persistence.Entity
javax.persistence.Idjakarta.persistence.Id
javax.validation.NotNulljakarta.validation.NotNull
javax.validation.Validjakarta.validation.Valid
javax.servlet.http.HttpServletRequestjakarta.servlet.http.HttpServletRequest
javax.annotation.PostConstructjakarta.annotation.PostConstruct
javax.transaction.Transactionaljakarta.transaction.Transactional

よくあるエラーと解決方法:

  1. コンパイルエラー: パッケージ構造とインポートを確認
  2. Beanエラー: アノテーションとコンポーネントスキャンを確認
  3. 循環依存: アーキテクチャの見直しまたは@Lazyを使用
  4. トランザクション: メソッド呼び出し方法と例外処理を確認
  5. データベースエラー: 接続情報とテーブル定義を確認
  6. HTTPエラー: マッピングとバリデーションを確認
  7. パフォーマンス: メモリ設定とデータ処理方法を最適化
  8. Jakarta移行エラー: javax.*jakarta.*に変更、依存関係を更新

適切なエラーハンドリングとデバッグテクニックにより、問題を迅速に解決できます。