教育サーバーのページ
オンラインテキスト目次
システムプログラミング演習

データベースとの連携 (Java アプリケーション)

1. データベースへのアクセス

データベースへのアクセスは、SQL文を作成し、作成された SQL文をデータベース管理ソフトウエア(DBMS)に送信すること でおこなわれる。

JDBCでは、柔軟性を確保するために、SQL文をDBMSに直接 送信するのではなく、SQLコンテナの役割をもつオブジェクトに 送信する。

DBMSに対してSQL文を送信するために、以下の2つの処理を おこなう。

  1. SQL文コンテナの作成
    Statementオブジェクトは、SQL文コンテナの役割を果たす。 Statementオブジェクトには、目的により使い分けられ、 以下の3種類のオブジェクトに分類される。なお、 Statementオブジェクトの生成は、newする必要がない。 接続を確立したConnectionオブジェクトから以下の目的に 合ったStatementオブジェクトを得て利用する。 なお、MySQLでは、上記のストアドプロシージャを実行できる CallableStatementは実装されていない。

    • Statementオブジェクト
      通常のSQL文を処理するときに利用
    • PreparedStatementオブジェクト
      SQL文のプリコンパイル用に利用

    Statementオブジェクトの種類と取得メソッドの関係は、 以下のようになる。

    種類取得するメソッド用途
    StatementcreateStatement()通常のSQL文
    PreparedStatementprepareStatement(String sql) SQLプリコンパイル

    特によく使われるStatementオブジェクトは、以下のように作成される。

    Statement stSql = dbConn.createStatement();
    

  2. SQL文の実行
    SQL文コンテナであるStatementオブジェクトに対しては、 SQL文が渡される。デフォルトでは、SQL文が渡されれば すぐに実行がおこなわれる。 SQL文を渡す主なメソッドには、executeQuery()とexecuteUpdate() の2つがある。 これらのメソッドは、以下に示すようにSQL文の処理によって 得られる結果を反映しての使い分けられる。

    • executeQuery()メソッド
      SELECT文などの問い合わせ文を送信する場合に使われ、 ResultSetオブジェクトに実行結果を格納して返す。 SQL文の実行結果が何も返さなかった場合でも、nullを 返すことはなく、空のResultSetオブジェクトを返す。 ResultSetを利用すれば、問い合わせで得られたデータ にアクセス可能である。
      executeQuery()メソッドの実行は、以下のようにおこなわれる。

      ResultSet result = st.executeQuery( sqlStr );
      

    • executeUpdate()メソッド
      問い合わせ以外のSQL文であるUPDATE文やINSERT文、DELETE文など のように、実行結果としてレコードの更新結果を処理した レコード数として返すSQL文や何も返さないDDL(表の作成、削除) を実行するために用いられる。
      executeUpdate()メソッドの実行は、以下のようにおこなわれる。

      st.executeUpdate( sqlStr );
      

2. SQL文実行結果の取り出し

executeQuery()メソッドの実行結果は、ResultSetオブジェクトとして アクセス可能である。したがって、RusultSetクラスのメソッドを 用いて、SELECT文などの問い合わせ文の実行結果を自由に プログラムから処理可能である。

ResultSet

ResultSetは、問い合わせにより返されるデータの行(レコード) をあらわす。ここでは、問い合わせの結果から列(カラム) を取得するために、以下のようなメソッドを提供する。 なお、列を取得するメソッドは、type getType(int | String)の 形式をとる。ここで、引数には、取得したい列の番号か、列名を 指定する。

[ResultSetクラスのメソッド]

メソッド機能
boolean first()現在の参照行を先頭に移動
boolean next()現在の参照行を1行下に移動
boolean previous()現在の参照行を1行上に移動
boolean last()現在の参照行を最終行に移動
String getString(String columnName)現在行から列名に指定した列の値を取得
int getInt(String columnName)現在行から列名に指定した列の値を取得
double getDouble(String columnName)現在行から列名に指定した列の値を取得
boolean getBoolean(String columnName)現在行から列名に指定した列の値を取得
Date getDate(String columnName)現在行から列名に指定した列の値を取得

ResultSetオブジェクトは、データベースからのデータを一度に 1行ずつ(レコード単位)でしかアクセスできない。 したがって、ResultSetオブジェクトの現在参照している1行 の次の行を参照するためには、next()メソッドが提供されて いる。next()メソッドがtrueを返している場合には、処理できる 行がまだ存在することを表している。引き続いて、ResultSet オブジェクトに対してnext()メソッド呼び出しを実行することで、 次の行が参照される。処理できる行が残っていない場合には、 falseが返される。

ResultSetの一般的な利用方法は、以下のようになる。

ResultSet result = st.executeQuery( sqlStr );
while(result.next()) {
  //        String str1 = result.getString( "Host" );
  //        String str2 = result.getString( "User" );
  //        System.out.println( str1 + ", " + str2 );
       String str1 = result.getString( "c" );
       System.out.println( str1 );
}

3. データベースへの接続のクローズ

データベースへの接続のクローズでは、以下の処理が必要になる。

データベースリソースを閉じるためには、上記に 示す処理が必要になり、具体的には、Connection オブジェクト、Statementオブジェクト、ResultSet オブジェクトのそれぞれを閉じる必要がある。 これらは、以下のような処理によりおこなわれる。

result.close();
st.close();
con.close();
}

4. Javaアプリケーションの基本形

データベースの検索 (その1)

以下のJdbcTest5.javaは、データベースを使ったJavaアプリケーション である。具体的には、localhostにあるデータベースサーバと接続し、 testデータベースと接続し、その中のfruitテーブルの内容を 表示する。

import java.net.*;
import java.sql.*;

public class JdbcTest5 {
  public static void main( String args[] ) throws Exception {
    String servername     = "localhost"; 
    // // 接続先サーバー名は,第1引数として与える。
    String urlprefix      = "jdbc:mysql://";
    //    String databasename   = "mysql";
    String databasename   = "test";
    String user           = "root";

    //	StringBuffer temp = null;
    //  if(args.length == 2) temp = new StringBuffer( args[1] ); else temp = new StringBuffer( "" );
    //	String password = temp.toString(); 
    String password = "tuis2019system"; 
    // String serverencoding = "EUC_JP";
    String serverencoding = "UTF-8";
  
    String url =  urlprefix + servername + "/" + databasename + "?useUnicode=true&characterEncoding=" + serverencoding;
  
    Connection con = null;
    try {
      Class.forName( "com.mysql.jdbc.Driver" );               
      // Loading Driver
      con = DriverManager.getConnection( url, user, password ); 
      // Connecting MySQL server
      System.out.println( "Connected...." );
      Statement st = con.createStatement();
      String sqlStr = "SELECT * FROM fruit";
      ResultSet result = st.executeQuery( sqlStr );
    
      while( result.next() ) {
        String str1 = result.getString( "no" );
        String str2 = result.getString( "name" );
        String str3 = result.getString( "price" );
        System.out.println( str1 + ", " + str2 + ", " + str3);
      }
    
      result.close();
      st.close();
      con.close();
    }
    catch( SQLException e ) {
      System.out.println( "Connection Failed. : " + e.toString() );
      throw new Exception();
    }
    catch( Exception e ) {
      System.out.println( "Exception! :" + e.toString() );  
      throw new Exception();
    }
    finally {
      try {
        if ( con != null ) con.close();
      }
      catch(Exception e){
        System.out.println( "Exception! :" + e.toString() );
        throw new Exception();
      }
    }
  }
}

JdbcTest5.javaは、

java JdbcTest5 ↓
により、localhost上のデータベースサーバと接続し、JdbcTest5.java プログラムを実行する。この場合のプログラムには、引数としてユーザ名を "root"、パスワードを"tuis2019system"として与えられ実行されることになる。

このようなデータベースを利用したJavaアプリケーションは、以下のような 手順をとり、プログラムを実行する。

プログラム JdbcTest5.java の説明

JdbcTest5.javaは、 localhost上のデータベースサーバと接続し、 プログラムを実行する。 ここでは、ユーザ名は"root"、パスワードは"tuis2019system"である。

まず、

import java.net.*;
import java.sql.*;
では、java.netパッケージとJDBC2.0 Core APIであるjava.sqlパッケージが インポートされる。

    String servername     = "localhost"; 
では、接続先サーバー名を"localhost"で与えることを示している。

    String user           = "root";
では、データベースの接続に用いるユーザ名を指定しており、ここでは rootユーザをあらわしている。

    String password = "tuis2019system"; 
では、データベースの接続に用いるユーザのパスワードを指定している。

    String serverencoding = "UTF-8";
    String url =  urlprefix + servername + "/" + databasename + "?useUnicode=true&characterEncoding=" + serverencoding;
では、取り扱う文字コードをUTF-8文字とし、データベースをあらわすURLを 設定している。

データベースをあらわすURL(データベースURL)は、データベースに接続する場合に 必要となる情報をセットした文字列である。この文字列の構造は、"jdbc"、 サブプロトコル、サブネームの3つの部分から構成される。

jdbc:サブプロトコル:サブネーム

サブプロトコルは、ドライバやデータベースによる決まる名前である。 一般には、データベースソフトウエアの名称が指定される。 サブネームは、サブプロトコルにより規定されるデータソース、一般には データベース名やデータベースソフトウエアが動作するホスト名、ポート 番号などが記述される。

データベースURLのサブネームのパラメータにより、使用する文字をUnicode、 サーバの文字コードをUTF-8文字であると指定している。

 Class.forName( "com.mysql.jdbc.Driver" );    
では、クラスローだによりJDBCドライバを読み込んでいることを 示している。引数は、データベースにアクセスするためのJDBCドライバ のクラス名である。

con = DriverManager.getConnection( url, user, password ); // Connecting MySQL server
では、DriverManagerクラスのgetConnectionメソッドを使ってデータベースに 接続する。ここで、第一引数に与えているものが、上記のデータベースURL である。実行されたメソッドの戻り値は、接続を表すConnectionオブジェクトである。

      Statement st = con.createStatement();
では、データベースの接続後に、sql文をデータベースに直接渡すのでは なく、sqlコンテナの役割を果たすオブジェクトに渡すためのStatement オブジェクトを作成する。

Statementオブジェクトには3種類あり、目的による使い分ける。 通常のsql文を処理する場合には、Statementオブジェクトを用いる。 また、sql文のプリコンパイル用にはPreparedStatementを、 ストアドプロシージャ用にはCallableStatementを利用する。

Statementオブジェクトは、直接newする必要なく、接続を確立した Connectionオブジェクトから目的にあったStatementオブジェクトを 得て利用する。

      String sqlStr = "SELECT * FROM fruit";
      ResultSet result = st.executeQuery( sqlStr );
では、まず、strStrに実行するSQL文を文字列で指定する。 次に、Statementオブジェクトstに対してSQL文を渡してSQL文 の実行をおこなう。SQL文を渡すためのメソッドには、execute(), executeQuery(), executeUpdate()などがある。これらの違いは、 SQL文の実行により得られる結果がどのような情報を返すかに よって使い分ける。

SELECT文のようなSQL文ではexecuteQuery()メソッドを、 INSERT文、UPDATE文、DELETE文のようなSQL文ではexecuteUpdate()メソッド を使うことになる。

executeQuery()メソッドでは、問い合わせをおこなった結果を、ResultSet インターフェイスに格納して返す。一方、executeUpdate()メソッドでは、 結果として行のセットを返さないSQL文に利用する。

      while( result.next() ) {
        int no1 = result.getString( "no" );
        String str2 = result.getString( "name" );
        int price3 = result.getString( "price" );
        System.out.println( no1 + ", " + str2 + ", " + price3);
      }
では、ResultSetオブジェクトから結果を取得して表示している。 getString()メソッドは、RuseltSetから指定されたフィールド名(列) の値をStringとして取得する。

      result.close();
      st.close();
      con.close();
では、ResultSetオブジェクト、Statementオブジェクト、Connectionオブジェクト の切断をおこなう。

データベースの検索 (その2)

以下のJdbcTest6.javaは、localhost上のデータベースサーバ に接続し、データを検索するプログラムである。

import java.sql.*;

public class JdbcTest6 {
	public static void main(String[] args) {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			
			String url = "jdbc:mysql://localhost/test";

			String user = "root";
			String password = "tuis2019system";
			Connection conn = DriverManager.getConnection(url, user, password);
			
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery("SELECT name, price FROM fruit");
			
			while (rs.next()) {
				String name = rs.getString("name");
				int price = rs.getInt("price");
				System.out.println(name + " : " + price);
			}
	
			rs.close();
			stmt.close();
			conn.close();
		} catch(SQLException e) {
			e.printStackTrace();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

上記のプログラム JdbcTest6.java は、 localhost上のデータベースサーバ に接続し、データを検索する。検索により testデータベース内の表fruitにおいて nameフィールドとpriceフィールドを抽出し、 それぞれの値を表示する。

5. 演習問題

問題-1

JdbcTest5.javaを実行して、その結果を表示せよ。

問題-3

JdbcTest6.javaを実行して、その結果を表示せよ。

問題-4

接続するテーブルをfruit1として、fruit1のすべてのフィールド 値を表示する(JdbcTest5.javaと同様なふるまいをする) プログラムJdbcTest50.javaを作成・実行し、その結果を示せ。

問題-5

接続するテーブルをfruit1として、fruit1のフィールド名が「名前」と 「値段」に対応するフィールド値を検索し表示する(JdbcTest6.javaと 同様なふる まいをする)プログラムJdbcTest61.javaを作成・実行し、その結果を 示せ。

問題-6

接続するテーブルをhanbai_tblとして、hanbai_tblのフィールド名が "hanbaicode", "syohincode", "price", "hanbaibi"に対応する フィールド値を検索し表示する(JdbcTest6.javaと同様なふるまいを する)プログラムJdbcTest62.javaを作成・実行し、その結果を 示せ。

問題-7

MySQLコマンドを起動し、SQL文を与えることで以下のテーブル customers_tblを作成せよ。なお、データベース名がtestの データベースを作成し、使用したSQLコマンドも示せ。

customers_tblテーブルの構造

列名 データ型NOT NULL
customerid INT(10)NOT NULL
customernameVARCHAR(25)
customeraddressVARCHAR(40)
customerphoneVARCHAR(100)

customers_tblテーブル

customeridcustomernamecustomeraddresscustomerphone
1Mike Barott1756 7th St(325)200-2378
2Mike Brannen5460 7th St(680)259-6383
3Mike Carroll1152 Ave S(108)563-6737
4Mike Courville2987 15th St(243)443-2481
5Mike Dodd4360 20th St(308)834-6776
6Mike Ferguson5505 9th St(203)860-8901
7Mike Gilmer2610 Ave T(322)421-5245
8Mike Hand7162 15th St(743)813-1043
9Mike Holder2181 14th St(746)536-8136

問題-8

接続するテーブルを上記で作成したcustomers_tblとして、customers_tblのすべてのフィールド名と対応するフィールド値を表示する プログラムJdbcTest63.javaを作成・実行し、その結果を示せ。

システムプログラミング演習


Yasuo NAGAI