MySQL×JDBC×JSP:文字コード
ボクの環境(Mac OSX)で,文字コードでかなり苦戦したので,メモがてら書いておきます.
どこで躓いたか?
今授業で,「データベースにアクセスして,図書を検索する」というのをやっています.それでやっているうちに,何度となく文字化けに悩まされ,何度となく解消してきました.
しかし前日,フォームの入力から図書を検索する,というところで,日本語を入力するとクエリが文字化けし,正確に検索できないという事がありました.というのも,データベースの方の文字コードがLatin-1(ISO-8859-1)に対し,クエリがUTF-8だったからです.
これで,図書一覧は(回りくどい方法でしたが)問題無く*1表示できたし,このままでイケルと思ってたんだけど,入力に日本語が絡んでくると,途端牙を剥いたんですね.
MySQL
create database
まずは,MySQLの方から問題を解決していきます.そもそも,なぜLatin-1なんだ?
試しに,「hoge」というデータベースを作ってみます.
mysql> create database hoge; Query OK, 1 row affected (0.01 sec)
次に,データベースを「hoge」に設定して
show variables like 'character\_set\_%';
とすると,文字コードの一覧が見れます.
mysql> use hoge Database changed mysql> show variables like 'character\_set\_%'; +--------------------------+--------+ | Variable_name | Value | +--------------------------+--------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | +--------------------------+--------+ 7 rows in set (0.00 sec)
と,デフォルトのままでは文字コードの設定ががLatin-1と,相当よろしくない.インストールのときのオプションでミスったのかも.しかしながら,いちいちインストールし直すのも面倒くさいので,簡単なテクニックで解決です.
先ずは「hoge」をドロップしちまって,作り直しましょうか.
mysql> drop database hoge; Query OK, 0 rows affected (0.00 sec)
次に,データベースを作成.この時,オプションを指定します.
mysql> create database hoge collate sjis_japanese_ci; Query OK, 1 row affected (0.02 sec) mysql> use hoge Database changed mysql> show variables like 'character\_set\_%'; +--------------------------+--------+ | Variable_name | Value | +--------------------------+--------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | sjis | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | +--------------------------+--------+ 7 rows in set (0.00 sec)
この程度ではまだ駄目ですね.mysql:9586によると,
character_set_client
クライアントから渡された SQL 文はこの文字コードであると解釈される。character_set_connection
キャラクタセットイントロデューサ (例えば『_ujis'ほげ'』)が省略されたSQL 文中の文字列リテラルはこの文字コードであると解釈される。
character_set_results
サーバーがクライアントに返す結果をこの文字コードに変換する。この変数を NULL にセットすると、結果に対する文字コード変換をしないようにできる。
との事ですので,この辺りをShift-JISにしない事には,ちゃんとクエリの解釈をShift-JISで解釈してくれないでしょう.また,帰ってくるのもLatin-1なので,手間がかかります.
そこで,
set character set sjis;
とすると,これらの値をShift-JISに変換できます.やってみます.
mysql> set character set sjis; Query OK, 0 rows affected (0.01 sec) mysql> show variables like 'character\_set\_%'; +--------------------------+--------+ | Variable_name | Value | +--------------------------+--------+ | character_set_client | sjis | | character_set_connection | sjis | | character_set_database | sjis | | character_set_filesystem | binary | | character_set_results | sjis | | character_set_server | latin1 | | character_set_system | utf8 | +--------------------------+--------+ 7 rows in set (0.00 sec)
ちゃんとsjisになってます.なぜかcharacter_set_serverだけはlatin1のままですが,これはどーでも良い.
これでひとまず,データベースの設定はできました.
create table
次に,テーブルを作ります.コレはもう普通に,
mysql> CREATE TABLE books ( id INT, name VARCHAR(255), publisher VARCHAR(255), author VARCHAR(255), arrivedate DATE, isbn INT, PRIMARY KEY (id) );
てするだけ.特にテクニックは必要ありません.
要素をファイルから読み込む
テーブルの要素をファイルから読み込む場合,文字コードをShift-JISに,改行コードをLFにしておけば,まず問題ありません.
JSP
とりあえずShift-JISに
まず,ソースコード自体の文字コードはShift-JISにしましょう.
次に,JSPのソースです.
<%@ page pageEncoding="SJIS" contentType="text/html; charset=SJIS" %>
ヘッダと呼べば良いのでしょうか,はじめの行です.charsetをSJISにしています.
次にurlはどうすれば良いか?
String url = "jdbc:mysql://localhost/bookdb?characterEncoding=sjis";
characterEncodingをsjisにして繋いでいます.
クエリも同様にして,
request.setCharacterEncoding("Shift-JIS");
とします.これでクエリがShift-JISになります.
ResultSet
次に,MySQLから帰ってくるのはどうするのか.
まだLatin-1とかで頑張っていたときは,
new String(rs.getString("name").getBytes("ISO-8859-1"))
などと回りくどい事をしていましたが,オールShift-JISにしてしまうと
rs.getString("name")
で完了.なんて楽なんだっ!
とりあえず大丈夫?
一応,ボクの環境だとこんなかんじで問題無く出来ています.ボクのを参考にしてやったのにデキネーヨ!なんて事があったら,是非教えて欲しいです.「こんな方法もあるよ」とかあれば,是非コメントして欲しいです.
ではでは.