The Ja-Jakarta ProjectTomcat Servlet/JSP コンテナ

リンク

ユーザガイド

リファレンス

Tomcat開発

Tomcat5 サーブレット/JSP コンテナ

JNDIデータソースの手引き

Printer Friendly Version
印刷用
バージョン
目次

はじめに
データベース接続プール(DBCP)の設定
Tyrex接続プール
DBCP以外のソリューション
OCIクライアントを使用したOracle 8i
一般的な問題

はじめに

JNDIデータソースの設定はJNDIリソースの手引きでおおまかな説明をしていますが、 個々の設定項目への指定は少々特殊であるという、 tomcat-userからのフィードバックがありました。

ここにあるのは、tomcat-userメーリングリストに投稿された主要なデータベース用のいくつかの設定例とデータベースを扱うための一般的なヒントです。

これらの情報は、tomcat-userメーリングリストへ投稿された設定やフィードバックに由来しています。 より多くの人々が使えるかも知れないと思うテスト済みの他の設定がある場合や、 何らかによりこのセクションを改善できると思った場合は、それをレポートしてください。

データベース接続プール(DBCP)の設定

DBCPはJDBC2.0をサポートします。システムが1.4JVMを使っている場合はDBCPはJDBC3.0をサポートします。 もしDBCPとJDBC3.0の機能を1.4JVMで使っている場合は知らせてください。

設定パラメータの完全な一覧は DBCP JavadocsのBasicDataSourceクラスを参照してください。

インストール

DBCP はJakarta-Commons Database Connection Poolを使います。 これはいくつかのJakarta-Commonsコンポーネントに依存します。:

  • Jakarta-Commons DBCP 1.0
  • Jakarta-Commons Collections 2.0
  • Jakarta-Commons Pool 1.0
これらのjarファイルはJDBCドライバと一緒に $CATALINA_HOME/common/libにインストールします。
注意:サードパーティ製のドライバはzipファイルではなく、jarファイルにしてください。 Tomcatは$CATALINA_HOME/common/lib/*.jarのみをクラスパスに追加します。
注意: これらのjarファイルを/WEB-INF/lib$JAVA_HOME/jre/lib/ext、 その他の場所にインストールしないでください。 $CATALINA_HOME/common/lib以外の場所にインストールすると問題が発生するでしょう。

データベース接続プールのリーク予防策

データベース接続プールは、データベースへの接続のプールを生成・管理します。 既存のデータベースへの接続を再生し再利用することは、新規に接続を開くよりもさらに効率的です。

接続のプーリングには一つ問題があります。WebアプリケーションはResultSet、 Statement、およびConnectionを明示的に閉じなければなりません。 Webアプリケーションがこれらのリソースを閉じていないと、データベース接続の"リーク"となり、 再利用不可能という結果になります。 有効な接続が無くなると、ついにはWebアプリケーションのデータベース接続失敗という結果になります。

この問題には解決策があります。Jakarta-Commons DBCPはこれらの放棄されたデータベース接続を追跡し、 回復するように設定できます。 しかも接続を回復するだけでなく、これらのリソースを開始し閉じなかったコードのスタックトレースを生成できます。

放棄されたデータベース接続を解放し、再生するようにDBCPデータソースを設定するには、 次のparamaterをDBCPデータソースのResourceにあるResourceParamsの設定に追加します。:

            <parameter>
              <name>removeAbandoned</name>
              <value>true</value>
            </parameter>
有効なデータベース接続が動作する場合、低レベルのDBCPは見つかったすべての放棄されたデータベース接続を回復し再生します。 デフォルトはfalseです。

データベース接続が放棄されたと見なすまでのアイドル秒数を設定するには、 removeAbandonedTimeoutパラメータを使います。

            <parameter>
              <name>removeAbandonedTimeout</name>
              <value>60</value>
            </parameter>
接続が放棄され、解放されるまでのデフォルトタイムアウトは300秒です。

データベース接続リソースが放棄されたコードのスタックトレースをDBCPにログ採取させたい場合は、 logAbandonedパラメータをtrueに設定します。

            <parameter>
              <name>logAbandoned</name>
              <value>true</value>
            </parameter>
デフォルトはfalseです。

MySQLのDBCP設定例

0. はじめに

動作が報告されているMySQLのバージョンとmm.mysql JDBCドライバ:

  • MySQL 3.23.47、InnoDBを使用したMySQL 3.23.47、MySQL 4.0.1alpha
  • mm.mysql 2.0.14 (JDBCドライバ)
新しいMySQL mm.mysql 3.0ドライバをテストした場合は、その結果をレポートしてください。

1. MySQLの設定

他のやり方では問題の原因になることがあるので、次の手順を確実に行ってください。

新しいテスト用ユーザ、新しいデータベースおよび単一のテスト用テーブルを作成します。 MySQLユーザには必ずパスワードを割り当てなければなりません。 ドライバが空のパスワードで接続しようとすると失敗します。

mysql> GRANT ALL PRIVILEGES ON *.* TO javauser@localhost 
    ->   IDENTIFIED BY 'javadude' WITH GRANT OPTION;
mysql> create database javatest;
mysql> use javatest;
mysql> create table testdata (
    ->   id int not null auto_increment primary key,
    ->   foo varchar(25), 
    ->   bar int);
注意:一度テストが成功したら上記のユーザは削除しましょう。

次に、テストデータ用のテーブルにテストデータを入れます。

mysql> insert into testdata values(null, 'hello', 12345);
Query OK, 1 row affected (0.00 sec)

mysql> select * from testdata;
+----+-------+-------+
| ID | FOO   | BAR   |
+----+-------+-------+
|  1 | hello | 12345 |
+----+-------+-------+
1 row in set (0.00 sec)

mysql>

2. server.xmlの設定

TomcatのJNDIデータソースの設定を行うには$CATALINA_HOME/conf/server.xml にリソースの宣言を追加します。

この記述をexamplesコンテキストの</Context>タグの間に追加し、 </Host>タグでlocalhost定義を閉じます。

<Context path="/DBTest" docBase="DBTest"
        debug="5" reloadable="true" crossContext="true">

  <Logger className="org.apache.catalina.logger.FileLogger"
             prefix="localhost_DBTest_log." suffix=".txt"
             timestamp="true"/>

  <Resource name="jdbc/TestDB"
               auth="Container"
               type="javax.sql.DataSource"/>

  <ResourceParams name="jdbc/TestDB">
    <parameter>
      <name>factory</name>
      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
    </parameter>

    <!-- プール内のデータベース接続の最大数。 mysqld max_connectionsが
         すべてのデータベース接続を処理するのに充分な大きさに設定されていることを
         確認すること。0を設定すると無制限になる。
         -->
    <parameter>
      <name>maxActive</name>
      <value>100</value>
    </parameter>

    <!-- アイドルとしてプール内に残すデータベース接続の最大数。
         0を設定すると無制限になる。
         -->
    <parameter>
      <name>maxIdle</name>
      <value>30</value>
    </parameter>

    <!-- データベース接続が利用可能になるまでの最大待ち時間(ミリ秒単位)
         この設定例は10秒。このタイムアウトを超過すると例外が投げられる。
         -1を設定すると無限に待つ。
         -->
    <parameter>
      <name>maxWait</name>
      <value>10000</value>
    </parameter>

    <!-- データベース接続用のMySQLデータベースユーザ名とパスワード -->
    <parameter>
     <name>username</name>
     <value>javauser</value>
    </parameter>
    <parameter>
     <name>password</name>
     <value>javadude</value>
    </parameter>

    <!-- mm.mysql JDBCドライバクラス名 -->
    <parameter>
       <name>driverClassName</name>
       <value>org.gjt.mm.mysql.Driver</value>
    </parameter>

    <!-- MySQLデータベースへ接続するためのJDBC接続URL。
         URLの引数 autoReconnect=true はmysqldが接続と閉じた場合に
         mm.mysql JDBCドライバが自動的に再接続することを保証する。
         デフォルトではmysqldは8時間後にアイドル状態となった接続を閉じる。
         -->
    <parameter>
      <name>url</name>
      <value>jdbc:mysql://localhost:3306/javatest?autoReconnect=true</value>
    </parameter>
  </ResourceParams>
</Context>

3. web.xmlの設定

テストアプリケーションにWEB-INF/web.xmlを作成します。

<?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app PUBLIC
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <description>MySQL Test App</description>
  <resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/TestDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
</web-app>

4. テスト用コード

後で使うために、簡単なsimple.jspを作成します。

<html>
  <head>
    <title>DB Test</title>
  </head>
  <body>

  <%
    foo.DBTest tst = new foo.DBTest();
    tst.init();
  %>

  <h2>Results</h2>
    Foo <%= tst.getFoo() %><br/>
    Bar <%= tst.getBar() %>

  </body>
</html>

また、実際に新しいデータソースと接続プールを使うJavaクラスを作成します。 注意: このコードは製品として実用できるだけの品質を確保していません。簡単なテストのみに使えます。

package foo;

import javax.naming.*;
import javax.sql.*;
import java.sql.*;

public class DBTest {

  String foo = "Not Connected";
  int bar = -1;
    
  public void init() {
    try{
      Context ctx = new InitialContext();
      if(ctx == null ) 
          throw new Exception("Boom - No Context");

      DataSource ds = 
            (DataSource)ctx.lookup(
               "java:comp/env/jdbc/TestDB");

      if (ds != null) {
        Connection conn = ds.getConnection();
              
        if(conn != null)  {
            foo = "Got Connection "+conn.toString();
            Statement stmt = conn.createStatement();
            ResultSet rst = 
                stmt.executeQuery(
                  "select id, foo, bar from testdata");
            if(rst.next()) {
               foo=rst.getString(2);
               bar=rst.getInt(3);
            }
            conn.close();
        }
      }
    }catch(Exception e) {
      e.printStackTrace();
    }
 }

 public String getFoo() { return foo; }
 public int getBar() { return bar;}
}

最後に、DBTest.warというwarファイルとして、 またはDBTestという名前のサブディレクトリとして $CATALINA_HOME/webappsにWebアプリケーションを配備します。

配備したら、苦労した成果を見るために、ブラウザで http://localhost:8080/DBTest/test.jspを開きましょう。

Oracle 8i

0. はじめに

私たちはOracle DBAではないので、このセクションに関するコメントの提供者に感謝します。

Oracleでは通常わかっていること以外にも、MySQL用の設定からは少々の変更が必要です。 まず、デフォルトではTomcatは$CATALINA_HOME/common/libにインストールされている、 *.jarファイルのみを使うので、classes111.zipclasses12.zip は拡張子を.jarにリネームする必要があります。 jarファイルはzipファイルなので、解凍してこれらのファイルをjarにする必要はありません。単純にリネームするだけで充分です。 さらに知っておくべきことがあります。JDK1.4で使ってTomcat4.0の(早期)バージョンを動かす場合は、 classes12.zipを解凍し、javax.sql.*階層のクラスを削除して再度jar化しないと読み込まれません。

1. server.xmlの設定

上記のMySQLの設定と同様のやり方でserver.xmlファイルのデータソースの定義をする必要があります。 これは、ユーザscott、パスワードtigerで、mysidというsidにあるmyschemaというスキーマに接続する、 thinドライバを使ったmyoracleというデータソースの定義です。 (注意:thinドライバを使った場合はsidはtnsnameと同一ではありません。)

OCIドライバを使う場合は単純にURL文字列中のthinをociに変更するだけです。

<Resource name="jdbc/myoracle" auth="Container"
              type="javax.sql.DataSource"/> 

<ResourceParams name="jdbc/myoracle">
  <parameter>
    <name>factory</name>
    <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
  </parameter>
  <parameter>
    <name>driverClassName</name>
    <value>oracle.jdbc.driver.OracleDriver</value>
  </parameter>
  <parameter>
    <name>url</name>
    <value>jdbc:oracle:thin:myschema@127.0.0.1:1521:mysid</value>
  </parameter>
  <parameter>
    <name>username</name>
    <value>scott</value>
  </parameter>
  <parameter>
    <name>password</name>
    <value>tiger</value>
  </parameter>
  <parameter>
    <name>maxActive</name>
    <value>20</value>
  </parameter>
  <parameter>
    <name>maxIdle</name>
    <value>10</value>
  </parameter>
  <parameter>
    <name>maxWait</name>
    <value>-1</value>
  </parameter>
</ResourceParams>

2. web.xmlの設定

アプリケーションのweb.xmlファイルを作成するときには、 DTDで定義された要素の順序に従っていることを確認してください。

<resource-ref>
 <description>Oracle Datasource example</description>
 <res-ref-name>jdbc/myoracle</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
</resource-ref>

3. コードの例

データソースのコードをこのように書き換えれば上記のサンプルアプリケーションと同じものが使えます。 (データベースインスタンス、テーブル等は作成したものと想定します。)

Context initContext = new InitialContext();
Context envContext  = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
Connection conn = ds.getConnection();
//etc.
PostgreSQL

0. はじめに

PostgreSQLはOracleと同様のやり方で設定できますが、完全に同等ではないことを改めて強調しておきます。 これらの点はまだテストされていないため、フィードバックを高く評価したいと思います。

1. server.xmlの設定

<Resource name="jdbc/postgres" auth="Container"
          type="javax.sql.DataSource"/> 

<ResourceParams name="jdbc/postgres">
  <parameter>
    <name>factory</name>
    <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
  </parameter>
  <parameter>
    <name>driverClassName</name>
    <value>org.postgresql.Driver</value>
  </parameter>
  <parameter>
    <name>url</name>
    <value>jdbc:postgresql://127.0.0.1:5432/mydb</value>
  </parameter>
  <parameter>
    <name>username</name>
    <value>myuser</value>
  </parameter>
  <parameter>
    <name>password</name>
    <value>mypasswd</value>
  </parameter>
  <parameter>
    <name>maxActive</name>
    <value>20</value>
  </parameter>
  <parameter>
    <name>maxIdle</name>
    <value>10</value>
  </parameter>
  <parameter>
    <name>maxWait</name>
    <value>-1</value>
  </parameter>
</ResourceParams> 

2. web.xmlの設定

<resource-ref>
 <description>postgreSQL Datasource example</description>
 <res-ref-name>jdbc/mydb</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
</resource-ref>
Tyrex接続プール
はじめに

Tomcat5はトランザクション管理とTyrex 1.0 を使ったリソース設定のサポートを提供します。 ユーザはJTA/JCAリソースをjavax.transaction.UserTransactionと同様にJNDI名前空間より取得できます。

必要なJARファイルのインストール

WebアプリケーションでTyrexを使うには、WebアプリケーションとTomcatがTyrex jarファイルおよびそれが必要とするjarファイルにアクセスする必要があります。 次は必要なjarファイルの一覧およびそれらを入手する場所です:

次のjarファイルは http://tyrex.sourceforge.net/ から入手可能なTyrexバイナリ配布版に含まれています。

  • tyrex-1.0.jar
  • ots-jts_1.0.jar
  • jta_1.0.1.jar
  • xerces-J_1.4.0.jar
同様に、次の2つのjarファイルも必要です:

これらすべての6つのjarファイルはTomcatとWebアプリケーションの両方から見えるように$CATALINA_HOME/common/libに配置する必要があります。

Tyrexの設定

Tyrexのドキュメント(http://tyrex.sourceforge.net/)はTyrexのプロパティの正しく詳細な設定方法を提供します。 例として、Tyrexのドメイン設定XMLファイルで指定された次のTyrex設定を使います。

<domain>
  <name>myDomain</name>
  <resources>
    <dataSource>
      <name>myDatasource</name>
      <jar>/home/david/mm.mysql-2.0.14-bin.jar</jar>
      <class>org.gjt.mm.mysql.jdbc2.optional.MysqlXaDataSource</class>
      <config>
        <user>david</user>
        <password>secret</password>
        <serverName>localhost</serverName>
        <port>3306</port>
        <database>daviddb</database>
      </config>
    </dataSource>
  </resources>
</domain>

いくつかの注意点:

  • jarファイルはフルパスで指定する必要があります。 (相対パスでは、Tyrexはカレントディレクトリを参照します。通常は、そうしません。) URLを指定することもできます。
  • 要素内にネストした全ての要素はデータソースクラスに標準的なsetterメソッドを使ってパラメータとして渡されます。
  • これ以上の設定オプションは、Tyrexの設定方法のより詳細な説明と同様に、 http://tyrex.sourceforge.net/configuration.htmlにあります。

このXML設定ファイルはTomcatのクラスローダがgetResource()メソッドを使って見つけられる場所に配置する必要があります。 WebアプリケーションのWEB-INF/classesディレクトリはとても良い選択です。

Configuring Tomcat

Tyrex XML設定ファイルを配置して用意できたら、JNDI名前空間にTyrexリソースを登録します。 これはTomcatのserver.xmlファイルを使って行います。 重要なパラメータを2つ設定する必要があります。ドメイン設定ファイル名(tyrexDomainConfig)と、 使用するTyrexドメイン名(tyrexDomainName)です。 これらは次のようにEnvironmentパラメータとして設定する必要があります:

<Environment name="tyrexDomainConfig" type="java.lang.String" value="domain-config.xml"/>
<Environment name="tyrexDomainName" type="java.lang.String" value="myDomain"/>

また、リソースの設定を行う必要があります。(Webアプリケーションの<Context>要素中に行います。):

<Resource name="my-datasource" auth="Container" type="tyrex.resource.Resource"/>
<ResourceParams name="my-datasource">
  <parameter>
    <name>name</name>
    <value>myDataSource</value>
  </parameter>
</ResourceParams>

いくつかの注意点:

  • どのようにTyrexを設定していても、リソースの型は常にtyrex.resource.Resourceです。
  • ResourceParamパラメータにはnameのみが必要です。 -- 値はTyrex設定ファイルで指定したリソース名を設定します。
  • Tomcat/JNDIリソースとTyrexリソースの違いに注意してください。(一見、混乱を招きます!)

アプリケーションのコーディング

Tyrexリソースは比較的簡単に使えます。単純にJNDIを使うだけでデータソースを取得できます。

InitialContext initCtx = new InitialContext();
DataSource ds = (DataSource) initCtx.lookup("java:comp/env/my-datasource");
Connection conn = ds.getConnection();
...and so on.

Tyrexは標準のロケーション(java:comp/UserTransaction)からJNDI経由で取得できる、 javax.transaction.UserTransactionも提供します。

DBCP以外のソリューション

これらのソリューションでは、データベースへの単一の接続(テスト以外は推奨しません)、または他のプーリング技術を利用します。

OCIクライアントを使ったOracle 8i
はじめに

OCIクライアントを使ったJNDIデータソースの生成に厳密に取り組まないうちは、上記のOracleとDBCPのソリューションと組み合わせることができます。

OCIドライバを使うにはOracleクライアントのインストールが必要です。Oracle8i(8.1.7)クライアントをCDよりインストールし、 適切なJDBC/OCIドライバ(Oracle8i 8.1.7.1 JDBC/OCIドライバ)をotn.oracle.comからダウンロードします。

[訳注: 日本では Oracle Technology Network Japan ( http://otn.oracle.co.jp/ ) からダウンロードすることも可能です。 ]

After renaming classes12.zip file to classes12.jar for Tomcat, copy it into $CATALINA_HOME/common/lib. You may also have to remove the javax.sql.* classes from this file depending upon the version of Tomcat and JDK you are using.

すべてをひとつにまとめる

$PATHまたはLD_LIBRARY_PATHocijdbc8.dllまたは.soがあること(おそらく$ORAHOME\binにあります)を確認してください。そして、System.loadLibrary("ocijdbc8");を使った簡単なテストプログラムでネイティブライブラリがロードできることも確認してください。

次に、この重要な行を含んだテスト用の簡単なServletまたはJSPを作成します:

DriverManager.registerDriver(new
oracle.jdbc.driver.OracleDriver());
conn =
DriverManager.getConnection("jdbc:oracle:oci8:@database","username","password");

テスト用Servlet/JSPのURLにアクセスしようとして、 元の理由がjava.lang.UnsatisfiedLinkError:get_env_handleであるServletExceptionが発生した場合、 データベースはhost:port:SID形式です。

まず、UnsatisfiedLinkErrorは以下のことを示しています。

  • JDBCクラスファイルとOracleクライアントとのバージョンのミスマッチ。 手がかりは必要なライブラリファイルが見つからない、と述べているメッセージです。 例えば、Oracleバージョン8.1.6のclasses12.zipファイルとバージョン8.1.5のOracleクライアントを使っているかも知れません。 classeXXXs.zipファイルとOracleクライアントソフトウェアのバージョンはマッチしていなければなりません。
  • $PATHLD_LIBRARY_PATHの問題。
  • otnからダウンロードしたドライバは無視して、 $ORAHOME\jdbc\libディレクトリにあるclasses12.zipファイルを使うと動作するという報告があります。

それから、ORA-06401 NETCMN: invalid driver designatorというエラーが発生するかも知れません。

Oracleのドキュメントには次のようにあります。「理由:ログイン(接続)文字列に無効なドライバ指定が含まれています。対処:文字列を修正し、再送信してください。」 データベース接続文字列(host:port:SID形式)をこのように修正してください: (description=(address=(host=myhost)(protocol=tcp)(port=1521))(connect_data=(sid=orcl)))

うーん、もしTNSNamesが解決しているのならこれが必要とは思いません。 - 私はOracle DBAではありませんが。

一般的な問題

ここにはデータベースを使うWebアプリケーションが行き当たる共通の問題と、 それを解決するためのヒントがあります。

データベース接続が断続的に失敗する

TomcatはJVM上で実行しています。JVMはもう使われないJavaオブジェクトを消去するためにガーベジコレクション(GC)を定期的に実行します。 JVMがGCを実行するとき、Tomcat内のコードの実行はフリーズします。 データベース接続を確立するための最大時間がガーベジコレクションに要する時間より小さく設定されている場合、 データベース接続は失敗します。

ガーベジコレクションにどれぐらい時間がかかるのかをデータ採取するには、 Tomcat起動時の環境変数CATALINA_OPTSに引数-verbose:gcを付加します。 verbose gcが有効な場合、毎回のガーベジコレクションにどれぐらい時間がかかったかが $CATALINA_BASE/logs/catalina.outログファイルに含まれます。

JVMが正しく調整されていれば、ガーベジコレクションにかかる時間の99%は1秒以内です。 残りは数秒かかることがあります。GCに10秒以上かかることは例外的です。

データベース接続のタイムアウトが10-15秒に設定されていることを確認してください。 DBCPの場合はmaxWaitパラメータを使って設定します。

接続を手当たり次第に閉じようとしたときに発生する例外

これは、ひとつのリクエストが接続プールからデータベース接続をひとつ取得し、2度閉じると発生します。 接続プールを使っている場合、接続を閉じると接続は他のリクエストで再利用するためにプールへ返却され、 接続は閉じられません。また、Tomcatは平行してリクエストを処理するために複数のスレッドを使います。 これはTomcatでこのエラーが発生するイベントのシーケンスの例です:

  スレッド1で実行中のリクエスト1がデータベース接続を取得する

  リクエスト1がデータベース接続を閉じる

  JVMは実行スレッドをスレッド2に切り替える

  スレッド2で実行中のリクエスト2がデータベース接続を取得する
  (リクエスト1が閉じたばかりのデータベース接続とおなじもの)

  JVMが実行スレッドをスレッド1に切り替える

  リクエスト1がfinallyブロック内で2度目のデータベース接続を閉じる

  JVMが実行スレッドをスレッド2に切り替える

  スレッド2のリクエスト2がデータベース接続を閉じようとするが、
  リクエスト1がすでに閉じれているので失敗する
これは接続プールから取得したデータベース接続を使用する正しいコードの記述例です:
  Connection conn = null;
  Statement stmt = null;  // Or PreparedStatement if needed
  ResultSet rs = null;
  try {
    conn = ... 接続プールからの接続の取得 ...
    stmt = conn.createStatement("select ...");
    rs = stmt.executeQuery();
    ... ResultSetの繰り返し ...
    rs.close();
    rs = null;
    stmt.close();
    stmt = null;
    conn.close(); // 接続プールへの返却
    conn = null;  // 2度閉じないことを確認する
  } catch (SQLException e) {
    ... deal with errors ...
  } finally {
    // 常にResultSetとStatementは閉じられ、
    // 接続はプールへ返却されることを確認してください
    if (rs != null) {
      try { rs.close(); } catch (SQLException e) { ; }
      rs = null;
    }
    if (stmt != null) {
      try { stmt.close(); } catch (SQLException e) { ; }
      stmt = null;
    }
    if (conn != null) {
      try { conn.close(); } catch (SQLException e) { ; }
      conn = null;
    }
  }


[訳注: この文書は阿島 哲夫が翻訳し、 小川 環が校正しました。 日本語訳に対するコメントがあれば、report@jajakarta.orgに送って下さい。]
Copyright © 1999-2003, Apache Software Foundation