カスタム検索

2008年2月27日水曜日

GrailsでOracle、CLOB型

OracleではString型はVARCHAR2の4000文字が最大となります。
これ以上長い文字列をいれようと思った場合はCLOB(わけのわからん互換性の低いいやーな感じの型)などを使うのですが、これはStringではないのでStringと同じようには動作しません。
(likeや一致などでエラーになったり)

で、Grails上で使う場合ですが、CLOB型のフィールドを作るにはドメインのmappingに指定してやれば作る事が出来ます。


class Book {
static mapping = {
text type:'clob'
}

String text
}


はい、ですが、上にも書いたとおりCLOB型はStringではないので、検索などを実行するとエラーになります。
CLOBとStringをキャストしてやる必要があるのですが、ここら辺のDBの非互換性を制御するためにあるのがHibernateのDialectというやつです。
GrailsでDialectを設定するには conf/DataSource.groovy を編集します。
dataSourceの部分に dialect を追加してやります。


dataSource {
pooled = false
dialect = org.hibernate.dialect.Oracle9Dialect.class
driverClassName = "oracle.jdbc.OracleDriver"
username = "user"
password = "pass"
}


[2008.03.03] 追記 ---------------------------------------------------
dialectは指定しなくてもいけるみたいです。
クエリ自体は最適化されてるっぽいのでDBを固定出来る場合は書いておいた方がいいかも
-----------------------------------------------------------------

これで検索(Book.findAllByTextLike("妄想") 等)を実行してみると、、、おおっと!エラー
Dialectで方言を吸収してくれるのですが、CLOBの宣言のままだとHibernateは「CLOBとして使いたいんだろうなーこいつ」と判断してくれます。
なので宣言を text にします。


class Book {
static mapping = {
text type:'text'
}

String text
}


これでHibernateは「あー、Oracleで長文使いたいんだねー、じゃあDBの型はCLOBにしとくけどStringとして使えるようにしとくよー」と脳内会話が繰り広げられ無事解決です。

また、このFieldTypeの変換部分は、org.hibernate.types.UserType を継承したUserTypeを作成し、mapping の type にクラス名を指定する事で自分で作成する事も出来るようです。試してませんが :)

0 件のコメント: