MySQLで文字コードを「utf8」とした場合UnicodeのBMPしか扱えないそうです。
http://yanok.net/2010/06/mysqlutf-8.html
サロゲートペアを扱う必要がある場合は最初から文字コードを「utf8mb4」として定義しないといけないらしい。。。(--
なんとも残念な仕様です。「Unicode対応」と言いつつサロゲートペア未対応のものはたまにあるので、そこにはそれほど驚きませんが対応するのであれば「utf8mb4」みたいな新しいキーワードを導入するのではなく「utf8」として対応してほしかったと思います。
DB作成の際には文字コードは意識しますが何の迷いもなく「utf8」を選ぶっちゅーの(--
そんな愚痴はさておいて、ここではPlayframework(1.2.5)からMySQLのutf8mb4なデータベースを扱う話をします。
MySQLでutf8mb4のデータベースを作成する方法については色々なところで紹介されているのでここでは特にとりあげません。それだけはまった人が多いってことですよね(^^;;;
さて、MySQLのutf8mb4化も終わり次にPlayのアプリケーションからINSERT/SELECTのテストを試みたんですが、最初はやっぱりサロゲートペアが正しく扱われませんでした。
データベース側の設定がまだ足りてないのかといろいろ試行錯誤したんですが、これ実はPlay側の設定の問題でした。
PlayではDBの設定はapplication.confで行うのですが、その設定方法には
db=mysql://user:pwd@host/database
のように1行にユーザー名やパスワードなどのすべての情報を記述する方法と
db.url=jdbc:mysql://host/database db.driver=com.mysql.jdbc.Driver db.user=user db.pass=password
のように4行にばらして指定する方法があります。
1行でまとめて指定する方法が使用できるのはPostgreSQLやMySQLなどのPlayが標準で対応しているDBだけでOracleやSQLServerを使用する場合は常にばらした記述方法を使用しなければならないのですが、可能な場合は1行設定を使用することの方が多いかと思います。
ここに罠があります。
1行設定は内部的に4行の個別設定にばらされるのですが、この時にdb.urlが
db.url=jdbc:mysql://host/database?useUnicode=yes&characterEncoding=UTF-8&connectionCollation=utf8_general_ci
のようにエンコーディングのオプションをハードコードで付加された形で設定されてしまうのです。
このためutf8mb4のデータベースを使用する際は1行設定は使用することができず
db.url=jdbc:mysql://host/database?useUnicode=yes&characterEncoding=UTF-8&connectionCollation=utf8mb4_general_ci db.driver=com.mysql.jdbc.Driver db.user=user db.pass=password
のようにutf8mb4を明示してバラに設定する必要があります。