カスタム検索

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 にクラス名を指定する事で自分で作成する事も出来るようです。試してませんが :)

2008年2月22日金曜日

groovyでPDF! PDFBuilder!

groovy-pdfというおもしろそうなものを見つけたのでgrailsで使ってみました。
一言で言うと、iTextをgroovyのBuilderで実装しましたよってものです。

まずはインストール。
ソースをgoogle codeから落としてきましょう。

svn checkout http://groovy-pdf.googlecode.com/svn/trunk/ groovy-pdf

ソースしか上がってないので自分でコンパイルしてやる必要があります。
groovyをインストールし、gantをダウンロードしインストール。
(解凍したフォルダに移動して、 groovy bin/install.groovy)
コンソールからgantで実行し、Cannot open file build.gant とメッセーじが出たらインストールされています。

先程チェックアウトしたプロジェクトのフォルダへ移動し、gant compile と実行すれば dist/pdfbuilder.jar というファイルが出来るので、それを grailsプロジェクトのlibフォルダへコピー
あとはサンプルの内容をアクション内にコピペしてやればとりあえずテキストが出てきます。

まだ対応していない処理などもありますが、Builder形式でかけるのでBuilderの書式を覚えてしまえば誰でも簡単P・D・F!P・D・F!

デフォでは日本語がでませんので、この辺はiTextの設定をまた後日 :)

2008年2月13日水曜日

納車


先日待ちに待ったシビックTypeRが納車されました。
丸2ヶ月ぐらいかかった分もあってか非常に快適です :)

実に5年ぶりのスポーツカー&初のVTECです。
ストレートのフル加速はさすがにFDやエボには劣りますが、レスポンスのダイレクト感とVTECに入った後の間隔はやばいぐらい気持ちいいです。
公道ではまともにVTECを使えないので早くサーキットで走ってみたいです :)

・画像を追加、どこからアップロードするかなかなか気づかなかったのは秘密

2008年2月12日火曜日

GrailsでのClass.forNameについて

grails 1.0以前では自前で書いたクラスを Class.forName("className") で呼び出せてたんですが、今 grails 1.0.1-SNAPSHOT でやってみたら ClassNotFound のエラーが、、、(´・ω・`)

で、Javaのリファレンスを見てみると

Class.forName("Foo")

Class.forName("Foo", true, this.getClass().getClassLoader())
を呼んでるのとの事

なんでクラスローダーのへんの問題かと思い、とりあえずそのまま実行してみると、、、さっくり動いちゃいました。
ということは groovy でオーバーライドされちゃってるんでしょうか、まぁこんな事もありましたというメモメモ。

2008年2月6日水曜日

TomcatでJNDI in Grails

grailsから作成したwarをtomcat上でJNDIを使って動かすというのをやったので覚え書き。

・grailsからwarの作成

grails war
以上 :)
{applicationName}-0.1.war って感じのファイルが出来れば成功です。

・grailsのDataSource.groovyをJNDIへ書き換える

warした場合は production を書き換えます。

production {
  dataSource {
   pooled = true
   dbCreate = "update"
   jndiName = "java:comp/env/jdbc/oracle"
  }
}


urlがなくなってjndiNameに変わります。
java:comp/env/ までは固定で、 jdbc/oracle というのがJNDIの接続名になります。

・Tomcat側の設定

コンテキストにたいしてJNDIを設定します。

tomcat/conf/server.xml の中の <Host ...> の中に以下の内容を追加します。


<Context path="/hoge" docBase="hoge"
debug="5" reloadable="true" crossContext="true">

<Resource name="jdbc/oracle"
auth="Container"
type="javax.sql.DataSource"
username="user"
password="pass"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@127.0.0.1:1521:hogedb"
/>

</Context>


ContextのpathとdocBaseにはプロジェクト名を、
ResourceのnameにJNDIの接続名を、
username,password,driverClassName,urlはDBに応じて設定して下さい。
必要なドライバを tomcat/common/lib にいれておきます。

・起動

作成した war を tomcat/webapps/ へいれ、tomcatを起動します。
エラー無くたちあがれば成功です。
Tomcat上のJNDIの状態を知りたい場合は、TomcatAdministratorを入れれば簡単に確認する事が出来ます。


・おまけ

上記の設定だとコンテキスト毎にJNDIの設定を書く必要がありますが、複数のコンテキストで共通のJNDIを使う場合は以下のように設定します。

tomcat/conf/server.xml 内の <GlobalNamingResources> の中に <Resource> を設定します。(内容は同じです)
Context内に <ResourceLink> を設定します。


<Context path="/hoge" docBase="hoge"
debug="5" reloadable="true" crossContext="true">

<ResourceLink name="jdbc/oracle"
global="jdbc/oracle"
type="javax.sql.DataSource"/>

</Context>


これでGlobalNamingResourcesに設定したResourceを設定できます。