リソースの開放
2.6 リソースの開放
本節では、JDBCを利用してJavaプログラムからMariaDBデータベースへ接続した際の、リソースの開放について学習します。
2.6.1 確実なリソースの開放
データベースと連携するシステムはSQLの実行を頻繁に行うようになります。その際に、操作するデータの量が多くなると、リソースがシステムのパフォーマンスに影響します。その為、リソースの開放は確実に行う必要があります。本テキストでこれまで作成してきたプログラムを見ると、SQL文の実行中に例外が発生した場合、データベースが接続された状態のままになってしまっています。例外が発生した場合でもリソースを開放する処理が行われるように、例外処理に注意してリソースを確実に開放する方法を学習しましょう。
では、どのように記述すれば確実なリソースの開放が行えるのか実際にプログラムを作成してみましょう。
リソースの開放を行うプログラム
このプログラムは、データベースへ接続し、テーブルに登録されたデータを全て表示するプログラムです。SQL文を実行中にエラーが発生した場合でも、リソースの開放が行われるように例外処理を記述しています。
➢ SampleSelect2.java① ソース・フォルダー :myjdbc_kanda/src
② パッケージ :jp.co.f1.jdbc.ch02
③ 名前 :SampleSelect2
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
package jp.co.f1.jdbc.ch02; import java.sql.*; public class SampleSelect2 { //接続用の情報をフィールドに定数として定義 private static String RDB_DRIVE="org.mariadb.jdbc.Driver"; private static String URL="jdbc:mariadb://localhost/mybookdb"; private static String USER="bms"; private static String PASSWD="bms123"; public static void main(String[] args) { Connection con = null; Statement smt = null; try { Class.forName(RDB_DRIVE); con = DriverManager.getConnection(URL,USER,PASSWD); smt = con.createStatement(); String sql = "SELECT * FROM bookinfo"; ResultSet rs = smt.executeQuery(sql); while (rs.next()) { System.out.println("isbn -> " + rs.getString("isbn") + " title -> " + rs.getString("title") + " price-> " + rs.getString("price")); } } catch (Exception e) { System.out.println("JDBCデータベース接続エラー" + e); } finally { try { if (smt != null) { System.out.println("SQLステートメントをクローズしました。"); smt.close(); } if (con != null) { System.out.println("DB接続をクローズしました。"); con.close(); } } catch (SQLException ignore) { //例外処理の無視 } } } }
実行結果
解説
このプログラムは2.1節で学習したSampleSelect.javaを改良したプログラムです。大きな違いは34行目から48行目で、finally処理を追加し、その中でリソース(smt、com)の開放を行なっている点です。
try~catchにfinallyブロックを追加する事で、正常時でも例外が発生した場合でも必ず処理されるルートを作成します。finallyブロックにSQLステートメント(smt)とデータベース接続(con)の開放処理を行うことで確実にリソースの開放が行えるようになります。
なお、例外が発生した場所によってはリソースを取得していない場合があるため、36行目と40行目で開放する前にnullチェックを行っています。
このプログラムでは以下ようにfinallyブロックが実行されます。
① 正常処理の場合
正常処理を行なってfinallyブロックが実行される場合、smtとconは両方とも取得されているので、finallyブロックでは両方のリソースの開放が行われる。
② conを取得するまでに例外が発生
conを取得するまでに例外が発生した場合、smtとconは両方とも取得されてないので、finallyブロックでは両方ともリソースの開放は行われない。
③ smtを取得するまでに例外が発生
smtを取得するまでに例外が発生した場合、conのみ取得されsmtは取得されていないので、finallyブロックではconのみのリソースの開放が行われる。
ポイント
- リソースの開放は確実に行うためにfinallyブロックで行う。
- close()メソッドを実行することで、ConnectionオブジェクトとStatementオブジェクトのリソースを解放する。
- リソースを解放する場合、リソースがあるか判断してから解放処理を行う。