日々常々

ふつうのプログラマがあたりまえにしたいこと。

JavaからOracle接続時にORA-12705が発生する

JDBC経由でOracleに接続する際、稀にORA-12705が発生するという事象がありました。環境は Java1.6 Oracle10gXE ojdbc14.jar です。ojdbc6.jar を使うべきなのかも知れませんが、現状この環境なのだから仕方がありません。

java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1
ORA-12705: Cannot access NLS data files or invalid environment specified

このエラーはエラーメッセージに書いてあるとおりです。ORA-12705で検索すれば普通に判りますが、エラーコードを見る事自体は、手元にOracleに接続できる環境があれば容易です。

C:\>set nls_lang=xx
C:\>sqlplus user/pass
SQL*Plus: Release 10.2.0.1.0 - Production on Fri Apr 2 21:43:57 2010
Copyright (c) 1982, 2005, Oracle.  All rights reserved.

ERROR:
ORA-12705: Cannot access NLS data files or invalid environment specified

Enter user-name:

Oracleは接続時にNLSの情報に対応する設定ファイルを読み込んで接続します。この際の設定が拙ければ上記のエラーとなり、接続できません。なお、NLS_LANGだけでなく、Oracle10gの場合はORA_NLS10を見たりもします。ですがこれらの設定は必須ではなく、設定されていなくてもOSの設定とかその辺をみてうまいことしてくれます。

C:\>set nls_lang=
C:\>set ora_nls10=
C:\>sqlplus user/pass
SQL*Plus: Release 10.2.0.1.0 - Production on 金 4月 2 22:47:20 2010
Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
に接続されました。
SQL>

ここまでが予備知識。本題は「JavaからOracle接続時にORA-12705が発生する」なので、環境変数の設定不備ならば、常に繋がらないはず。となると、実行中に何かが意図せず変更されてしまっているとと考えられます。エラーメッセージから考えると、NLSの設定がちゃんとなっていないと考えるのが妥当でしょう。
JDBCで接続する際のNLSの設定の元ネタは、Locale#getDefaultのようです。DB接続の前にLocale.setDefault(Locale.ROOT);とかやってみると、常にORA-12705が発生して失敗するようになりましたので間違いないでしょう。Locale.ITALIANを設定してみたらエラーメッセージが(多分)イタリア語になりましたし。

そんなわけで、DB接続の直前にLocale#setDefaultを行えば、何か別の契機で変更されていても大抵の場合は大丈夫になります。ごまかしの対症療法でよいならば。もっとも、Localeが変更される契機がどこかにあるならば、設定からDB接続の間に割り込まれる可能性はあります。

DefaultLocaleが勝手に変わるなんて話は聞いた事がないのですが、今回の事象が発生している環境では変わっていたような気がします。