JavaでDBと接続してSQLを発行する方法
ここではMySQLに登録したデータを抽出する例を示します。 事前に用意するテーブルとデータを作るSQLを以下に示します。
drop table fruits;
create table fruits (
id int not null,
name varchar(20),
price int,
primary key (id)
);
insert into fruits (id, name, price) values
(1,'りんご', 200),
(2,'みかん', 250),
(3,'なし', 300);
mysql> select * from fruits;
+----+--------+-------+
| id | name | price |
+----+--------+-------+
| 1 | りんご | 200 |
| 2 | みかん | 250 |
| 3 | なし | 300 |
+----+--------+-------+
SELECTの結果の取得 (executeQuery)
String url = "jdbc:mysql://localhost:3306/sample?serverTimezone=JST";
try (Connection conn = DriverManager.getConnection(url, "dbuser", "password");
Statement stmt = conn.createStatement()) {
ResultSet result = stmt.executeQuery("SELECT * FROM fruits");
while (result.next()) {
System.out.printf("%d: %s %d円\n",
result.getInt("id"), result.getString("name"), result.getInt("price"));
}
// => 1: りんご 200円
// => 2: みかん 250円
// => 3: なし 300円
} catch (SQLException e) {
e.printStackTrace();
}
UPDATEの実行 (executeUpdate)
結果を返さない(select以外の)SQL文を発行するときは executeUpdate を使います。
String url = "jdbc:mysql://localhost:3306/sample?serverTimezone=JST";
String sql = "UPDATE fruits SET price=? WHERE name=?";
try (Connection conn = DriverManager.getConnection(url, "dbuser", "password");
PreparedStatement stmt = conn.prepareStatement(sql)) {
// パラメータのバインド
stmt.setInt(1, 500);
stmt.setString(2, "りんご");
System.out.println(stmt.executeUpdate()); // => 1
} catch (SQLException e) {
e.printStackTrace();
}
mysql> select * from fruits;
+----+--------+-------+
| id | name | price |
+----+--------+-------+
| 1 | りんご | 500 |
| 2 | みかん | 250 |
| 3 | なし | 300 |
+----+--------+-------+
トランザクションのコミットとロールバック (commit, rollback)
insert時に意図的に主キーが重複する値を指定してロールバックを発生させる例:
String url = "jdbc:mysql://localhost:3306/sample?serverTimezone=JST";
String sql = "UPDATE fruits SET price=? WHERE name=?";
try (Connection conn = DriverManager.getConnection(url, "dbuser", "password");
PreparedStatement stmt = conn.prepareStatement(sql)) {
conn.setAutoCommit(false);
try {
// update文:この更新はコミットされるまでDBに反映されない
stmt.executeUpdate("UPDATE fruits SET price=999 WHERE name='りんご'");
// insert文:主キーidが重複するレコードを挿入
stmt.executeUpdate("INSERT INTO fruits(id, name, price) VALUES (1, 'すいか', 1000)");
// コミット
conn.commit();
} catch (SQLException e) {
// ロールバック
conn.rollback();
System.out.println("ロールバック発生:" + e.getMessage());
// => ロールバック発生:Duplicate entry '1' for key 'fruits.PRIMARY'
}
} catch (SQLException e) {
e.printStackTrace();
}
SELECTの結果のカーソルを移動
カーソル移動ができるようにするためには、TYPE_SCROLL_INSENSITIVE または TYPE_SCROLL_SENSITIVE を指定する必要があります。
カーソル種類 (createStatementの第一引数):
- TYPE_FORWARD_ONLY : カーソルは順方向にしか移動できない(next()しか使えない)
- TYPE_SCROLL_INSENSITIVE : 任意のカーソル移動が可能。他によるデータ変更を反映しない
- TYPE_SCROLL_SENSITIVE : 任意のカーソル移動が可能。他によるデータ変更を反映する
カーソル移動方法:
- absolute(int) : 指定した行番号にカーソルを移動する(絶対位置に移動する)
- afterLast() : 最終行の後ろにカーソルを移動する
- beforeFirst() : 先頭行の前にカーソルを移動する
- first() : 先頭行にカーソルを移動する
- last() : 最終行にカーソルを移動する
- next() : 次の行にカーソルを移動する
- previous() : 前の行にカーソルを移動する
- relative(int) : 指定した行数(負数もあり)だけカーソルを移動する(相対位置に移動する)
String url = "jdbc:mysql://localhost:3306/sample?serverTimezone=JST";
try (Connection conn = DriverManager.getConnection(url, "dbuser", "password");
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY)) {
ResultSet result = stmt.executeQuery("SELECT * FROM fruits ORDER BY id");
// 最初のレコードを取得
result.first();
System.out.printf("%d: %s %d円\n",
result.getInt("id"), result.getString("name"), result.getInt("price"));
// => 1: りんご 200円
// 最後のレコードを取得
result.last();
System.out.printf("%d: %s %d円\n",
result.getInt("id"), result.getString("name"), result.getInt("price"));
// => 3: なし 300円
} catch (SQLException e) {
e.printStackTrace();
}