001package com.streamconverter.tools; 002 003import java.sql.Connection; 004import java.sql.DriverManager; 005import java.sql.PreparedStatement; 006import java.sql.ResultSet; 007import java.sql.ResultSetMetaData; 008import java.sql.SQLException; 009import java.util.Scanner; 010 011// import org.h2.tools.Server; // H2のWebサーバー機能は依存関係の問題でコメントアウト 012 013/** 014 * H2データベースの中身を確認するためのツール 015 * 016 * <p>このツールでは以下の方法でH2データベースにアクセスできます: 1. H2 Web Console(ブラウザ経由) 2. 対話型SQLクライアント(コマンドライン) 3. 017 * データベース構造の表示 018 */ 019public class DatabaseInspector { 020 021 private static final String DEFAULT_DB_URL = "jdbc:h2:mem:demo;DB_CLOSE_DELAY=-1"; 022 023 public static void main(String[] args) { 024 try { 025 System.out.println("=== H2 Database Inspector ===\n"); 026 027 // デモ用データベースを初期化 028 initializeDemoDatabase(); 029 030 // メニュー表示 031 showMenu(); 032 033 } catch (Exception e) { 034 System.err.println("エラーが発生しました: " + e.getMessage()); 035 e.printStackTrace(); 036 } 037 } 038 039 /** メニューを表示して操作を選択 */ 040 private static void showMenu() { 041 Scanner scanner = new Scanner(System.in); 042 043 while (true) { 044 System.out.println("\n--- 操作メニュー ---"); 045 System.out.println("1. H2 Web Console を起動"); 046 System.out.println("2. テーブル一覧を表示"); 047 System.out.println("3. テーブルのデータを表示"); 048 System.out.println("4. カスタムSQLクエリを実行"); 049 System.out.println("5. データベース構造を表示"); 050 System.out.println("0. 終了"); 051 System.out.print("\n選択してください (0-5): "); 052 053 try { 054 int choice = scanner.nextInt(); 055 scanner.nextLine(); // 改行を消費 056 057 switch (choice) { 058 case 1: 059 startWebConsole(); 060 break; 061 case 2: 062 showTables(); 063 break; 064 case 3: 065 showTableData(scanner); 066 break; 067 case 4: 068 executeCustomQuery(scanner); 069 break; 070 case 5: 071 showDatabaseStructure(); 072 break; 073 case 0: 074 System.out.println("終了します。"); 075 return; 076 default: 077 System.out.println("無効な選択です。0-5の番号を入力してください。"); 078 } 079 } catch (Exception e) { 080 System.out.println("エラー: " + e.getMessage()); 081 scanner.nextLine(); // エラー時の入力をクリア 082 } 083 } 084 } 085 086 /** H2 Web Consoleを起動 */ 087 private static void startWebConsole() { 088 System.out.println("⚠️ Web Console機能は現在無効になっています"); 089 System.out.println("💡 代替案:"); 090 System.out.println(" - メニューの「2. テーブル一覧を表示」でテーブルを確認"); 091 System.out.println(" - メニューの「3. テーブルのデータを表示」でデータを確認"); 092 System.out.println(" - メニューの「4. カスタムSQLクエリを実行」でクエリを実行"); 093 System.out.println(" - QuickDatabaseLookupクラスも利用可能です"); 094 095 /* 096 // H2 Web Server依存関係の問題により一時的に無効化 097 try { 098 Server webServer = Server.createWebServer("-webAllowOthers", "-webPort", "8082"); 099 webServer.start(); 100 101 System.out.println("✅ H2 Web Console が起動されました!"); 102 System.out.println("📖 ブラウザで以下のURLにアクセスしてください:"); 103 System.out.println(" http://localhost:8082"); 104 System.out.println("\n💡 接続情報:"); 105 System.out.println(" JDBC URL: " + DEFAULT_DB_URL); 106 System.out.println(" User Name: (空白)"); 107 System.out.println(" Password: (空白)"); 108 System.out.println("\n⚠️ 注意: このプロセスを終了するとWebコンソールも停止します"); 109 110 } catch (SQLException e) { 111 System.err.println("Web Console の起動に失敗しました: " + e.getMessage()); 112 } 113 */ 114 } 115 116 /** テーブル一覧を表示 */ 117 private static void showTables() { 118 try (Connection conn = DriverManager.getConnection(DEFAULT_DB_URL)) { 119 String query = 120 "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PUBLIC'"; 121 122 try (PreparedStatement stmt = conn.prepareStatement(query); 123 ResultSet rs = stmt.executeQuery()) { 124 125 System.out.println("\n📋 テーブル一覧:"); 126 while (rs.next()) { 127 System.out.println(" - " + rs.getString("TABLE_NAME")); 128 } 129 } 130 } catch (SQLException e) { 131 System.err.println("テーブル一覧の取得に失敗しました: " + e.getMessage()); 132 } 133 } 134 135 /** 指定したテーブルのデータを表示 */ 136 private static void showTableData(Scanner scanner) { 137 System.out.print("テーブル名を入力してください: "); 138 String tableName = scanner.nextLine().trim(); 139 140 if (tableName.isEmpty()) { 141 System.out.println("テーブル名が入力されていません。"); 142 return; 143 } 144 145 try (Connection conn = DriverManager.getConnection(DEFAULT_DB_URL)) { 146 String query = "SELECT * FROM " + tableName; 147 148 try (PreparedStatement stmt = conn.prepareStatement(query); 149 ResultSet rs = stmt.executeQuery()) { 150 151 System.out.println("\n📊 テーブル「" + tableName + "」のデータ:"); 152 printResultSet(rs); 153 } 154 } catch (SQLException e) { 155 System.err.println("データの取得に失敗しました: " + e.getMessage()); 156 } 157 } 158 159 /** カスタムSQLクエリを実行 */ 160 private static void executeCustomQuery(Scanner scanner) { 161 System.out.print("SQLクエリを入力してください: "); 162 String query = scanner.nextLine().trim(); 163 164 if (query.isEmpty()) { 165 System.out.println("クエリが入力されていません。"); 166 return; 167 } 168 169 try (Connection conn = DriverManager.getConnection(DEFAULT_DB_URL)) { 170 try (PreparedStatement stmt = conn.prepareStatement(query)) { 171 172 if (query.trim().toUpperCase().startsWith("SELECT")) { 173 // SELECT文の場合 174 try (ResultSet rs = stmt.executeQuery()) { 175 System.out.println("\n🔍 クエリ結果:"); 176 printResultSet(rs); 177 } 178 } else { 179 // INSERT, UPDATE, DELETE等の場合 180 int affectedRows = stmt.executeUpdate(); 181 System.out.println("✅ 実行完了。影響を受けた行数: " + affectedRows); 182 } 183 } 184 } catch (SQLException e) { 185 System.err.println("クエリの実行に失敗しました: " + e.getMessage()); 186 } 187 } 188 189 /** データベース構造を表示 */ 190 private static void showDatabaseStructure() { 191 try (Connection conn = DriverManager.getConnection(DEFAULT_DB_URL)) { 192 // テーブルとカラム情報を取得 193 String query = 194 """ 195 SELECT 196 TABLE_NAME, 197 COLUMN_NAME, 198 DATA_TYPE, 199 IS_NULLABLE, 200 COLUMN_DEFAULT 201 FROM INFORMATION_SCHEMA.COLUMNS 202 WHERE TABLE_SCHEMA = 'PUBLIC' 203 ORDER BY TABLE_NAME, ORDINAL_POSITION 204 """; 205 206 try (PreparedStatement stmt = conn.prepareStatement(query); 207 ResultSet rs = stmt.executeQuery()) { 208 209 System.out.println("\n🏗️ データベース構造:"); 210 211 String currentTable = ""; 212 while (rs.next()) { 213 String tableName = rs.getString("TABLE_NAME"); 214 215 if (!tableName.equals(currentTable)) { 216 if (!currentTable.isEmpty()) { 217 System.out.println(); 218 } 219 System.out.println("📋 テーブル: " + tableName); 220 currentTable = tableName; 221 } 222 223 String columnName = rs.getString("COLUMN_NAME"); 224 String dataType = rs.getString("DATA_TYPE"); 225 String nullable = rs.getString("IS_NULLABLE"); 226 String defaultValue = rs.getString("COLUMN_DEFAULT"); 227 228 System.out.printf( 229 " ├─ %-15s %-15s %s%s%n", 230 columnName, 231 dataType, 232 "YES".equals(nullable) ? "(NULL可)" : "(NOT NULL)", 233 defaultValue != null ? " デフォルト:" + defaultValue : ""); 234 } 235 } 236 } catch (SQLException e) { 237 System.err.println("データベース構造の取得に失敗しました: " + e.getMessage()); 238 } 239 } 240 241 /** ResultSetの内容を整形して表示 */ 242 private static void printResultSet(ResultSet rs) throws SQLException { 243 ResultSetMetaData metaData = rs.getMetaData(); 244 int columnCount = metaData.getColumnCount(); 245 246 // ヘッダー行を表示 247 for (int i = 1; i <= columnCount; i++) { 248 System.out.printf("%-20s", metaData.getColumnName(i)); 249 } 250 System.out.println(); 251 252 // 区切り線 253 for (int i = 1; i <= columnCount; i++) { 254 System.out.print("--------------------"); 255 } 256 System.out.println(); 257 258 // データ行を表示 259 while (rs.next()) { 260 for (int i = 1; i <= columnCount; i++) { 261 String value = rs.getString(i); 262 System.out.printf("%-20s", value != null ? value : "(NULL)"); 263 } 264 System.out.println(); 265 } 266 } 267 268 /** デモ用データベースの初期化 */ 269 private static void initializeDemoDatabase() throws SQLException { 270 try (Connection conn = DriverManager.getConnection(DEFAULT_DB_URL)) { 271 // テーブルを作成してデータを挿入(既存の場合はスキップ) 272 String checkTable = 273 "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'CUSTOMERS'"; 274 try (PreparedStatement stmt = conn.prepareStatement(checkTable); 275 ResultSet rs = stmt.executeQuery()) { 276 277 if (rs.next() && rs.getInt(1) > 0) { 278 System.out.println("✅ デモデータベースは既に初期化済みです"); 279 return; 280 } 281 } 282 283 // テーブル作成とデータ挿入(DatabaseRuleDemoと同じ) 284 setupDemoData(conn); 285 System.out.println("✅ デモデータベースを初期化しました"); 286 } 287 } 288 289 private static void setupDemoData(Connection conn) throws SQLException { 290 // テーブル作成 291 conn.prepareStatement( 292 """ 293 CREATE TABLE customers ( 294 id INTEGER PRIMARY KEY, 295 name VARCHAR(100), 296 email VARCHAR(100), 297 phone VARCHAR(20) 298 ) 299 """) 300 .execute(); 301 302 conn.prepareStatement( 303 """ 304 CREATE TABLE products ( 305 code VARCHAR(20) PRIMARY KEY, 306 name VARCHAR(100), 307 price DECIMAL(10,2), 308 category VARCHAR(50) 309 ) 310 """) 311 .execute(); 312 313 conn.prepareStatement( 314 """ 315 CREATE TABLE departments ( 316 code VARCHAR(10) PRIMARY KEY, 317 name VARCHAR(50), 318 manager VARCHAR(50) 319 ) 320 """) 321 .execute(); 322 323 // サンプルデータ挿入 324 insertSampleData(conn); 325 } 326 327 private static void insertSampleData(Connection conn) throws SQLException { 328 // 顧客データ 329 PreparedStatement customerStmt = 330 conn.prepareStatement("INSERT INTO customers (id, name, email, phone) VALUES (?, ?, ?, ?)"); 331 332 customerStmt.setInt(1, 1001); 333 customerStmt.setString(2, "田中太郎"); 334 customerStmt.setString(3, "tanaka@example.com"); 335 customerStmt.setString(4, "090-1234-5678"); 336 customerStmt.execute(); 337 338 customerStmt.setInt(1, 1002); 339 customerStmt.setString(2, "佐藤花子"); 340 customerStmt.setString(3, "sato@example.com"); 341 customerStmt.setString(4, "090-9876-5432"); 342 customerStmt.execute(); 343 344 customerStmt.setInt(1, 1003); 345 customerStmt.setString(2, "鈴木一郎"); 346 customerStmt.setString(3, "suzuki@example.com"); 347 customerStmt.setString(4, "090-5555-7777"); 348 customerStmt.execute(); 349 350 // 商品データ 351 PreparedStatement productStmt = 352 conn.prepareStatement( 353 "INSERT INTO products (code, name, price, category) VALUES (?, ?, ?, ?)"); 354 355 productStmt.setString(1, "LAPTOP001"); 356 productStmt.setString(2, "高性能ビジネスノートPC"); 357 productStmt.setBigDecimal(3, new java.math.BigDecimal("98000.00")); 358 productStmt.setString(4, "PC"); 359 productStmt.execute(); 360 361 productStmt.setString(1, "MOUSE001"); 362 productStmt.setString(2, "無線光学マウス"); 363 productStmt.setBigDecimal(3, new java.math.BigDecimal("2980.00")); 364 productStmt.setString(4, "周辺機器"); 365 productStmt.execute(); 366 367 // 部署データ 368 PreparedStatement deptStmt = 369 conn.prepareStatement("INSERT INTO departments (code, name, manager) VALUES (?, ?, ?)"); 370 371 deptStmt.setString(1, "DEV"); 372 deptStmt.setString(2, "開発部"); 373 deptStmt.setString(3, "山田部長"); 374 deptStmt.execute(); 375 376 deptStmt.setString(1, "SALES"); 377 deptStmt.setString(2, "営業部"); 378 deptStmt.setString(3, "田村部長"); 379 deptStmt.execute(); 380 } 381}