S-JIS[2010-07-19/2021-02-10] 変更履歴

PreparedStatement

JDBCPreparedStatementは、同一のSQLでパラメーターを変更して何度も実行するのに適している。

import java.sql.PreparedStatement;

概要

PreparedStatementは、ConnectionのprepareStatementメソッドで作成する。[2021-02-10]
prepareStatementメソッドには引数としてSQL文を渡す。

	String sql = "select * from TEST where VALUE1=? and VALUE2=?";

	try (PreparedStatement ps = conn.prepareStatement(sql)) {
		int i = 1;
		ps.setString(i++, "abc"); // VALUE1='abc'
		ps.setInt(i++, 123);      // VALUE2=123

		〜
	}

SQL文の中で「?」(パラメーター)になっている箇所に、set系メソッドで具体的な値を指定する。
set系メソッドの第1引数は、「?」の位置番号。1から始まる。(「?」が複数あるときは先頭から順番に1,2,3…という連番になる)
「?」のある場所のデータ型に応じて、setInt()・setString()といったメソッドを使い分ける。
Javaのクラスはデータ型に応じて変換されるので(変換可能なクラスに限るが)、例えば日付に関してsetDate()を使ってセットすれば、SQL文上にto_date()等の関数を書く必要は無い。

PreparedStatementは使い終わったらクローズする必要がある。
try文でクローズするのが便利。


SQL文の中に「:name」の様に書いて名前でパラメーターを指定する例を見かけることがあるが、これは標準のJDBCでは対応していないらしい。
JPAでは仕様化されているらしいけど^^;)


executeQuery

PreparedStatementを使ってSELECTする例。[2021-02-10]

SELECTする場合はexecuteQueryメソッドを使用する。

	String sql = "select * from TEST where KEY=?";
	try (PreparedStatement ps = conn.prepareStatement(sql)) {
		ps.setInt(1, 999);

		try (ResultSet rs = ps.executeQuery()) {
			while (rs.next()) {
				System.out.printf("KEY  =%d%n", rs.getInt("KEY");
				System.out.printf("VALUE=%s%n", rs.getString("VALUE1");
			}
		}
	}

executeUpdate

PreparedStatementを使ってINSERTする例。

更新系のSQL(INSERT/UPDATE/DELETE)の場合はexecuteUpdateメソッドを使用する。

	String sql = "insert into TEST (KEY) values(?)";
	try (PreparedStatement ps = conn.prepareStatement(sql)) {
		ps.setInt(1, 999);

		int r = ps.executeUpdate();
		System.out.println("更新件数:" + r);

		conn.commit();
	}

executeBatch

PreparedStatement(Statement)には、複数のSQL文を一括して実行するバッチ機能がある。
同一のSQLでパラメーターを変えて何度も実行するなら、executeUpdate()を何回も呼ぶよりもexecuteBatch()を使う方が高速。

	String sql = "insert into TEST " + "(KEY)" + " values(?)";
	try (PreparedStatement ps = conn.prepareStatement(sql)) {
		for (int i = 0; i <= 9999; i++) {
			ps.setInt(1, i);
			ps.addBatch();
		}
		ps.executeBatch();
		System.out.println("更新件数:" + ps.getUpdateCount());

		conn.commit();
	}

自分のPC上のOracleで1万件のINSERTを試したら、executeUpdate()を1万回呼んで1回コミットする方法だと約5.4秒、executeBatch()を使うと0.2〜0.4秒だった。


java.sql.Dateとjava.timeとの変換

Java8で新しく日付時刻API(java.time)が追加になったが、PreparedStatementでは直接は使用できない。[2021-02-10]
(PreparedStatementのset系メソッドやResultSetのget系メソッドは、java.timeに対応していない)

しかしjava.sql.Date等の日付系クラスについては、java.timeクラスとの変換メソッドが実装されている。

  java.sqlへの変換例 java.timeへの変換例 備考
日付 LocalDate ldate = 〜;
java.sql.Date sdate = java.sql.Date.valueOf(ldate);
java.sql.Date sdate = 〜;
LocalDate ldate = sdate.toLocalDate();
java.sql.Dateは年月日を扱う。
java.sql.Date sdate = new java.sql.Date(TimeUnit.DAYS.toMillis(ldate.toEpochDay()));
日時 LocalDateTime ldt = 〜;
java.sql.Timestamp sdt = java.sql.Timestamp.valueOf(ldt);
java.sql.Timestamp sdt = 〜;
LocalDateTime ldt = dst.toLocalDateTime();
java.sql.Timestampは年月日と時刻を扱う。
時刻 LocalTime ltime = 〜;
java.sql.Time stime = java.sql.Time.valueOf(ltime);
java.sql.Time stime = 〜;
LocalTime ltime = stime.toLocalTime();
java.sql.Timeは時刻を扱う。

JDBCへ戻る / Java目次へ戻る
メールの送信先:ひしだま