無料PHPプログラム

MySQL 5.1 リファレンスマニュアル :: 24 MySQL コネクタ :: 24.4 MySQL Connector/J :: 24.4.5 Connector/J に関する注記とヒント :: 24.4.5.1 JDBC の基本コンセプト
« 24.4.5 Connector/J に関する注記とヒント

24.4.5.2 J2EE および 他の Java フレームワークで Connector/J を使用する »
Section Navigation      [Toggle]
  • 24.4.5 Connector/J に関する注記とヒント
  • 24.4.5.1 JDBC の基本コンセプト
  • 24.4.5.2 J2EE および 他の Java フレームワークで Connector/J を使用する
  • 24.4.5.3 よくある問題と解決法

24.4.5.1. JDBC の基本コンセプト

[+/-]

24.4.5.1.1. DriverManager インターフェイスを使用して MySQL に接続する
24.4.5.1.2. ステートメントを使用して SQL を実行する
24.4.5.1.3. CallableStatements を使用してストアド プロシージャを実行する
24.4.5.1.4. AUTO_INCREMENT カラム値の呼び出し

このセクションでは、JDBC の一般的な背景を説明します。

24.4.5.1.1. DriverManager インターフェイスを使用して MySQL に接続する

アプリケーション サーバの外で JDBC を使用している場合、DriverManager クラスは Connections の確立を管理します。

DriverManager は、Connections をどの JDBC ドライバ で作成するべきかの指示を必要とします。この最も簡単な方法は、java.sql.Driver インターフェイスを実装するクラスで Class.forName() を使用することです。MySQL Connector/J では、このクラスの名称は com.mysql.jdbc.Driver になります。このメソッドで、外部構成ファイルを使用して、データベースへの接続に使用するドライバ クラス名とドライバ パラメータを供給することが可能です。

次のセクションの Java コードは、アプリケーションの main() メソッドから MySQL Connector/J を登録する方法を表しています。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

// Notice, do not import com.mysql.jdbc.*
// or you will have problems!

public class LoadDriver {
    public static void main(String[] args) {
        try {
            // The newInstance() call is a work around for some
            // broken Java implementations

            Class.forName("com.mysql.jdbc.Driver").newInstance();
        } catch (Exception ex) {
            // handle the error
        }
}

ドライバが DriverManager に登録されたら、DriverManager.getConnection() を呼び出すことによって、特定のデータベースに接続される Connection インスタンスを取得することができます :

例 24.1. DriverManager から接続を取得する

この例は、DriverManager から Connection インスタンスを取得する方法を示しています。getConnection() メソッドにはいくつかの異なる署名があります。JDK に添付されている API 資料で、詳しい使用方法を確認してください。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

...
try {
    Connection conn = 
       DriverManager.getConnection("jdbc:mysql://localhost/test?" + 
                                   "user=monty&password=greatsqldb");

    // Do something with the Connection

   ...
} catch (SQLException ex) {
    // handle any errors
    System.out.println("SQLException: " + ex.getMessage());
    System.out.println("SQLState: " + ex.getSQLState());
    System.out.println("VendorError: " + ex.getErrorCode());
}

Connection が確立されたら、Statement と PreparedStatement のオブジェクトの作成、そしてデータベースに関するメタデータの摘出に使用できます。これについては次のセクションで説明されます。

24.4.5.1.2. ステートメントを使用して SQL を実行する

Statement オブジェクトは、後で説明されるように、基本的な SQL クエリを実行し、ResultSet クラスを通しての結果の摘出を可能にします。

Statement を作成するには、前で説明した DriverManager.getConnection() か Data- Source.getConnection() メソッドのひとつを介して摘出した Connection オブジェクトで createStatement() メソッドを呼び出します。

Statement インスタンスを得たら、使いたい SQL で executeQuery( String) メソッドを呼び出し、SELECT クエリを実行することができます。

データベースのデータを更新するには、executeUpdate(String SQL) メソッドを使用します。このメソッドは、update 文に影響を受けた行の数を戻します。

SQL 文が SELECT 、または UPDATE/INSERT になるかが事前に分からない場合は、execute(String SQL) メソッドを使用することができます。このメソッドは、SQL クエリが SELECT の場合は true 、UPDATE 、INSERT 、もしくは DELETE 文の場合は false を返します。ステートメントが SELECT クエリの場合は、getResultSet() メソッドを呼び出すことで結果を摘出できます。ステートメントが UPDATE 、INSERT 、もしくは DELETE 文であれば、Statement インスタンスで getUpdateCount() を呼び出すことによって、影響を受けた行の数を呼び出すことができます。

例 24.2. java.sql.Statement を使用して SELECT クエリを実行する

// assume that conn is an already created JDBC connection
Statement stmt = null;
ResultSet rs = null;

try {
    stmt = conn.createStatement();
    rs = stmt.executeQuery("SELECT foo FROM bar");

    // or alternatively, if you don't know ahead of time that
    // the query will be a SELECT...

    if (stmt.execute("SELECT foo FROM bar")) {
        rs = stmt.getResultSet();
    }

    // Now do something with the ResultSet ....
} finally {
    // it is a good idea to release
    // resources in a finally{} block
    // in reverse-order of their creation
    // if they are no-longer needed

    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException sqlEx) { // ignore }

        rs = null;
    }

    if (stmt != null) {
        try {
            stmt.close();
        } catch (SQLException sqlEx) { // ignore }

        stmt = null;
    }
}
24.4.5.1.3. CallableStatements を使用してストアド プロシージャを実行する

MySQL サーバ バージョン 5.0 からは、Connector/J 3.1.1 以降と使用する場合、java.sql.CallableStatement インターフェイスは getParameterMetaData() メソッドを除いて完全に実装されています。

MySQL ストアド プロシージャの詳細は、 http://dev.mysql.com/doc/mysql/en/stored-procedures.html をご覧ください。

Connector/J は、JDBC の CallableStatement インターフェイスを通して、ストアド プロシージャ機能を露出します。

注意 :? MySQL サーバの現行バージョンは、JDBC ドライバが呼び出し可能なステートメントに結果セット メタデータを提供するための十分な情報を返しません。つまり、CallableStatement を使用すると、ResultSetMetaData は NULL を返す場合があります。

次の例は、1 増やされた inOutParam の値を戻すストアド プロシージャと、ResultSet として inputParam を介して渡されたストリングを示しています :

例 24.3. ストアド プロシージャ

CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), \ 
                                        INOUT inOutParam INT)
BEGIN
    DECLARE z INT;
    SET z = inOutParam + 1;
    SET inOutParam = z;

    SELECT inputParam;

    SELECT CONCAT('zyxw', inputParam);
END

demoSp プロシージャを Connector/J で使用するには、次の手順に従ってください :

  1. Connection.prepareCall() を使用して、呼び出し可能なステートメントを準備

    JDBC エスケープ シンタックスを使用する必要があり、またパラメータ プレースホルダを囲む丸括弧 (()) はオプションではないので注意。

    例 24.4. Connection.prepareCall() の使用

    import java.sql.CallableStatement;
    
    ...
    
        //
        // Prepare a call to the stored procedure 'demoSp'
        // with two parameters
        //
        // Notice the use of JDBC-escape syntax ({call ...})
        //
    
        CallableStatement cStmt = conn.prepareCall("{call demoSp(?, ?)}");
    
    
    
        cStmt.setString(1, "abcdefg");

    注意.? 出力パラメータのサポートのためにドライバが行うメタデータの取り出しにより、Connection.prepareCall() は拡張可能なメソッドです。性能上の理由から、コード内で CallableStatement インスタンスを使用して、Connection.prepareCall() への不要な呼び出しを最小限に抑えてください。

  2. 出力パラメータ ( ある場合は ) を登録

    出力パラメータ( ストアド プロシージャの作成時に OUT または INOUT と特定されたパラメータ ) の値を取り出すには、JDBC は、CallableStatement インターフェイスの様々な registerOutputParameter() メソッドを使用して、ステートメントの実行の前にそれらを特定することを要求します :

    例 24.5. 出力パラメータの登録

    import java.sql.Types;
    ...
    //
    // Connector/J supports both named and indexed
    // output parameters. You can register output
    // parameters using either method, as well
    // as retrieve output parameters using either
    // method, regardless of what method was
    // used to register them.
    //
    // The following examples show how to use
    // the various methods of registering
    // output parameters (you should of course
    // use only one registration per parameter).
    //
    
    //
    // Registers the second parameter as output, and
    // uses the type 'INTEGER' for values returned from
    // getObject()
    //
    
    cStmt.registerOutParameter(2, Types.INTEGER);
    
    //
    // Registers the named parameter 'inOutParam', and
    // uses the type 'INTEGER' for values returned from
    // getObject()
    //
    
    cStmt.registerOutParameter("inOutParam", Types.INTEGER);
    ...
    

  3. 入力パラメータ ( ある場合は ) を設定

    入力および in/out パラメータは、PreparedStatement オブジェクトを対象として設定されます。しかし、CallableStatement はまた、名前によってパラメータの設定をサポートします :

    例 24.6. CallableStatement 入力パラメータの設定

    ...
    
        //
        // Set a parameter by index
        //
    
        cStmt.setString(1, "abcdefg");
    
        //
        // Alternatively, set a parameter using
        // the parameter name
        //
    
        cStmt.setString("inputParameter", "abcdefg");
    
        //
        // Set the 'in/out' parameter using an index
        //
    
        cStmt.setInt(2, 1);
    
        //
        // Alternatively, set the 'in/out' parameter
        // by name
        //
    
        cStmt.setInt("inOutParam", 1);
    
    ...

  4. CallableStatement を実行し、すべての結果セット、もしくは出力パラメータを呼び出す

    CallableStatement はいかなる Statement execute メソッド ( executeUpdate() 、executeQuery() 、または execute() ) の呼び出しもサポートしますが、最も呼び出しやすいメソッドは execute() で、ストアド プロシージャが結果セットを返すかが事前に分からなくても問題ありません :

    例 24.7. 結果と出力パラメータの値を呼び出す

    ...
    
        boolean hadResults = cStmt.execute();
    
        //
        // Process all returned result sets
        //
    
        while (hadResults) {
            ResultSet rs = cStmt.getResultSet();
    
            // process result set
            ...
    
            hadResults = rs.getMoreResults();
        }
    
        //
        // Retrieve output parameters
        //
        // Connector/J supports both index-based and
        // name-based retrieval
        //
    
        int outputValue = cStmt.getInt(2); // index-based
    
        outputValue = cStmt.getInt("inOutParam"); // name-based
    
    ...

24.4.5.1.4. AUTO_INCREMENT カラム値の呼び出し

JDBC API のバージョン 3.0 より前では、自動インクリメント、または識別カラムをサポートするデータベースからキー値を呼び出す標準の方法がありませんでした。MySQL に古い JDBC ドライバを使用すると、Statement インターフェイスでいつでも MySQL 特有のメソッドを使用でき、また、AUTO_INCREMENT キーを持つテーブルに INSERT を発行した後で、クエリ SELECT LAST_INSERT_ID() を発行することができました。MySQL 特有メソッド呼び出しの使用はポータブルではなく、AUTO_INCREMENT キーの値を得るために SELECT を発行するには、データベースまでもう一度往復する必要があり、最も効率的とはいえません。次のコード部品は、AUTO_INCREMENT 値を呼び出す 3 つの方法を実証します。まず、AUTO_INCREMENT キーを呼び出し、JDBC-3.0 にアクセスする必要がある場合に推奨されるメソッドである、新しい JDBC-3.0 メソッド getGeneratedKeys() 使用を実証します。その次の例では、標準の SELECT LAST_INSERT_ID() クエリを使用して、同じ値を呼び出す方法を挙げます。最後の例では、insertRow() メソッドを使用する場合に、更新可能な結果セットが AUTO_INCREMENT 値を呼び出す方法を示します。

例 24.8. Statement.getGeneratedKeys() を使った AUTO_INCREMENT カラム値の呼び出し

   Statement stmt = null;
   ResultSet rs = null;

   try {

    //
    // Create a Statement instance that we can use for
    // 'normal' result sets assuming you have a
    // Connection 'conn' to a MySQL database already
    // available

    stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                                java.sql.ResultSet.CONCUR_UPDATABLE);

    //
    // Issue the DDL queries for the table for this example
    //

    stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
    stmt.executeUpdate(
            "CREATE TABLE autoIncTutorial ("
            + "priKey INT NOT NULL AUTO_INCREMENT, "
            + "dataField VARCHAR(64), PRIMARY KEY (priKey))");

    //
    // Insert one row that will generate an AUTO INCREMENT
    // key in the 'priKey' field
    //

    stmt.executeUpdate(
            "INSERT INTO autoIncTutorial (dataField) "
            + "values ('Can I Get the Auto Increment Field?')",
            Statement.RETURN_GENERATED_KEYS);

    //
    // Example of using Statement.getGeneratedKeys()
    // to retrieve the value of an auto-increment
    // value
    //

    int autoIncKeyFromApi = -1;

    rs = stmt.getGeneratedKeys();

    if (rs.next()) {
        autoIncKeyFromApi = rs.getInt(1);
    } else {

        // throw an exception from here
    }

    rs.close();

    rs = null;

    System.out.println("Key returned from getGeneratedKeys():"
        + autoIncKeyFromApi);
} finally {

    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException ex) {
            // ignore
        }
    }

    if (stmt != null) {
        try {
            stmt.close();
        } catch (SQLException ex) {
            // ignore
        }
    }
}

例 24.9. SELECT LAST_INSERT_ID() を使った AUTO_INCREMENT カラム値の呼び出し

   Statement stmt = null;
   ResultSet rs = null;

   try {

    //
    // Create a Statement instance that we can use for
    // 'normal' result sets.

    stmt = conn.createStatement();

    //
    // Issue the DDL queries for the table for this example
    //

    stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
    stmt.executeUpdate(
            "CREATE TABLE autoIncTutorial ("
            + "priKey INT NOT NULL AUTO_INCREMENT, "
            + "dataField VARCHAR(64), PRIMARY KEY (priKey))");

    //
    // Insert one row that will generate an AUTO INCREMENT
    // key in the 'priKey' field
    //

    stmt.executeUpdate(
            "INSERT INTO autoIncTutorial (dataField) "
            + "values ('Can I Get the Auto Increment Field?')");

    //
    // Use the MySQL LAST_INSERT_ID()
    // function to do the same thing as getGeneratedKeys()
    //

    int autoIncKeyFromFunc = -1;
    rs = stmt.executeQuery("SELECT LAST_INSERT_ID()");

    if (rs.next()) {
        autoIncKeyFromFunc = rs.getInt(1);
    } else {
        // throw an exception from here
    }

    rs.close();

    System.out.println("Key returned from " + 
                       "'SELECT LAST_INSERT_ID()': " +
                       autoIncKeyFromFunc);

} finally {

    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException ex) {
            // ignore
        }
    }

    if (stmt != null) {
        try {
            stmt.close();
        } catch (SQLException ex) {
            // ignore
        }
    }
}
   

例 24.10. Updatable ResultSets 内の AUTO_INCREMENT カラム値の呼び出し

   Statement stmt = null;
   ResultSet rs = null;

   try {

    //
    // Create a Statement instance that we can use for
    // 'normal' result sets as well as an 'updatable'
    // one, assuming you have a Connection 'conn' to
    // a MySQL database already available
    //

    stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                                java.sql.ResultSet.CONCUR_UPDATABLE);

    //
    // Issue the DDL queries for the table for this example
    //

    stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
    stmt.executeUpdate(
            "CREATE TABLE autoIncTutorial ("
            + "priKey INT NOT NULL AUTO_INCREMENT, "
            + "dataField VARCHAR(64), PRIMARY KEY (priKey))");

    //
    // Example of retrieving an AUTO INCREMENT key
    // from an updatable result set
    //

    rs = stmt.executeQuery("SELECT priKey, dataField "
       + "FROM autoIncTutorial");

    rs.moveToInsertRow();

    rs.updateString("dataField", "AUTO INCREMENT here?");
    rs.insertRow();

    //
    // the driver adds rows at the end
    //

    rs.last();

    //
    // We should now be on the row we just inserted
    //

    int autoIncKeyFromRS = rs.getInt("priKey");

    rs.close();

    rs = null;

    System.out.println("Key returned for inserted row: "
        + autoIncKeyFromRS);

} finally {

    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException ex) {
            // ignore
        }
    }

    if (stmt != null) {
        try {
            stmt.close();
        } catch (SQLException ex) {
            // ignore
        }
    }
}


   

上記の例のコードを使用する時は、次の出力を取得してください : getGeneratedKeys() から戻されたキー : 1 SELECT LAST_INSERT_ID() から戻されたキー : 1 挿入された行に戻されたキー : 2 関数の値は接続へスコープされているため、SELECT LAST_INSERT_ID() クエリの使用がしにくい場合がありますので注意してください。したがって、他のクエリが同じ接続上で発生する場合、値は上書きされます。一方、getGeneratedKeys() メソッドは Statement インスタンスにスコープされているので、他のクエリが同じ接続上で発生しても使用が可能ですが、同じ Statement インスタンス上では使用できません。

Copyright c 1997, 2010, Oracle and/or its affiliates. All rights reserved. Legal Notices
Top / Previous / Next / Up / Table of Contents
© 2010, Oracle Corporation and/or its affiliates

無料CGI PHPスクリプト | 新着情報スクリプト | 営業日カレンダー | PHPマニュアル | MySQLマニュアル | PEARマニュアル

Copyright (c) 2010 jmcodex.com All rights reserved.