MySQL Connector/J は一般的に利用可能な Sun の JDBC 対応テストスイートの全バージョンで、すべてのテストにパスしています。ただし、JDBC 仕様は、特定の機能をどのように実装するか、もしくは、その仕様は実装でリーウェイを許可するかについての点で曖昧な部分が多くみられます。
このセクションでは、特定の実装の決定が MySQL Connector/J の使用方法におよぼす影響の詳細を、インターフェイスごとに説明します。
Blob
Connector/J 3.1.0 からは、プロパティ
'emulateLocators=true' を JDBC URL
に加えることで、ロケータで Blob
をエミュレートすることができます。この方法を使うと、他のデータを取り出すまでドライバは実際の
Blob データのローディングを遅らせ、その後
blob データ ストリームで摘出メソッド (
getInputStream()
、getBytes()
、など )
を使用します。
これを実行するには、実際の Blob の名称に カラムの値を伴うカラム エイリアスを使用する必要があります。その例は :
SELECT id, data as 'data' from blobtable
これを行うには、次のルールに従う必要があります :
SELECT
はまた、ただひとつのテーブルを参照していなければならず、そのテーブルはプライマリ
キーを持っている必要があります。
SELECT
はプライマリ
キーを組成するすべてのカラムをカバーする必要があります。
Blob 実装はインプレース変更を許可しません
( DatabaseMetaData.locatorsUpdateCopies()
メソッドで報告されたように、それらはコピーです
) 。このため、対応する
PreparedStatement.setBlob()
または
ResultSet.updateBlob()
(
更新可能な結果セットの場合 )
メソッドを使い、変更をデータベースに戻して保存するようにしてください。
CallableStatement
Connector/J 3.1.1 からは、ストアド
プロシージャが、CallableStatement
インターフェイスを介して MySQL バージョン
5.0
以降に接続している時にサポートされるようになりました。現在は、CallableStatement
の getParameterMetaData()
メソッドはサポートされていません。
Clob
Clob 実装はインプレース変更を許可しません
( DatabaseMetaData.locatorsUpdateCopies()
メソッドで報告されたように、それらはコピーです
)
。このため、PreparedStatement.setClob()
メソッドを使用して、変更をデータベースに戻して保存するようにしてください。JDBC
API は ResultSet.updateClob()
メソッドを持っていません。
Connection
MM.MySQL
の旧バージョンとは異なり、isClosed()
メソッドはサーバを ping
して生きているかを判断しません。JDBC
仕様に従い、closed()
が接続で呼び出された時にのみ true
を戻します。接続がまだ有効か確認したい場合は、SELECT
1
などの簡単なクエリを発行してください。接続が無効になっていれば、ドライバは例外を投入します。
DatabaseMetaData
外部キー情報 (
getImportedKeys()
/getExportedKeys()
および getCrossReference()
) は
InnoDB
テーブルでのみ入手可能です。ただし、ドライバは
SHOW CREATE TABLE
を使用してこの情報を取り出すので、他の保存エンジンが外部キーをサポートする場合、ドライバはそれらも透過的にサポートします。
PreparedStatement
PreparedStatements は、MySQL がプリペアド
ステートメント機能を持たないため、ドライバによって実装されます。これにより、ドライバがクライアントの完全な
SQL
のパーサを持つことが要求されるため、ドライバは
getParameterMetaData()
または
getMetaData()
を実装しません。
MySQL Connector/J 3.1.0 からは、サーバ側プリペアド ステートメントおよびバイナリ エンコードされた結果セットは、サーバがそれらをサポートする場合に使用されます。
setBinaryStream()
、setAsciiStream()
、setUnicodeStream()
、setBlob()
、または
setClob()
を介して設定された
large
パラメータとサーバ側プリペアド
ステートメントを使用する際は注意してください。非
large パラメータに変更された large
パラメータとステートメントを再実行したい場合、clearParameters()
を呼び出し、すべてのパラメータを再度設定する必要があります。その理由は以下です
:
サーバ側プリペアド
ステートメントとクライアント側エミュレーションの双方の間、大きなデータは
PreparedStatement.execute()
が呼び出された時にのみ交換されます。
それが終了したら、クライアント側のデータの読み取りに使用されたストリームは閉じられ ( JDBC 仕様により ) 、再度読み取ることはできません。
パラメータが large から 非 large
へ変更する場合、ドライバはプリペアド
ステートメントのサーバ側の状況をリセットし、変更するパラメータが前の大きな値になり代わるの許可する必要があります。これにより、サーバに送られたすべての大きなデータが取り除かれ、したがってデータの再送を
setBinaryStream()
、setAsciiStream()
、setUnicodeStream()
、setBlob()
、または
setClob()
を介して要求します。
結果的に、パラメータのタイプを非 large
にしたい場合は、再実行される前に、clearParameters()
を呼び出し、プリペアド
ステートメントのすべてのパラメータを再度設定する必要があります。
ResultSet
デフォルトにより、ResultSets は完全に摘出され、メモリに保存されます。ほとんどの場合において、これは最も効果的な操作方法であり、MySQL の設計により、ネットワーク プロトコルはより簡単に実装できます。多大な行や大きな値を持つ ResultSets を扱っていて、要求されるメモリのために JVM に十分なスペースを割り振れない場合は、ドライバに結果を一行ごとにストリームし戻すよう指示することができます。
この機能を有効にするには、次の方法で Statement インスタンスを作成する必要があります。
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(Integer.MIN_VALUE);
フェッチのサイズが
Integer.MIN_VALUE
の、前進専用、読み取り専用のコンビネーションは、行ごとに結果セットをストリームするようドライバに指示する信号として機能します。この後、このステートメントで作成された結果セットは行ごとに摘出されます。
このアプローチには注意点がいくつかあります。接続にクエリを発行する前に、結果セットのすべての行を読まなければならず、さもなければ例外が投入されます。
これらのステートメントが保持するロックが解除されうる最も早い時点は
( InnoDB
などの他の保存エンジンの
MyISAM
テーブル レベル
ロック、または 行レベル ロックであっても
) 、ステートメントが完遂された時です。
ステートメントがトランザクションの範囲内にある時は、ロックはトランザクションが完遂した時に解除されます ( つまり、ステートメントが先に完遂される必要があります ) 。他のほとんどのデータベースと同じく、ステートメントで保留になっているすべての結果が読み取られるまで、またはステートメントのアクティブな結果セットが閉じられるまで、ステートメントは完遂されません。
したがって、結果のストリーミングを使用する場合、結果セットを作成しているステートメントが参照するテーブルへの並行アクセスを維持したいのであれば、それらをできるだけ速く処理してください。
ResultSetMetaData
isAutoIncrement()
メソッドは MySQL
サーバ 4.0
以降を使用している時にのみ作動します。
Statement
JDBC ドライバの 3.2.1
以前のバージョンを使用し、5.0.3
以前のバージョンのサーバに接続している場合、上記のように結果セットのストリーミングをトグルする以外では、setFetchSize()
は無効です。
Connector/J 5.0.0
以降は、Statement.cancel()
と
Statement. setQueryTimeout()
両方へのサポートを含みます。両方ともに
MySQL 5.0.0 以降が必要で、KILL
QUERY
文を発行するために別の接続が要求されます。setQueryTimeout()
の場合、その実装はタイムアウト機能を扱うために追加のスレッドを作成します。
タイムアウトの期限切れによって取り消されるクエリを実行するスレッドのブロックを解除し、例外として投入する方法が現在はないため、setQueryTimeout()
へのステートメントの取り消しの失敗は、そのまま失敗するのではなく、それ自体を
RuntimeException
として宣言する場合があります。
MySQL はSQL カーソルをサポートせず、JDBC ドライバはそれらをエミュレートしないので、"setCursor- Name()" は無効です。