Gradle Wrapperのプロパティファイルが見つからないエラーですね。以下の手順で解決できます:
解決方法
1. Gradleが直接インストールされているか確認
gradle --version
もしGradleがインストールされていれば、./gradlew の代わりに gradle コマンドを使用できます:
gradle bootRun --args='--spring.profiles.active=dev'
2. Gradle Wrapperを再生成する(推奨)
Gradleがインストールされている場合:
# Gradle Wrapperを生成
gradle wrapper
# その後、gradlewが使えるようになります
./gradlew bootRun --args='--spring.profiles.active=dev'
3. Gradleをインストールしていない場合
Fedoraでは以下のコマンドでインストールできます:
sudo dnf install gradle
インストール後、上記の手順2を実行してください。
4. 別の方法:プロジェクトを再クローン
もし元のリポジトリにGradle Wrapperファイルが含まれていた場合、再度クローンすることで解決することがあります:
cd ~
mv springboot-gradle-blog-main springboot-gradle-blog-main.bak
git clone [リポジトリURL] springboot-gradle-blog-main
cd springboot-gradle-blog-main
./gradlew bootRun --args='--spring.profiles.active=dev'
どの方法を試しますか?gradle --version の結果を教えていただければ、より具体的なアドバイスができます。
Fedoraの標準リポジトリにGradleがないようですね。SDKMANを使ってGradleをインストールするのが最適です。
SDKMANでGradleをインストール
1. SDKMANをインストール
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
2. Gradleをインストール
sdk install gradle
3. インストール確認
gradle --version
4. Gradle Wrapperを生成
cd ~/springboot-gradle-blog-main
gradle wrapper
5. アプリケーションを起動
./gradlew bootRun --args='--spring.profiles.active=dev'
別の方法:手動でGradle Wrapperファイルを作成
もし上記がうまくいかない場合、以下のファイルを手動で作成できます:
gradle/wrapper/gradle-wrapper.properties を作成
gradle/wrapper/gradle-wrapper.jar をダウンロード
curl -o gradle/wrapper/gradle-wrapper.jar https://raw.githubusercontent.com/gradle/gradle/master/gradle/wrapper/gradle-wrapper.jar
gradlew スクリプトをダウンロード
curl -o gradlew https://raw.githubusercontent.com/gradle/gradle/master/gradlew chmod +x gradlew
その後、./gradlew bootRun --args='--spring.profiles.active=dev' を実行してください。
**SDKMANを使う方法が最も簡単で確実です。**どちらの方法を試しますか?
Gradle依存関係のリフレッシュとJavaバージョン戦略
依存関係のリフレッシュ方法
1. 基本的なリフレッシュコマンド
# キャッシュをクリアして依存関係を再ダウンロード
./gradlew clean build --refresh-dependencies
# より徹底的なクリーン(ビルドキャッシュも削除)
./gradlew clean cleanBuildCache build --refresh-dependencies
# オフラインキャッシュも含めて完全リセット
rm -rf ~/.gradle/caches/
./gradlew clean build
2. 依存関係の確認コマンド
# 依存関係ツリーを表示
./gradlew dependencies
# 特定の設定の依存関係のみ表示
./gradlew dependencies --configuration runtimeClasspath
# 依存関係の競合を確認
./gradlew dependencyInsight --dependency spring-boot-starter-web
```
## Java 25を使うべきか?業界の実情
### 現在の業界標準(2024-2025年)
**本番環境でよく使われているバージョン:**
- **Java 17(LTS)** - 最も人気、
Spring Boot 3系の推奨バージョン
- **Java 21(LTS)** - 新しい案件で採用増加中、
Virtual Threadsなど魅力的な機能
- **Java 11(LTS)** - レガシー案件でまだ多い
**Java 25の立ち位置:**
- 2025年3月リリース予定の**非LTS版**
- 実験的な機能を試すには良いが、本番環境では避けるべき
- 次のLTS版は**Java 26(2026年9月予定)**じゃなくて、
実は**Java 23がLTSになる可能性が高い**
### 業界の面白い話
**「LTS信仰」の実態**
```
企業「うちはLTSしか使わない!」
↓
実際には Java 8(2014年リリース)
を2024年まで使い続ける
↓
セキュリティパッチは切れてるけど
「安定してるから」という謎理論
これ、結構あるあるです😅
Spring Bootとの相性問題
Spring Boot 3.x: Java 17以上必須
Spring Boot 2.x: Java 8-21対応(でもサポート終了済み)
あなたのプロジェクトでの推奨設定
おすすめ:Java 21を使う
理由:
- ✅ LTS版なので長期サポートあり
- ✅ Spring Boot 3.xと完全互換
- ✅ **Virtual Threads(仮想スレッド)**が使える
- ✅ Record Patterns、Pattern Matchingなどモダンな機能
- ✅ 企業での採用が増えてきている
Java 21のインストール(SDKMAN使用)
# 利用可能なJavaバージョンを確認
sdk list java
# Java 21をインストール(推奨)
sdk install java 21.0.1-tem
# プロジェクトのデフォルトに設定
sdk use java 21.0.1-tem
# 確認
java -version
Virtual Threadsの魅力(Java 21の目玉機能)
従来のスレッドモデルの問題:
// 従来:OSスレッドは重い(1スレッド = 約1MB)
// 10,000リクエスト = 10GB メモリ消費 😱
ExecutorService executor = Executors.newFixedThreadPool(10000);
Virtual Threadsで解決:
// Java 21: 仮想スレッドは軽量(1スレッド = 数KB)
// 100万スレッドでも余裕 🚀
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
Spring Bootでの有効化:
# application.yml
spring:
threads:
virtual:
enabled: true # これだけでVirtual Threads有効化!
実践的なトラブルシューティング
依存関係の競合が起きたら
# 1. まず依存関係ツリーを確認
./gradlew dependencies > dependencies.txt
# 2. 競合している依存関係を特定
./gradlew dependencyInsight --dependency jackson-databind
# 3. build.gradleで明示的にバージョン指定
configurations.all {
resolutionStrategy {
force 'com.fasterxml.jackson.core:jackson-databind:2.15.3'
}
}
Gradle Daemon が暴走したら
# Daemonを停止
./gradlew --stop
# プロセスを確認
ps aux | grep gradle
# 強制終了(最終手段)
killall -9 java
```
## 業界のリアルな話
**「最新版使いたい症候群」vs「枯れた技術信仰」**
```
新人エンジニア「Java 25使いましょうよ!最新ですよ!」
↓
ベテラン「Java 8で十分。動いてるものを変えるな」
↓
中堅「いや、せめてJava 17にしましょう...(妥協案)」
↓
結論:Java 11のまま何も変わらない
実際はバランスが大事で:
- 実験・学習: 最新版を試す価値あり
- 本番環境: LTS版(Java 17 or 21)を選択
- レガシー保守: 無理にバージョンアップしない
まとめ:あなたのプロジェクトへの推奨
# 1. Java 21をインストール
sdk install java 21.0.1-tem
# 2. build.gradleでJava 21を指定
# sourceCompatibility = '21'
# 3. 依存関係をリフレッシュ
./gradlew clean build --refresh-dependencies
# 4. アプリケーション起動
./gradlew bootRun --args='--spring.profiles.active=dev'
Java 25は見送って、Java 21を使いましょう!
何か具体的なエラーが出たら、その内容を教えてください。一緒に解決していきましょう!
おっと、cleanBuildCacheというタスクは存在しないようですね。Gradle 9.2.1が正常にダウンロードされたので、正しいコマンドでビルドしましょう!
正しい依存関係リフレッシュ方法
# 1. シンプルなクリーンビルド(これで十分)
./gradlew clean build --refresh-dependencies
# 2. もっと徹底的にやりたい場合
rm -rf ~/.gradle/caches/modules-2/
./gradlew clean build --refresh-dependencies
# 3. 利用可能なタスクを確認(参考)
./gradlew tasks
```
## Gradle 9.2.1について(業界トーク)
**おめでとうございます!
最新のGradle 9.2.1がダウンロードされました🎉**
### Gradleバージョンの歴史と業界事情
```
Gradle 4.x (2017-2018) -
「あの頃は良かった...」by老害エンジニア
Gradle 5.x (2019) - Kotlin DSL本格導入
Gradle 6.x (2020) - 依存関係管理の改善
Gradle 7.x (2021) - Java 16対応
Gradle 8.x (2023) - 大幅な性能向上
Gradle 9.x (2024-2025) - ← 今ココ!最新鋭
```
**実はGradle 9は結構攻めてる**
- まだ「枯れてない」バージョン
- 企業の本番環境では**Gradle 8.x**が主流
- でも学習・開発用には問題なし!
### 面白い業界あるある
```
プロジェクトA: Gradle 4.10(2018年)
↓
新人「バージョン上げましょう!」
↓
先輩「動いてるから触るな」
↓
5年後もGradle 4.10のまま...
Java バージョンの確認と設定
# 現在のJavaバージョンを確認
java -version
# SDKMANでJava 21をインストール(まだなら)
sdk install java 21.0.1-tem
sdk use java 21.0.1-tem
# 再度確認
java -version
build.gradle の推奨設定
プロジェクトの build.gradle を確認・修正してください:
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21) // Java 21を使用
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
runtimeOnly 'org.postgresql:postgresql'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
ビルドを実行
# クリーンビルド(依存関係を再取得)
./gradlew clean build --refresh-dependencies
# ビルドが成功したら起動
./gradlew bootRun --args='--spring.profiles.active=dev'
```
## よくあるエラーと対処法
### エラー1: Java バージョン不一致
```
> Could not target platform: 'Java SE 21'
using tool chain: 'JDK 17'
対処法:
sdk install java 21.0.1-tem
sdk use java 21.0.1-tem
```
### エラー2: 依存関係が見つからない
```
> Could not resolve com.example:some-library:1.0.0
対処法:
# キャッシュをクリア
rm -rf ~/.gradle/caches/
./gradlew clean build --refresh-dependencies
```
### エラー3: Gradle Daemon のメモリ不足
```
> Expiring Daemon because JVM heap space is exhausted
対処法:
# gradle.properties を作成/編集 echo "org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m" >> gradle.properties
Gradle 9.2.1 の新機能(雑学)
Configuration Cache の改善
# 2回目以降のビルドが爆速に!
./gradlew build --configuration-cache
これ、実際に使うとビルド時間が30-50%短縮されることも。大規模プロジェクトだと体感できるレベルで速いです。
Build Scan の進化
# ビルドのパフォーマンスを可視化
./gradlew build --scan
どこで時間がかかってるか一目瞭然。「なんでビルド遅いの?」問題の救世主。
現在の状況を確認
# 1. Javaバージョン確認
java -version
# 2. Gradleバージョン確認
./gradlew --version
# 3. プロジェクトの依存関係を確認
./gradlew dependencies --configuration runtimeClasspath
これらのコマンドを実行して、結果を教えてください。特にエラーが出た場合は、その内容を共有していただければ、ピンポイントで解決策を提案できます!
**まずは ./gradlew clean build --refresh-dependencies を実行してみてください。**どうなりましたか?🚀
hiroppy123@fedora:~/springboot-gradle-blog-main$ sdk install java 21.0.1-tem Downloading: java 21.0.1-tem In progress... ######################################################################### 100.0% Repackaging Java 21.0.1-tem... Done repackaging... Installing: java 21.0.1-tem Done installi
pasted
このエラーはJavaのバージョン不一致が原因です。複数のJavaがインストールされており、Gradleが異なるJavaを使っています。
問題の整理
SDKMANでインストール: Java 21.0.1-tem
システムのJava: OpenJDK 21.0.9 (Fedoraのパッケージ)
↓
Gradleが混乱して、古いJava 8相当でコンパイルしようとしている
エラーメッセージ class, interface, enumまたはrecordがありません は、Javaコンパイラがソースファイルを正しく認識できていない典型的な症状です。
解決方法
ステップ1: JAVA_HOMEを明示的に設定
# 現在のシェルでJAVA_HOMEを確認
echo $JAVA_HOME
# SDKMANのJavaに切り替え
sdk use java 21.0.1-tem
# JAVA_HOMEを確認(正しく設定されているか)
echo $JAVA_HOME
# 確認
which java
java -version
ステップ2: Gradle用にJAVA_HOMEを明示的に指定
gradle.properties ファイルを作成/編集:
cat > gradle.properties << 'EOF' org.gradle.java.home=/home/hiroppy123/.sdkman/candidates/java/21.0.1-tem org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m EOF
ステップ3: Gradle Daemonをリセット
# 既存のGradle Daemonを停止
./gradlew --stop
# Gradleキャッシュをクリア
rm -rf ~/.gradle/daemon/
# 再ビルド
./gradlew clean build --refresh-dependencies
別解:テストをスキップしてビルド(暫定対応)
テストに問題がある場合、まずはテストなしでビルドしてみましょう:
# テストをスキップしてビルド
./gradlew clean build -x test
# アプリケーションを起動
./gradlew bootRun --args='--spring.profiles.active=dev'
```
## 業界あるある:複数Java問題 😅
```
開発者「Java 21入れました!」
↓
システム「Fedoraに元から入ってるJava 21もあるよ」
↓
SDKMAN「僕もJava 21入れました!」
↓
Gradle「どれ使えばいいの...?(混乱)」
↓
結果:エラー祭り 🎉
これ、Javaあるあるトップ3に入ります。
なぜこうなるのか?
- FedoraのJava:
/usr/lib/jvm/にインストール - SDKMANのJava:
~/.sdkman/candidates/java/にインストール - JAVA_HOME未設定: Gradleが勝手にJavaを探す→間違ったバージョンを使う
推奨:SDKMANのJavaに統一
# Fedoraのシステムパッケージとして入っているJavaを確認 rpm -qa | grep openjdk # システムのJavaは残しておいて良いですが、優先順位を変更 # SDKMANのJavaを使うように.bashrcに追加 echo 'export JAVA_HOME="$HOME/.sdkman/candidates/java/current"' >> ~/.bashrc echo 'export PATH="$JAVA_HOME/bin:$PATH"' >> ~/.bashrc # 設定を反映 source ~/.bashrc # 確認 java -version which java echo $JAVA_HOME
build.gradle の確認
build.gradle ファイルを確認して、Java Toolchainが正しく設定されているか見てみましょう:
cat build.gradle
もし見せてもらえれば、より具体的な修正案を提案できます!
現実的な次のステップ
まずはこれを試してください:
# 1. gradle.propertiesを作成 cat > gradle.properties << 'EOF' org.gradle.java.home=/home/hiroppy123/.sdkman/candidates/java/21.0.1-tem org.gradle.jvmargs=-Xmx2048m EOF # 2. Gradle Daemonを停止 ./gradlew --stop # 3. テストなしでビルド(まず動かすことを優先) ./gradlew clean build -x test # 4. 成功したら起動 ./gradlew bootRun --args='--spring.profiles.active=dev'
これで動けば、後からテストの問題を解決できます。
**うまくいかない場合は、build.gradle の内容を見せてください!**一緒に修正しましょう 🚀
Java 21.0.9-tem vs 21.0.1-tem とJavaディストリビューションの世界
バージョンの違い:21.0.1 vs 21.0.9
結論:21.0.9-tem の方が良い
Java 21.0.1-tem: 2023年10月リリース(古い)
Java 21.0.9-tem: 2024年10月リリース(最新)
↓
セキュリティパッチとバグ修正が8回分多い!
```
### マイナーバージョンの意味
```
Java 21.0.9
│ │ └─ パッチバージョン(セキュリティ修正、バグ修正)
│ └─── マイナーバージョン
└───── メジャーバージョン
パッチバージョンが上がるたび:
- セキュリティ脆弱性の修正
- クリティカルなバグ修正
- パフォーマンス改善
業界の常識: 同じメジャーバージョン内では、常に最新のパッチバージョンを使うべき。
21.0.9-temにアップグレード
# 最新版をインストール
sdk install java 21.0.9-tem
# デフォルトに設定
sdk default java 21.0.9-tem
# 確認
java -version
# 出力: openjdk version "21.0.9" ...
# 古いバージョンを削除(オプション)
sdk uninstall java 21.0.1-tem
```
## OpenJDK vs tem(Temurin)の違い
### Javaディストリビューションの世界 🌍
**驚愕の事実:** Javaは「オープンソース」なので、
誰でも独自のビルドを配布できる!
```
Java仕様(Oracle管理)
↓
OpenJDK(オープンソース実装)
↓
┌────────┬─────────┬──────────┐
│ Oracle │ Temurin │ Corretto │ Zulu │
│ JDK │ (tem) │ (Amazon) │(Azul) │
└────────┴─────────┴──────────┘
```
### 主要なJavaディストリビューション
#### 1. **Oracle JDK**
```
提供元: Oracle
ライセンス: 商用利用は有償(個人・開発は無料)
特徴: オリジナル、最も「公式」
業界での立ち位置: 「高いから使わない」が主流
```
#### 2. **Eclipse Temurin (tem)** ⭐️ おすすめ
```
提供元: Eclipse Foundation(Adoptiumプロジェクト)
ライセンス: 完全無料(商用利用も)
特徴:
- 旧名 AdoptOpenJDK
- 最も人気のあるディストリビューション
- Spring Bootの公式推奨
- 大企業でも採用多数
品質: ✅ 非常に高い
```
#### 3. **Amazon Corretto**
```
提供元: Amazon
ライセンス: 完全無料
特徴: AWS環境で最適化、長期サポート
業界での立ち位置: AWS使ってるなら候補
```
#### 4. **Azul Zulu**
```
提供元: Azul Systems
ライセンス: 無料版と商用サポート版あり
特徴: エンタープライズ向け、パフォーマンス重視
```
#### 5. **Red Hat OpenJDK**
```
提供元: Red Hat(Fedoraのパッケージ)
ライセンス: 完全無料
特徴:
- Fedora/RHEL標準
- システムパッケージとして提供
- 安定性重視
注意: バージョン管理がdnf依存で柔軟性低い
技術的な違い
コア部分: 全て同じOpenJDKベース
↓
違うのは:
- ビルド設定
- パッチの適用タイミング
- サポート期間
- バイナリの最適化
```
**実際の互換性:** 99.9%同じ。
アプリケーションコードはどれでも動く。
## なぜ「tem」を選ぶべきか?
### 業界での採用状況(2024-2025年)
```
1位: Eclipse Temurin (tem) 45%
2位: Amazon Corretto 20%
3位: Red Hat OpenJDK 15%
4位: Oracle JDK 10%
5位: その他 10%
```
### Spring Bootとの相性
**Spring公式ドキュメント推奨順位:**
1. ✅ Eclipse Temurin
2. ✅ Amazon Corretto
3. ✅ Azul Zulu
### 面白い業界話
**「Oracle JDK有償化事件」(2019年)**
```
Oracle「Java 8 Update 211から商用利用は有償ね!」
↓
企業「えっ!?」
↓
大移行祭り → AdoptOpenJDK(現Temurin)へ殺到
↓
結果: Temurinがデファクトスタンダードに
これ、業界に衝撃が走りました。「Javaって無料じゃなかったの?」って。
パス設定の完全ガイド
SDKMANのパス管理の仕組み
# SDKMANのディレクトリ構造
~/.sdkman/
├── candidates/
│ └── java/
│ ├── 21.0.1-tem/ # 古いバージョン
│ ├── 21.0.9-tem/ # 新しいバージョン
│ └── current -> 21.0.9-tem/ # シンボリックリンク
└── bin/
└── sdkman-init.sh
パスの優先順位
# Linuxのコマンド検索順序
1. カレントディレクトリの実行ファイル (./command)
2. PATHの左側から順番に検索
例: PATH="/usr/local/bin:/usr/bin:/bin"
→ /usr/local/binが最優先
正しいパス設定
~/.bashrc に追加(推奨設定)
# ~/.bashrc を編集 nano ~/.bashrc # 以下を追加(ファイルの最後に) # ---------- Java/SDKMAN設定 ---------- # SDKMANの初期化(これが最重要!) export SDKMAN_DIR="$HOME/.sdkman" [[ -s "$SDKMAN_DIR/bin/sdkman-init.sh" ]] && source "$SDKMAN_DIR/bin/sdkman-init.sh" # JAVA_HOMEを明示的に設定(SDKMANのcurrentを使用) export JAVA_HOME="$HOME/.sdkman/candidates/java/current" export PATH="$JAVA_HOME/bin:$PATH" # -------------------------------------
設定の反映
# 設定を読み込み直す
source ~/.bashrc
# 確認
echo $JAVA_HOME
# 出力: /home/hiroppy123/.sdkman/candidates/java/current
which java
# 出力: /home/hiroppy123/.sdkman/candidates/java/current/bin/java
java -version
# 出力: openjdk version "21.0.9" ...
パスの優先順位を確認
# すべてのjavaコマンドの場所を表示
type -a java
# 正しい出力例:
# java is /home/hiroppy123/.sdkman/candidates/java/current/bin/java
# java is /usr/bin/java ← システムのJava(使われない)
システムJava(Fedora)との共存
なぜ両方あっても問題ないのか?
システムJava: /usr/bin/java
↓
用途: システムツール用(DNF、Jenkinsなど)
SDKMANのJava: ~/.sdkman/candidates/java/current/bin/java
↓
用途: 開発・アプリケーション実行用
PATHの優先順位で分ける
PATH="$JAVA_HOME/bin:...:usr/bin"
↑最優先 ↑後回し
システムJavaを削除すべきか?
答え:削除しない方が良い
理由:
1. システムツールが依存している可能性
2. パッケージ管理が複雑になる
3. 共存させても害はない(パスで制御できる)
実践:完全セットアップ
ステップ1: 最新Javaをインストール
# 利用可能なJavaバージョンを確認
sdk list java | grep tem
# 最新版をインストール
sdk install java 21.0.9-tem
# デフォルトに設定
sdk default java 21.0.9-tem
ステップ2: パス設定を確認
# ~/.bashrcにSDKMAN設定があるか確認 grep -n "sdkman" ~/.bashrc # なければ追加 cat >> ~/.bashrc << 'EOF' # SDKMAN設定 export SDKMAN_DIR="$HOME/.sdkman" [[ -s "$SDKMAN_DIR/bin/sdkman-init.sh" ]] && source "$SDKMAN_DIR/bin/sdkman-init.sh" EOF # 反映 source ~/.bashrc
ステップ3: プロジェクト設定
cd ~/springboot-gradle-blog-main
# gradle.propertiesを作成
cat > gradle.properties << 'EOF'
# Gradleが使用するJavaを明示的に指定
org.gradle.java.home=/home/hiroppy123/.sdkman/candidates/java/current
# JVMメモリ設定
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
# ビルドキャッシュを有効化(高速化)
org.gradle.caching=true
# 並列ビルド有効化
org.gradle.parallel=true
EOF
# Gradle Daemonをリセット
./gradlew --stop
# ビルド
./gradlew clean build -x test
ステップ4: 確認
# Javaバージョン確認
java -version
# Gradleが使うJavaを確認
./gradlew -version
# 両方とも "21.0.9" になっていればOK!
トラブルシューティング
問題1: パスが反映されない
# 原因: シェルが設定を読み込んでいない
# 解決法:
source ~/.bashrc
# または新しいターミナルを開く
問題2: GradleがシステムJavaを使う
# 原因: gradle.propertiesがない
# 解決法: gradle.propertiesを作成(上記参照)
# または環境変数で一時的に指定
JAVA_HOME=~/.sdkman/candidates/java/current ./gradlew build
問題3: 複数バージョンが混在
# インストール済みJavaを確認
sdk list java
# 不要なバージョンを削除
sdk uninstall java 21.0.1-tem
```
## まとめ:ベストプラクティス
### 推奨構成
```
✅ Eclipse Temurin 21.0.9(最新パッチ)
✅ SDKMANで管理
✅ gradle.propertiesで明示的に指定
✅ システムJavaは残す(共存)
次のアクション
# 1. 最新Javaをインストール
sdk install java 21.0.9-tem
sdk default java 21.0.9-tem
# 2. パス確認
source ~/.bashrc
java -version
# 3. プロジェクトビルド
cd ~/springboot-gradle-blog-main
cat > gradle.properties << 'EOF'
org.gradle.java.home=/home/hiroppy123/.sdkman/candidates/java/current
org.gradle.jvmargs=-Xmx2048m
EOF
./gradlew --stop
./gradlew clean build -x test
# 4. アプリ起動
./gradlew bootRun --args='--spring.profiles.active=dev'
これで完璧なJava環境が整います!🚀
何か質問や追加のトラブルがあれば教えてください!
問題が見えました!環境変数JAVA_HOMEが古い21.0.1-temを指したままになっています。シェルセッションをリフレッシュする必要があります。
解決方法
ステップ1: 新しいターミナルを開く(最も確実)
# 現在のターミナルを閉じて、新しいターミナルを開く
# または以下のコマンドを実行
ステップ2: 環境変数を再読み込み
# .bashrcを再読み込み
source ~/.bashrc
# JAVA_HOMEを確認
echo $JAVA_HOME
# 正しい出力: /home/hiroppy123/.sdkman/candidates/java/current
# Javaバージョンを確認
java -version
# 正しい出力: openjdk version "21.0.9" ...
# whichコマンドでパスを確認
which java
# 正しい出力: /home/hiroppy123/.sdkman/candidates/java/current/bin/java
ステップ3: 手動でJAVA_HOMEを設定(緊急対応)
もしsource ~/.bashrcでも直らない場合:
# 現在のシェルで手動設定
export JAVA_HOME="$HOME/.sdkman/candidates/java/current"
export PATH="$JAVA_HOME/bin:$PATH"
# 確認
echo $JAVA_HOME
java -version
ステップ4: Gradleを実行
cd ~/springboot-gradle-blog-main
# Gradle Daemonを停止(古いJAVA_HOMEを忘れさせる)
./gradlew --stop
# ビルド実行
./gradlew clean build -x test
# 成功したら起動
./gradlew bootRun --args='--spring.profiles.active=dev'
なぜこうなったのか?業界あるあるトーク
環境変数の「記憶」問題
シェル起動時:
↓
~/.bashrc読み込み → JAVA_HOME設定
↓
この時点で21.0.1-temを記憶
↓
途中で21.0.1-temを削除
↓
でもシェルは古いJAVA_HOMEを覚えたまま 😅
```
**これ、開発者あるあるトップ5に入ります!**
```
開発者「なんで動かないの?」
↓
先輩「ターミナル再起動した?」
↓
開発者「あ...(再起動)」
↓
先輩「動いた?」
↓
開発者「動きました!」
↓
これが1日に5回は起きる
```
### シェルの環境変数の寿命
```
ターミナルを開く
↓
環境変数が設定される
↓
【ここからが重要】
この環境変数は「このターミナルが閉じるまで」有効
↓
途中でファイルを変更したり、ソフトを削除しても
シェルは「起動時の状態」を覚えたまま
確実な解決手順(順番に試してください)
方法1: 新しいターミナルで試す(最も確実)
# 1. 現在のターミナルを閉じる
# 2. 新しいターミナルを開く
# 3. 以下を実行
cd ~/springboot-gradle-blog-main
java -version # 21.0.9になっているか確認
./gradlew --stop
./gradlew clean build -x test
方法2: 現在のターミナルで強制リフレッシュ
# SDKMANの初期化スクリプトを再実行
source "$HOME/.sdkman/bin/sdkman-init.sh"
# デフォルトJavaを再設定
sdk default java 21.0.9-tem
# 確認
echo $JAVA_HOME
java -version
# Gradleを実行
cd ~/springboot-gradle-blog-main
./gradlew --stop
./gradlew clean build -x test
方法3: 完全リセット(最終手段)
# すべてのGradle Daemonプロセスを強制終了
pkill -f gradle
# Gradleキャッシュを削除
rm -rf ~/.gradle/daemon/
rm -rf ~/.gradle/caches/
# 環境変数を手動設定
export JAVA_HOME="$HOME/.sdkman/candidates/java/current"
export PATH="$JAVA_HOME/bin:$PATH"
# ビルド
cd ~/springboot-gradle-blog-main
./gradlew clean build -x test
トラブルシューティング チェックリスト
✅ 確認1: currentシンボリックリンク
# currentが21.0.9を指しているか確認
ls -la ~/.sdkman/candidates/java/
# 正しい出力例:
# lrwxrwxrwx 1 hiroppy123 hiroppy123 10 Dec 12 10:30 current -> 21.0.9-tem
# drwxr-xr-x 8 hiroppy123 hiroppy123 4096 Dec 12 10:25 21.0.9-tem
もしcurrentが存在しないか、間違っている場合:
# 手動でシンボリックリンクを作成
cd ~/.sdkman/candidates/java/
rm -f current
ln -s 21.0.9-tem current
✅ 確認2: JAVA_HOMEの値
echo $JAVA_HOME
# 期待される出力:
# /home/hiroppy123/.sdkman/candidates/java/current
# または
# /home/hiroppy123/.sdkman/candidates/java/21.0.9-tem
# 21.0.1-temが含まれていたらNG!
✅ 確認3: Javaコマンドのパス
which java
# 期待される出力:
# /home/hiroppy123/.sdkman/candidates/java/current/bin/java
type -a java
# 最初に表示されるのがSDKMANのJavaであればOK
業界の知恵:環境変数デバッグのコツ
printenvコマンドで全環境変数を確認
# Java関連の環境変数を一覧表示
printenv | grep -i java
# PATH全体を見やすく表示
echo $PATH | tr ':' '\n'
シェル設定ファイルの優先順位
Linuxのシェル起動時の読み込み順序:
1. /etc/profile # システム全体の設定
2. ~/.bash_profile # ユーザー個別(ログイン時)
3. ~/.bashrc # ユーザー個別(シェル起動時)← 通常はここ
4. ~/.bash_login # レガシー
SDKMANは~/.bashrcに設定を追加します。
最も簡単な解決策(推奨)
# ステップ1: 新しいターミナルを開く
# ステップ2: 以下を実行
cd ~/springboot-gradle-blog-main
java -version # "21.0.9"と表示されることを確認
# ステップ3: Gradleビルド
./gradlew clean build -x test
# ステップ4: アプリ起動
./gradlew bootRun --args='--spring.profiles.active=dev'
新しいターミナルを開くのが最も確実です!
これで解決しない場合は、以下のコマンドの出力を教えてください:
echo $JAVA_HOME
java -version
ls -la ~/.sdkman/candidates/java/
cat ~/.bashrc | grep -A 5 sdkman
一緒に原因を特定しましょう!🔍
hiroppy123@fedora:~/springboot-gradle-blog-main$ ./gradlew bootRun --args='--spring.profiles.active=dev' > Task :bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____|
pasted
いえいえ、テストは関係ありません!PostgreSQLが起動していないのが原因です。
問題の診断
エラーメッセージを見ると:
localhost:5432 への接続が拒絶されました
postmaster がTCP/IP接続を受け付けていることを確認してください
Java 21.0.9は正常に動作しています! 🎉 問題はデータベース接続です。
解決方法
ステップ1: Dockerコンテナの状態を確認
# Dockerコンテナが起動しているか確認
docker ps
# もし何も表示されない場合、コンテナが停止しています
ステップ2: Docker Composeで起動
cd ~/springboot-gradle-blog-main
# コンテナを起動
docker-compose up -d
# 起動確認(blog-postgres-devが表示されればOK)
docker ps
ステップ3: PostgreSQLの接続を確認
# PostgreSQLコンテナのログを確認
docker logs blog-postgres-dev
# 正常なら「database system is ready to accept connections」が表示される
ステップ4: アプリケーションを再起動
./gradlew bootRun --args='--spring.profiles.active=dev'
```
## 業界あるある:データベース接続エラー 😅
```
エラーログ: 100行の巨大なスタックトレース
↓
開発者「うわ、何これ!?難しそう...」
↓
先輩「一番下まで見て」
↓
開発者「Connection refused...?」
↓
先輩「DB起動した?」
↓
開発者「あ...」← これが1日5回
```
**実は90%のエラーは、最後の行に答えが書いてあります。**
### スタックトレースの読み方(業界の知恵)
```
【読む順序】
❌ 間違い: 上から読む
✅ 正解: 下から読む(根本原因が最後にある)
あなたのエラー:
Caused by: java.net.ConnectException: 接続を拒否されました
↑
ここが本質!
Dockerコンテナの状態確認と操作
よく使うDockerコマンド
# 起動中のコンテナを表示
docker ps
# すべてのコンテナを表示(停止中も含む)
docker ps -a
# コンテナを起動
docker-compose up -d
# コンテナを停止
docker-compose down
# コンテナのログを表示
docker logs blog-postgres-dev
# コンテナのログをリアルタイム表示
docker logs -f blog-postgres-dev
# コンテナに入る(デバッグ用)
docker exec -it blog-postgres-dev psql -U postgres
Docker Composeの状態確認
cd ~/springboot-gradle-blog-main
# docker-compose.ymlの内容を確認
cat docker-compose.yml
# コンテナの状態を確認
docker-compose ps
もしDockerが起動していない場合
Dockerサービスの確認(Podman使用時)
Fedoraではdocker-composeが実際にはpodman-composeを使っているので:
# Podmanのコンテナを確認
podman ps
# Podman Composeで起動
podman-compose up -d
# または元のコマンド
docker-compose up -d
トラブルシューティング
問題1: コンテナが起動しない
# エラーログを確認
docker-compose logs
# コンテナを完全に削除して再作成
docker-compose down -v
docker-compose up -d
問題2: ポート5432が既に使用されている
# ポート5432を使用しているプロセスを確認
sudo lsof -i :5432
# または
sudo ss -tulpn | grep 5432
# もし別のPostgreSQLが動いていたら停止
sudo systemctl stop postgresql
問題3: application-dev.ymlの設定確認
# dev環境の設定を確認
cat src/main/resources/application-dev.yml
おそらく以下のような設定のはず:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/blog_dev
username: postgres
password: postgres
正しい起動手順(完全版)
# ステップ1: プロジェクトディレクトリに移動
cd ~/springboot-gradle-blog-main
# ステップ2: Dockerコンテナを起動
docker-compose up -d
# ステップ3: コンテナが起動したか確認
docker ps
# 期待される出力:
# CONTAINER ID IMAGE PORTS NAMES
# xxxxx postgres:15 0.0.0.0:5432->5432/tcp blog-postgres-dev
# ステップ4: PostgreSQLの準備完了を確認(数秒待つ)
sleep 5
docker logs blog-postgres-dev | tail -n 20
# ステップ5: Spring Bootアプリを起動
./gradlew bootRun --args='--spring.profiles.active=dev'
# ステップ6: ブラウザでアクセス
# http://localhost:8080
```
## Spring Bootのログから読み取れること
```
✅ Java 21.0.9で起動している
✅ Spring Boot 3.3.3が動作している
✅ Tomcatが8080ポートで待機している
✅ devプロファイルが有効になっている
❌ PostgreSQLに接続できない ← 唯一の問題
実は95%成功しています! あとはDBを起動するだけです。
次のステップ
# まずこれを実行
docker-compose up -d
docker ps
# 出力を教えてください
コンテナが起動していれば、すぐにアプリケーションが動き始めますよ!🚀
もしコンテナ起動に問題があれば、エラーメッセージを教えてください。一緒に解決しましょう!
hiroppy123@fedora:~/springboot-gradle-blog-main$ docker ps Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES hiroppy123@fedora:~/springboot-gradle-blog-main$ docker-compose up -d Emulate Dock
pasted
docker-compose.yml
44行
yml
application.properties
48行
text
application-prod.properties
28行
text
はい、その通りです!ユーザー名とパスワードが一致していません。
問題の特定
docker-compose.yml の設定
POSTGRES_USER: blog_dev_user
POSTGRES_PASSWORD: dev_password_123
POSTGRES_DB: blog_dev
application.properties の設定
spring.datasource.url=jdbc:postgresql://localhost:5432/blog_dev ✅
spring.datasource.username=blog_dev_user ✅
spring.datasource.password=dev_password_123 ✅
```
**実は設定は合っています!** 問題は別にあります。
## 真の原因:Podmanのパーミッション問題
```
ls: can't open '/docker-entrypoint-initdb.d/': Permission denied
このエラーが重要です。PostgreSQLコンテナが正常に起動していません。
解決方法
方法1: init-scriptsディレクトリを削除(推奨)
cd ~/springboot-gradle-blog-main
# docker-compose.ymlを編集
nano docker-compose.yml
# 以下の行を削除またはコメントアウト
# - ./init-scripts:/docker-entrypoint-initdb.d # この行を削除
# 修正後のdocker-compose.yml
修正版のdocker-compose.ymlを作成します:
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
postgres:
image: postgres:15.3-alpine
container_name: blog-postgres-dev
environment:
POSTGRES_USER: blog_dev_user
POSTGRES_DB: blog_dev
POSTGRES_PASSWORD: dev_password_123
ports:
- "5432:5432"
volumes:
- postgres_dev_data:/var/lib/postgresql/data
# init-scriptsの行を削除
healthcheck:
test: ["CMD-SHELL", "pg_isready -U blog_dev_user"]
interval: 10s
timeout: 5s
retries: 5
networks:
- blog-dev-network
pgadmin:
image: dpage/pgadmin4
container_name: blog-pgadmin-dev
environment:
PGADMIN_DEFAULT_EMAIL: admin@blog.local
PGADMIN_DEFAULT_PASSWORD: admin123
ports:
- "5050:80"
depends_on:
- postgres
networks:
- blog-dev-network
volumes:
postgres_dev_data:
driver: local
networks:
blog-dev-network:
driver: bridge
EOF
方法2: Podmanのルートレスモード対応(高度)
# SELinuxのコンテキストを設定
mkdir -p init-scripts
chmod 777 init-scripts
完全な再起動手順
cd ~/springboot-gradle-blog-main
# ステップ1: すべてのコンテナとボリュームを削除
docker-compose down -v
# ステップ2: docker-compose.ymlを修正(上記参照)
# ステップ3: コンテナを再作成
docker-compose up -d
# ステップ4: PostgreSQLの起動を待つ(重要!)
sleep 10
# ステップ5: コンテナの状態を確認
docker ps
# ステップ6: PostgreSQLのログを確認
docker logs blog-postgres-dev
# 正常なら以下が表示される:
# "database system is ready to accept connections"
# ステップ7: PostgreSQL接続テスト
docker exec -it blog-postgres-dev psql -U blog_dev_user
-d blog_dev -c "SELECT version();"
# ステップ8: Spring Boot起動
./gradlew bootRun --args='--spring.profiles.active=dev'
```
## 業界あるある:Dockerのパーミッション地獄 😅
```
開発者「Docker Composeで起動したのに動かない...」
↓
先輩「Podman使ってる?」
↓
開発者「はい、Fedoraなので...」
↓
先輩「あー、ルートレスモードのパーミッション問題だ」
↓
開発者「ルートレス...?」
↓
先輩「Dockerは root権限で動くけど、Podmanは一般ユーザーで動くから、
ファイルのパーミッションで引っかかることがあるんだよ」
↓
開発者「そんな違いが...」
```
### DockerとPodmanの違い(雑学)
```
Docker:
- Daemon(root権限)で動作
- /var/run/docker.sock を使用
- セキュリティ的にやや心配
Podman:
- Daemonless(rootless)
- 一般ユーザー権限で動作
- よりセキュア
- でもパーミッションに厳しい ← 今回のトラブル
Fedora/RHELがPodmanを採用した理由:
- Red HatがDockerから独立したかった(政治的理由)
- セキュリティ重視(rootless)
- Kubernetes互換性
トラブルシューティング
確認1: PostgreSQLが実際に起動しているか
# コンテナのステータス確認
docker ps -a
# 期待される出力:
# STATUS が "Up" になっている
# PostgreSQLプロセス確認
docker exec blog-postgres-dev ps aux | grep postgres
確認2: ポート5432が開いているか
# ホスト側から接続テスト
nc -zv localhost 5432
# または
telnet localhost 5432
# 成功すれば: "Connection succeeded"
確認3: データベースに直接接続
# psqlで接続テスト
docker exec -it blog-postgres-dev psql -U blog_dev_user -d blog_dev
# 成功すれば psqlプロンプトが表示される:
# blog_dev=>
# 接続できたら以下を実行:
\l # データベース一覧
\q # 終了
最終的な解決手順(コピペ用)
# 完全リセット
cd ~/springboot-gradle-blog-main
docker-compose down -v
# docker-compose.ymlを修正
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
postgres:
image: postgres:15.3-alpine
container_name: blog-postgres-dev
environment:
POSTGRES_USER: blog_dev_user
POSTGRES_DB: blog_dev
POSTGRES_PASSWORD: dev_password_123
ports:
- "5432:5432"
volumes:
- postgres_dev_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U blog_dev_user"]
interval: 10s
timeout: 5s
retries: 5
networks:
- blog-dev-network
pgadmin:
image: dpage/pgadmin4
container_name: blog-pgadmin-dev
environment:
PGADMIN_DEFAULT_EMAIL: admin@blog.local
PGADMIN_DEFAULT_PASSWORD: admin123
ports:
- "5050:80"
depends_on:
- postgres
networks:
- blog-dev-network
volumes:
postgres_dev_data:
driver: local
networks:
blog-dev-network:
driver: bridge
EOF
# コンテナ起動
docker-compose up -d
# 20秒待つ(PostgreSQL起動に時間がかかる)
echo "PostgreSQL起動待機中..."
sleep 20
# ログ確認
docker logs blog-postgres-dev
# 接続テスト
docker exec -it blog-postgres-dev psql -U blog_dev_user
-d blog_dev -c "SELECT 'Connection successful!' as status;"
# Spring Boot起動
./gradlew bootRun --args='--spring.profiles.active=dev'
もし起動に時間がかかる場合
PostgreSQLの初回起動は時間がかかります:
# リアルタイムでログを監視
docker logs -f blog-postgres-dev
# 以下が表示されるまで待つ:
# "database system is ready to accept connections"
# 表示されたら Ctrl+C でログ監視を終了
この手順で解決するはずです!結果を教えてください 🚀
hiroppy123@fedora:~/springboot-gradle-blog-main$ docker-compose up -d Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg. >>>> Executing external compose provider "/usr/libexec/docker/cli-plugins/docker-compose". Please see podman-compose(1) for how to disable this message
pasted
いえ、データベースは正常に作成されています! 🎉
エラーメッセージを見ると:
FATAL: database "blog_dev_user" does not exist
これはヘルスチェックが間違ったデータベース名で接続を試みているだけです。
実際の接続テストは成功しています:
SELECT version(); ← 成功!
PostgreSQL 15.3 ...
問題:ヘルスチェックの設定ミス
docker-compose.ymlのヘルスチェックが、ユーザー名をデータベース名として使おうとしています。
解決方法:docker-compose.ymlを修正
cd ~/springboot-gradle-blog-main
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
postgres:
image: postgres:15.3-alpine
container_name: blog-postgres-dev
environment:
POSTGRES_USER: blog_dev_user
POSTGRES_DB: blog_dev
POSTGRES_PASSWORD: dev_password_123
ports:
- "5432:5432"
volumes:
- postgres_dev_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U blog_dev_user -d blog_dev"]
# ^^^^^^^^^^^^
# データベース名を追加!
interval: 10s
timeout: 5s
retries: 5
networks:
- blog-dev-network
pgadmin:
image: dpage/pgadmin4
container_name: blog-pgadmin-dev
environment:
PGADMIN_DEFAULT_EMAIL: admin@blog.local
PGADMIN_DEFAULT_PASSWORD: admin123
ports:
- "5050:80"
depends_on:
- postgres
networks:
- blog-dev-network
volumes:
postgres_dev_data:
driver: local
networks:
blog-dev-network:
driver: bridge
EOF
でも実は、このエラーは無視しても問題ありません。PostgreSQLは正常に動作しています。
Spring Bootアプリを起動してみましょう
cd ~/springboot-gradle-blog-main
# そのまま起動
./gradlew bootRun --args='--spring.profiles.active=dev'
今度は成功するはずです! 🚀
もし完璧にしたい場合(オプション)
# コンテナを再起動(ヘルスチェックのエラーを消すため)
docker-compose down
docker-compose up -d
# 少し待つ
sleep 10
# Spring Boot起動
./gradlew bootRun --args='--spring.profiles.active=dev'
```
## ログの解説(業界トーク)
```
✅ database system is ready to accept connections
→ PostgreSQL本体は正常起動
❌ FATAL: database "blog_dev_user" does not exist
→ ヘルスチェックが間違った接続を試みている
→ でもこれは「ヘルスチェックのバグ」であって
PostgreSQL自体は動いている
✅ SELECT version(); が成功
→ 実際の接続は問題なし
```
### 業界あるある:ログの読み方
```
新人「FATALエラーが出てます!大変です!」
↓
先輩「どこで出てる?」
↓
新人「ヘルスチェックです...」
↓
先輩「実際の接続テストは?」
↓
新人「成功してます...」
↓
先輩「じゃあ動くよ。ヘルスチェックのミスだから」
↓
新人「えっ、FATALなのに...?」
↓
先輩「ログレベルは開発者が決めるから、
本当に致命的かどうかは文脈で判断するんだよ」
ログレベルの真実:
- FATAL = 開発者が「致命的」と思ったもの
- 実際には無視できることも多い
- 重要なのは「アプリが動くかどうか」
確認:Spring Bootが正常に起動するか
./gradlew bootRun --args='--spring.profiles.active=dev'
```
以下のログが出れば**大成功**:
```
Tomcat started on port 8080 (http)
Started BlogApplication in X.XXX seconds
```
その後、ブラウザで以下にアクセス:
```
http://localhost:8080
トラブルシューティング(念のため)
もし起動に失敗したら:
# PostgreSQL接続を手動確認
docker exec -it blog-postgres-dev psql -U blog_dev_user -d blog_dev
# psqlプロンプトで:
\l # データベース一覧
\dt # テーブル一覧(まだ空)
\q # 終了
まとめ
現状:
- ✅ Java 21.0.9 インストール済み
- ✅ Gradle 9.2.1 動作中
- ✅ PostgreSQL 15.3 起動中
- ✅ データベース
blog_dev作成済み - ✅ ユーザー
blog_dev_user作成済み - ⚠️ ヘルスチェックにバグ(でも無害)
次のステップ:
./gradlew bootRun --args='--spring.profiles.active=dev'
これで起動するはずです!結果を教えてください 🎉
./gradlew bootRun --args='--spring.profiles.active=dev' > Task :bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____|
pasted
はい!マイグレーションに失敗しています。でも原因は明確です!
問題の診断
ERROR: syntax error at or near "AUTO_INCREMENT"
```
**原因:** SQLの構文が**MySQL用**になっています。
PostgreSQLでは`AUTO_INCREMENT`ではなく`SERIAL`
または`GENERATED ALWAYS AS IDENTITY`を使います。
## データベース間の方言の違い(業界トーク)
```
MySQL: AUTO_INCREMENT ← よく使われる
PostgreSQL: SERIAL または GENERATED ALWAYS AS IDENTITY
Oracle: SEQUENCE + TRIGGER
SQL Server: IDENTITY
```
**これ、データベースあるあるトップ3に入ります!** 😅
```
開発者「MySQLで動いたコードをPostgreSQLに移したら動かない...」
↓
先輩「SQLの方言が違うんだよ」
↓
開発者「SQLって標準じゃないんですか?」
↓
先輩「理論上は標準があるけど、実際は各DBが独自拡張しまくってる」
↓
開発者「えっ...」
↓
先輩「だからORMが流行ったんだよ(遠い目)」
解決方法:Flywayマイグレーションファイルを修正
ステップ1: マイグレーションファイルの場所を確認
cd ~/springboot-gradle-blog-main
ls -la src/main/resources/db/migration/
ステップ2: すべてのマイグレーションファイルを修正
以下のコマンドで一括修正できます:
cd ~/springboot-gradle-blog-main
# V1__Create_users_table.sql を修正
cat > src/main/resources/db/migration/V1__Create_users_table.sql << 'EOF'
-- Flywayマイグレーションファイル: PostgreSQL用
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
enabled BOOLEAN DEFAULT TRUE,
account_non_locked BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_users_username ON users(username);
CREATE INDEX idx_users_email ON users(email);
EOF
MySQL vs PostgreSQL 構文対応表
| 機能 | MySQL | PostgreSQL |
|---|---|---|
| 自動採番 | BIGINT AUTO_INCREMENT |
BIGSERIAL または BIGINT GENERATED ALWAYS AS IDENTITY |
| 現在時刻 | NOW() |
CURRENT_TIMESTAMP または NOW() |
| 真偽値 | TINYINT(1) または BOOLEAN |
BOOLEAN |
| 文字列連結 | CONCAT() |
|| または CONCAT() |
| LIMIT | LIMIT 10 |
LIMIT 10 (同じ) |
| バッククォート | `column` |
"column" |
ステップ3: 他のマイグレーションファイルも確認
# すべてのマイグレーションファイルを表示
find src/main/resources/db/migration/ -name "*.sql"
-exec echo "=== {} ===" \; -exec cat {} \;
もし他にもAUTO_INCREMENTが含まれているファイルがあれば教えてください。一緒に修正しましょう。
ステップ4: データベースをリセット
Flywayはマイグレーションに失敗すると、中途半端な状態になることがあります。クリーンな状態から再スタートします:
# PostgreSQLのデータベースを削除して再作成
docker exec -it blog-postgres-dev psql -U blog_dev_user
-d postgres -c "DROP DATABASE IF EXISTS blog_dev;"
docker exec -it blog-postgres-dev psql -U blog_dev_user
-d postgres -c "CREATE DATABASE blog_dev;"
# または、コンテナを完全に再作成
docker-compose down -v
docker-compose up -d
sleep 10
ステップ5: アプリケーションを再起動
./gradlew clean bootRun --args='--spring.profiles.active=dev'
完全な修正スクリプト(コピペ用)
以下をまとめて実行してください:
cd ~/springboot-gradle-blog-main
# マイグレーションファイルをPostgreSQL用に修正
cat > src/main/resources/db/migration/V1__Create_users_table.sql << 'EOF'
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
enabled BOOLEAN DEFAULT TRUE,
account_non_locked BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_users_username ON users(username);
CREATE INDEX idx_users_email ON users(email);
EOF
# データベースをクリーンアップ
docker exec -it blog-postgres-dev psql -U blog_dev_user
-d postgres -c "DROP DATABASE IF EXISTS blog_dev;"
docker exec -it blog-postgres-dev psql -U blog_dev_user
-d postgres -c "CREATE DATABASE blog_dev;"
# アプリケーションをクリーンビルド&起動
./gradlew clean bootRun --args='--spring.profiles.active=dev'
他のマイグレーションファイルも修正が必要かも
もし複数のマイグレーションファイルがある場合、以下のパターンで修正してください:
テーブル作成の基本パターン
-- MySQL版(NG)
CREATE TABLE posts (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
content TEXT,
user_id BIGINT,
created_at DATETIME DEFAULT NOW()
);
-- PostgreSQL版(OK)
CREATE TABLE posts (
id BIGSERIAL PRIMARY KEY,
title VARCHAR(200) NOT NULL,
content TEXT,
user_id BIGINT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
```
## 業界の知恵:マイグレーションのベストプラクティス
### 1. データベース方言を意識する
```
開発環境: H2 / SQLite(軽量)
↓
本番環境: PostgreSQL / MySQL
↓
問題: 方言が違って動かない 😱
```
**推奨:**
- 開発環境でも本番と同じDBを使う(今回のようにDocker使用)
- ORMの抽象化に頼りすぎない
- Raw SQLを書く場合は必ずDB方言を確認
### 2. Flywayのバージョン管理
```
V1__Initial_schema.sql ← 最初
V2__Add_posts_table.sql ← 追加
V3__Add_comments_table.sql ← さらに追加
```
**ルール:**
- ファイル名は変更厳禁
- 一度適用したマイグレーションは変更厳禁
- 修正したい場合は新しいマイグレーションを追加
### 3. ロールバック戦略
Flywayは基本的に**ロールバック非対応**(有料版のみ対応)
```
失敗したら:
1. データベースを削除して再作成
2. マイグレーションファイルを修正
3. 再実行
本番環境では:
- テスト環境で十分確認
- バックアップ必須
トラブルシューティング
問題1: 他のマイグレーションファイルにもエラーがある
# すべてのマイグレーションファイルでAUTO_INCREMENTを検索
grep -r "AUTO_INCREMENT" src/main/resources/db/migration/
# 見つかったら、すべて BIGSERIAL に置換
find src/main/resources/db/migration/ -name "*.sql"
-exec sed -i 's/BIGINT AUTO_INCREMENT/BIGSERIAL/g' {} \;
問題2: Flywayのメタデータが残っている
# Flywayのメタデータテーブルを削除
docker exec -it blog-postgres-dev psql -U blog_dev_user
-d blog_dev -c "DROP TABLE IF EXISTS flyway_schema_history;"
問題3: 完全リセットしたい
# すべてのコンテナとボリュームを削除
docker-compose down -v
# 再作成
docker-compose up -d
sleep 10
# アプリ起動
./gradlew clean bootRun --args='--spring.profiles.active=dev'
まとめ
現状:
- ✅ Java 21.0.9 動作中
- ✅ PostgreSQL 15.3 動作中
- ✅ データベース接続成功
- ❌ マイグレーションファイルがMySQL用の構文
修正内容:
MySQL: BIGINT AUTO_INCREMENT
↓
PostgreSQL: BIGSERIAL
次のアクション: 上記の修正スクリプトを実行して、再度起動してください!
うまくいかない場合は、以下を教えてください:
ls -la src/main/resources/db/migration/
cat src/main/resources/db/migration/V1__Create_users_table.sql
一緒に解決しましょう!🚀
./gradlew bootRun --args='--spring.profiles.active=dev' > Task :bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____|
pasted
はい、その通りです!V4とV6でテーブルが重複して作成されようとしています。
問題の診断
ログを見ると:
✅ V1 - Create users table (成功)
✅ V2 - Create roles table (成功)
✅ V3 - Create posts table (成功)
✅ V4 - Consolidated migration (成功) ← ここでuser_rolesを作成済み
✅ V5 - Insert sample data (成功)
❌ V6 - Create user roles table (失敗) ← すでに存在するため失敗
V4でuser_rolesテーブルを作成しているのに、V6でも作ろうとしている
業界あるある:マイグレーションの重複問題 😅
初期開発:
V1: users作成
V2: roles作成
V3: posts作成
↓
後から整理:
V4: 「まとめて作り直そう!」← user_rolesも含む
↓
さらに後:
V6: 「あれ?user_rolesまだ作ってなかった?」← 忘れてた
↓
結果: 重複で失敗 💥
これ、チーム開発あるあるトップ3!
解決方法:重複マイグレーションを修正
方法1: V6を削除(推奨)
V4ですでに作成されているので、V6は不要です。
cd ~/springboot-gradle-blog-main
# V6マイグレーションファイルを削除
rm src/main/resources/db/migration/V6__Create_user_roles_table.sql
# データベースをクリーンアップ
docker exec -it blog-postgres-dev psql -U blog_dev_user
-d postgres -c "DROP DATABASE IF EXISTS blog_dev;"
docker exec -it blog-postgres-dev psql -U blog_dev_user
-d postgres -c "CREATE DATABASE blog_dev;"
# 再起動
./gradlew clean bootRun --args='--spring.profiles.active=dev'
方法2: V6を修正(IF NOT EXISTSを使用)
もしV6を残したい場合:
cat > src/main/resources/db/migration/V6__Create_user_roles_table.sql << 'EOF'
-- user_rolesテーブルが存在しない場合のみ作成
CREATE TABLE IF NOT EXISTS user_roles (
user_id BIGINT,
role_id BIGINT,
PRIMARY KEY (user_id, role_id),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE
);
-- インデックスも存在チェック
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE indexname = 'idx_user_roles_user') THEN
CREATE INDEX idx_user_roles_user ON user_roles(user_id);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE indexname = 'idx_user_roles_role') THEN
CREATE INDEX idx_user_roles_role ON user_roles(role_id);
END IF;
END
$$;
EOF
方法3: V4の内容を確認して整理(ベストプラクティス)
# V4の内容を確認
cat src/main/resources/db/migration/V4__Consolidated_migration.sql
# もしV4に全て含まれているなら、V6を削除
rm src/main/resources/db/migration/V6__Create_user_roles_table.sql
すべてのマイグレーションファイルを確認
cd ~/springboot-gradle-blog-main
# すべてのマイグレーションファイルを一覧表示
ls -la src/main/resources/db/migration/
# 内容を確認
for file in src/main/resources/db/migration/*.sql; do
echo "========== $file =========="
cat "$file"
echo ""
done
推奨:完全にクリーンアップして再構築
マイグレーションファイルが混乱している場合の最善策:
cd ~/springboot-gradle-blog-main
# ステップ1: すべてのマイグレーションファイルを確認
ls -la src/main/resources/db/migration/
# ステップ2: 重複しているV6を削除
rm src/main/resources/db/migration/V6__Create_user_roles_table.sql
# ステップ3: データベースを完全リセット
docker-compose down -v
docker-compose up -d
sleep 10
# ステップ4: クリーンビルド&起動
./gradlew clean bootRun --args='--spring.profiles.active=dev'
```
## Flywayのベストプラクティス(業界の知恵)
### マイグレーションファイルの命名規則
```
V1__Initial_schema.sql ← 初期スキーマ
V2__Add_posts_table.sql ← 追加テーブル
V3__Add_comments_column.sql ← カラム追加
V4__Create_indexes.sql ← インデックス作成
❌ 避けるべき:
V4__Consolidated_migration.sql ← 「まとめ直し」は混乱の元
V10__Fix_previous_migration.sql ← 過去のマイグレーションは修正不可
```
### 統合マイグレーション (Consolidated) の問題点
```
初期開発時:
V1: users
V2: roles
V3: user_roles
↓
後で「整理したい」と思って:
V4: Consolidated (users, roles, user_rolesを全部再作成)
↓
問題:
- V1-V3がすでに実行済み
- V4で同じテーブルを作ろうとして衝突
- さらにV6でまた重複...
```
**正しいアプローチ:**
```
V1: users
V2: roles
V3: user_roles
V4: Add_posts_table ← 新しい機能を追加
V5: Add_comments_table ← さらに追加
V6: Add_indexes_to_users ← 既存テーブルの改善
トラブルシューティング
問題1: V4の内容が分からない
# V4を表示
cat src/main/resources/db/migration/V4__Consolidated_migration.sql
もしuser_rolesが含まれていたら、V6は削除してください。
問題2: マイグレーション履歴を確認したい
# Flywayの履歴テーブルを確認
docker exec -it blog-postgres-dev psql -U blog_dev_user
-d blog_dev -c "SELECT * FROM flyway_schema_history ORDER BY installed_rank;"
問題3: 特定のマイグレーションだけやり直したい
Flywayの制限: 一度実行したマイグレーションは変更・削除できません。
解決策:
- データベースを完全削除して再作成
- または新しいマイグレーション(V7)で修正
完全解決スクリプト(コピペ用)
cd ~/springboot-gradle-blog-main
# V6を削除(V4で既に作成済みのため)
rm -f src/main/resources/db/migration/V6__Create_user_roles_table.sql
# データベースを完全リセット
echo "データベースをリセット中..."
docker-compose down -v
docker-compose up -d
# PostgreSQL起動を待つ
echo "PostgreSQL起動待機中..."
sleep 15
# 起動確認
docker logs blog-postgres-dev | tail -n 5
# アプリケーション起動
echo "Spring Boot起動中..."
./gradlew clean bootRun --args='--spring.profiles.active=dev'
```
## 成功の確認
起動が成功すると、以下のログが表示されます:
```
Tomcat started on port 8080 (http)
Started BlogApplication in X.XXX seconds (process running for X.XXX)
```
その後、ブラウザで確認:
```
http://localhost:8080
まとめ
原因: V4とV6でuser_rolesテーブルが重複
解決策:
- V6を削除(推奨)
- データベースをリセット
- 再起動
業界の教訓:
- マイグレーションは「前進のみ」
- 過去のマイグレーションを変更したくなったら、新しいマイグレーションで修正
- "Consolidated"マイグレーションは避ける
上記のスクリプトを実行して、結果を教えてください!🚀
0 件のコメント:
コメントを投稿