SkinnyFrameworkにてScaffoldしたモデルからOracleに接続するために変更したところをメモ。
試した環境としては、
- Windows 8.1
- SkinnyFramework 1.3.4
- Oracle 10g
ですが、他のOS等でも大丈夫だと思います。
1. JDBCドライバの依存設定
OracleのJDBCドライバはMavanRepositoryに登録されていないため、以下のいずれかの方法で参照を追加する必要があります。
- libディレクトリに置く
- ローカルのMavenリポジトリに発行して利用する
一番手軽なのは方法1で特に説明もいらないと思います。
ただし、方法1の場合だと実行可能JARファイルを出力(skinny package:standalone
)した際にJDBCドライバが含まれないようですので、ここでは方法2を説明します。
1.1. JDBCドライバをローカルのMavenリポジトリに登録する
まずはJDBCドライバを用意して、ローカルのMavenリポジトリに登録します。mvn
コマンドが必要となりますので、まだの方はここでインストールしましょう。手順は省略します。
JDBCドライバのファイル(ここでは ojdbc14.jar
)を配置したディレクトリでコマンドプロンプトを開き、以下のコマンドを実行します。
rem 以下は1行で入力する
C:\jdbc> mvn install:install-file -Dfile=ojdbc14.jar -DgroupId=com.oracle -DartifactId=ojdbc -Dversion=14 -Dpackaging=jar
rem 改行したい場合は、行の末尾に ^ を付けます
C:\jdbc> mvn install:install-file -Dfile=ojdbc14.jar ^
-DgroupId=com.oracle ^
-DartifactId=ojdbc ^
-Dversion=14 ^
-Dpackaging=jar
それぞれのパラメータについてはMavenの説明などを参照してください。ここでは省略します。
1.2. JDBCドライバを参照するように ビルドファイル project/Build.scala
を更新する
上の手順で登録したJDBCドライバを参照するように、ビルドファイルを更新します。
// project/Build.sbt を一部抜粋
// baseSettings を更新すればいいはず。
lazy val baseSettings = ScalatraPlugin.scalatraWithJRebel ++ herokuSettings ++ Seq(
// ...
libraryDependencies ++= Seq(
// Oracle の JDBC ドライバを追加
"com.oracle" % "ojdbc" % "14"
),
resolvers ++= Seq(
// ローカルの Maven リポジトリを追加
Resolver.mavenLocal
)
// ...
)
更新後、OracleのJDBCドライバが利用できるようになります。
2. Oracleへのコネクション設定
DBへの接続設定は、設定ファイル src/main/resources/application.conf
へ書きますが、デフォルトのまま利用すると以下のエラーが発生するはずです。
2014-11-03 15:24:29.091 ERROR --- [p1111954787-431] controller.Controllers$search$ : Cannot get a connection, pool error Unable to validate object
java.sql.SQLException: Cannot get a connection, pool error Unable to validate object
エラーが発生する理由の一つとして、デフォルトで設定されているコネクション確認用のクエリがOracleに通らないというものがあります。
該当の接続設定のpoolValidationQuery
を、以下のとおりDUAL表を参照するように変更します。
(変更前)
poolValidationQuery="select 1 as one"
(変更後)
poolValidationQuery="select 1 as one from dual"
^^^^^^^^^^
3. テーブルのカラム名が取得できない?
SkinnyORMからクエリを投げる際に、カラム名をMetaDataから取得しているようですが、自分の環境では取得できなかったため、以下のエラーが発生してました。
No column found for persons. If you use NamedDB, you must override connectionPoolName.
カラム名が取得できないため、暫定的に手動でカラム名を設定します。
(時間があったら解決方法を探します。)
// 以下のモデルがあるとして
case class Person(
id: Long,
name: String,
birthDay: DateTime
)
object Person extends ... {
// columnNames メソッドをオーバーライドして、snake_caseのカラム名を返すようにする。
override def columnNames = Seq("id", "name", "birth_day")
}
4. ページネーションが効かない
公式サイトにもありますが、Oracle(とSQLServer)への接続にはページネーションをサポートしていません。
Scaffolding - Skinny Framework
http://skinny-framework.org/documentation/scaffolding.html#skinnyresource's-paginaation-for-oracle,-ms-sqlserver
上記ページに書いてあるとおり、SkinnyModel#findModels(pageSize: Int, pageNo: Int): List[Model]
をカスタマイズすることでページネーションをすることが可能とあります。
DBにもメモリにもやさしくないですが、件数が少ない場合は全件取得してScalaのメソッドで対応すると楽です。
ちゃんとしたクエリを発行する方法については、調べてから更新しようと思います。
object Person extends ... {
// 良くない実装ですが、すごく簡単。
override def findModels(pageSize: Int, pageNo: Int): List[Person] = {
val limit = pageSize
val offset = pageSize * (pageNo - 1)
findAll().drop(offset).take(limit)
}
}
まとめ
とりあえず上記の対応をすることで、ScaffoldしたモデルからOracleに接続できるようになります。
それ以外にも必要なところがあれば随時更新していきます。