ひがやすを技術ブログ

電通国際情報サービスのプログラマ

S2 Hibernate Plugin

S2自身をコンパクトに保ちながら、機能追加をしていくために
Plugin形態を取ろうと思ってます。
PluginはS2自身から配布も切り離されます。
その第一弾は、S2 Hibernate Plugin。
意外に思う方も多いかもしれません。
S2Daoをやらないというわけではなく、
O/Rマッピングツールの中で、最も評価が高く
ユーザも多いであろうHibernateをS2でサポートすることは
ニーズが高いと思ったためです。
使い方はこんな感じ。
EmployeeDao.java


interface EmployeeDao {
public Employee getEmployee(String name);
}
EmployeeDaoImpl.java

class EmployeeDaoImpl extends AbstractHibernateDao
implements EmployeeDao {

EmployeeDaoImpl(SessionFactory factory) {
super(factory);
}
public Employee getEmployee(String name) {
return getSession().find(
"from Employee where name = ?"
name, Hibernate.STRING);
}
}

AbstractHibernateDao.getSession()で提供されるセッションは、
openもcloseも必要ありません。S2のJTAに連動します。
そのため、同一DAOのメソッド間でも同一トランザクション
あれば、セッションは維持されますし、異なるDAO、異なるサービス間でも
同一トランザクションであれば、セッションは維持されます。
SQLを意識したくない場合は、HibernateSQLを自前で
コントロールしたい場合は、DbUtils,S2Daoのような
使い分けになるのかなぁと思います。

SQLのツールとの連動

ひがさんのところで、Seasar2のデータ層のソリューションにHibernateをまずリリースしようか考えていることを書かれてます。私はSQLをごりごりごりごり書きたいごりごり。

未来に使ってくれる人より、今使ってくれる人を大事にしたいため、
S2Daoを先にリリースします。(^^;
SQL文の外部化ですが、バインド変数や動的SQL文の生成などを考えると
生のSQL文をそのままXMLには記述できないと思います。
なんかツール(antなど)を作ってXMLから生のSQLをはかせ、
そいつをSQL*Plusなどで実行する手もありますが、
ちょっとめんどくさい。
TapestrySQL版として、SQL*Plusなどで直接実行できるが
実行時には動的に値が変わるなんてことができるとうれしい。
そこで考えてみました。


SELECT empno, ename FROM emp
--S2 7788 -> ?{empno}
WHERE empno = 7788
のようにSQL文を記述します。SQL*Plusではそのまま実行できます。
S2Daoが実行するときには、--S2コメント分を見つけると次の行の
該当する文字列をバインド変数に置き換えて、引数のempnoを
バインドして実行します。
S2Daoは次のように解釈します。

SELECT empno, ename FROM emp
WHERE empno = ?{empno}
SQLツールでそのまま実行できるというのがコンセプトで、
SQLデザイナ(?)と開発者のスムースな分業が可能になります。

ハイブリッドSQL

なるほど。SQLコメントでSQLデザイナーとプログラマーで分業をやるという。悪乗りしてTapestry的ならこっちか?
SELECT empno, ename FROM emp
WHERE empno = /*S2*/7788/*?{empno}*/

とか?トークン内部の一部置き換えはできなくなっちゃいますけど。

ちょっとみにくいけど、置き換えできる範囲を自由に指定できるようになりますね。
動的に変わるSQL文をJavaで自由に組み立てられるようになります。


SELECT empno, ename FROM emp
/*S2*/WHERE job = 'CLERK' AND deptno = 10/*this.hoge()*/

class MyDaoImpl extends S2Dao {
//S2コメントの部分を置き換える
public void hoge(QueryContext ctx) {
//ctx.addSql(String)でSQL文の追加
//ctx.addSql(String sql, Object var)SQLを追加しながら
//バインド変数の追加
//ctx.getArg(String name)で引数の取得
自由にSQL文を組み立てる
ctx.addSql(" WHERE job = ?", ctx.getArg("job"));
ctx.addSql(" AND deptno = ?", ctx.getArg("deptno"));
}
}