[???] /
[Java FAQ] / [S134]
S134: JDBC(日本語の扱い)
[S134-Q01]
JDBCドライバを使って、データベースと日本語データをやりとりするには?
[S134-A01]
日本語対応のJDBCドライバを使用することにより、特に問題なく日本語
データを取り扱うことができます。
JDK付属のJDBCドライバとしては、JDK1.2に付属のJDBC-ODBCブリッジ
ドライバは日本語に対応しています。
JDK1.1に付属のJDBC-ODBCブリッジドライバでは、日本語データを正しく
扱えないことが確認されています。
日本語対応していないJDBCドライバを使用する場合は、S134-03 を参
照してください。
また、次のURLは大変参考になるので、一度目を通すことをお薦めします。
http://ux01.so-net.ne.jp/~kikuta/jdbcnote/jdbcnote.html
[S134-Q02]
JDBCドライバで日本語名のテーブルにアクセスするにはどうすれば?
[S134-A02]
日本語で定義したテーブル名、フィールド名をSQL文の文字列内で
指定する時には ESC文字+ダブルクォーテーションマークで囲むよう
にします。
例)
int id = 1002003004;
String name = "'にっぽん たろう'";
String sqltxt ="INSERT INTO \"日本語 テーブル\"" +
"(\"ID Number\",\"氏 名\") "+
"VALUES("+id+","+name+")";
日本語に対応しているJDBCドライバを用いている場合はこれだけ
でアクセスできます。なお、この方法については、次の環境で確認
がされています。JDKのバージョンはJDK1.2以降です。
PostgreSQL 6.5.2 + Linux
sun.jdbc.odbc.JdbcOdbcDriver(JDK1.3版)+Access97+Windows95
Oracle JDBC V8.0.5.0.4(Thin) classes111.zip+Oracle8+SunOS
日本語に対応していないJDBCドライバを用いている場合は、SQL
文を変換する必要があるでしょう。S134-03 を参考にして下さ
い。
[S134-Q03]
日本語化されていないJDBCドライバを使って、データベースと日本語
データをやりとりするには?
[S134-A03]
これから開発を始めるのであれば、日本語化されているJDBCドライ
バを使いましょう。
日本語化されていないJDBCドライバを使わざるを得ない場合は、次を
参考にして下さい。
-- JDK1.1以降を使用する場合
日本語化されていないJDBCドライバで日本語のデータをやりとりす
るのに保証された方法はありません。経験的に、次のようにすると
扱えることがわかっています。
* http://ux01.so-net.ne.jp/~kikuta/jdbcnote/jdbcnote.html を
参考にさせていただきました。
(検索)
1.ストリームを使う
ResultSet rs = stmt.executeQuery(query);
InputStreamReader isr = new InputStreamReader(
rs.getAsciiStream(index)
);
BufferedReader in = new BufferedReader(isr);
StringWriter sw = new StringWriter();
try {
int c;
while((c = in.read()) != -1)
sw.write(c);
in.close();
} catch (IOException e){
}
String result = sw.toString();
2.StringクラスのgetBytes()メソッドを使う
ResultSet rs = stmt.executeQuery(query);
String s = rs.getString(index);
try {
String result = new String(s.getBytes("8859_1"));
} catch (IOException e){
}
どちらも、検索した日本語データがresultに入ります。
(挿入・更新・削除)
String sqltxt ="INSERT INTO \"日本語 テーブル\"" +
"(\"ID Number\",\"氏 名\") "+
"VALUES("+id+","+name+")";
sqltxt = new String(sqltext.getBytes("SJIS"),"8859_1");
int num = stmt.executeUpdate(sqltxt);
* なぜ、これでうまくいくのでしょう?
JDBC-ODBCブリッジドライバを使っていて、ODBCドライバでは
文字列型のデータを Shift-JISコードのバイト列として扱って
いるとします。
このとき、"漢字OK"という文字列のバイトデータは 1バイトず
つ16進数で表現すると、次のようになります。
8A BF 8E 9A 4F 4B
このバイトデータを ResultSet.getString()で取り出すと、日
本語に対応していないJDBCドライバは、 1バイトデータを Uni-
codeに変換する処理を行い、2バイトの上位バイトに0x00を、
下位バイトに 1バイトのデータを埋め込みます。
0x008A, 0x00BF, 0x008E, 0x009A, 0x004F, 0x004B
したがって、この Unicode文字列をISO 8859-1でエンコーディ
ングし、8A BF 8E 9A 4F 4B に戻し、これを Shift-JISコード
のバイト列から Unicode文字列に変換してあげれば良いのです。
挿入・更新・削除の場合は SQL文全体に対してこの逆の操作を
行っているのです。
* これらの方法の問題点:
日本語に対応していないJDBCドライバについて、次のような前
提を置いていることです。
・データ更新時には Unicode文字列の上位 1バイトを無条件
で削除する。
・問い合わせ時には上位1バイトに無条件で0x00を、下位 1
バイトに 1バイトのデータを埋め込んだ作ったバイト列を
Unicode文字列として返す。
さらに詳細を知りたい場合は、
http://java-house.etl.go.jp/ml/archive/j-h-b/011682.html#body
を参考にして下さい。
-- JDK1.0.2を使用する場合
JDBCドライバの状況はJDK1.1を使用する場合と同様です。ただ
し、String型データのエンコーディングを指定するメソッドが
提供されていませんので、この機能を自作する必要があります。
[S134-Q04]
日本語対応していないJDBCドライバを使うときに、どうやって指定する文字
のエンコーディングを決めるのですか?
[S134-A04]
基本的には、JDBCドライバと通信するプログラムが動作するプラットフォー
ムに合わせて決めます。
JDBCドライバのタイプごとに、指針を示します。
ClientとServerが接続している部分を -|- と表記します。
1.Type1(JDBC-ODBC Bridge)
Java Program - JDBC - ODBC -|- DB Server
ODBCがサポートしている文字コードを指定します。
例えば、Java ProgramをWindowsで動かす場合は、次のようになります。
Windows95 | WindowsNTなど
Java Program - JDBC - ODBC -|- DB Server
(Unicode) (SJIS) (自動)
ODBC -|- DB Server の部分では、Middlewareが入る場合もありますが、
通常は Middlewareでの文字コードの変換は自動的に対応してくれるはず
なので省略します。
例えば、OracleとSQL*Netを使った場合は、次のようになります。
Windows95 | Solaris
Java Program - JDBC - ODBC - SQL*Net -|- SQL*Net - Oracle
(Unicode) (SJIS) (SJIS) (自動) (EUC)
2.Type2
Java Program - JDBC - Middleware -|- Middleware - DB Server
Middlewareがサポートしている文字コードを指定します。
例えば、Java ProgramをWindows95で動かし、DB ServerをSolarisで動か
す場合は、次のようになります。
Windows95 | Solaris
Java Program - JDBC - Middleware -|- Middleware - DB Server
(Unicode) (SJIS) (自動) (EUC)
3.Type3
Java Program - JDBC -|- Middleware - DB Server
JDBCとMiddlewareの性能によって変わるはずです。通常は、Type4と
同様に考えれば良いと思います。
4.Type4
Java Program - JDBC -|- DB Server
DB Server がどの文字コードを前提として動作しているかを調べ、そ
の文字コードを指定します。
例えば、Java ProgramをWindows95で動かし、EUCの文字コードを前提
として動作しているSolaris上のDB Serverと接続する場合は、次のよ
うになります。
Windows95 | Solaris
Java Program - JDBC -|- DB Server
(Unicode) (EUC)
Web (Three Tier Architecture) System などでも、上記の考え方を
あてはめれば、想像がつくはずです。
例えば、Web BrowserをWindows95で動かし、Windows NT上のServlet
を通して、EUCの文字コードを前提として動作しているSolaris上の
DB Serverとデータのやりとりをする場合は、次のようになります。
Windows95 | Windows NT | Solaris
Web Browser -|- Web Server+Servlet - JDBC -|- DB Server
(SJIS) (Unicode) (EUC)
[S134-Q05]
Oracleの表のLONG型の列に、ある日本語コードのテキストデータを入れたいのですが?
[S134-A05]
通常のカラムとしてデータを設定してみましょう。
JDK1.1のJDBCの仕様ではストリームを通して正しい国際化処理を期待
するのは無理です。setUnicodeStream(), setAsciiStream()などのス
トリームを使うと,データベース内のデータは文字化けしてしまいま
す。
contributor: KOYAMA. Hiroshi
コメントの送り先:Java FAQ BBS