S2Dao.NET を使ってみる(3)
の続き。以下のような機能を試してみる。
- バインド変数コメント
- 単純な置き換え
- LIKE を使った場合
- IN 句を使った場合
- BEGIN コメントを使ったSQLファイル
ソース一式をここに置いておく。
DB の変更
EMPテーブルだけだとこれらの機能を使うのが難しいので、DEPTテーブルとPOSTテーブルを追加した。
CREATE TABLE [dbo].[EMP] ( [EMPNO] numeric (10, 0) NOT NULL , [ENAME] nvarchar (50) NOT NULL , [DEPTNUM] numeric (10, 0) , [POSTNUM] numeric (10, 0) , CONSTRAINT [PK_EMP2] PRIMARY KEY CLUSTERED ([EMPNO])) GO CREATE TABLE [dbo].[DEPT] ( [DEPTNUM] numeric (10,0) NOT NULL , [DNAME] nvarchar (50) NOT NULL , CONSTRAINT [PK_DEPT] PRIMARY KEY CLUSTERED ([DEPTNUM])) GO CREATE TABLE [dbo].[POST] ( [POSTNUM] numeric (10,0) NOT NULL , [POSTNAME] nvarchar (50) NOT NULL , CONSTRAINT [PK_POST] PRIMARY KEY CLUSTERED ([POSTNUM])) GO
バインド変数コメントで単純な置き換え
画面のように、社員番号の上限と下限を指定して検索できるようにしてみる。
具体的にはこう。
[Query("empno BETWEEN /*start*/1 AND /*end*/1")] IList SelectByEmpNo(int start, int end);
バインド変数コメント(/*変数名*/リテラル)を記述する際に注意するのはこの3点。
- /*変数名*/ というように間にスペースは入れないこと。
- 変数名はメソッドの変数名と一致させること。
- リテラルは省略してもかまわない。
バインド変数コメントで LIKE を使う
画面のように、名前を指定して検索できるようにしてみる。
具体的にはこう。
[Query("ename LIKE /*ename*/'test'")] IList SelectByEname(string ename);
LIKEを使う場合、ワイルドカードはメソッドの引数に埋め込むこと。
バインド変数コメントで IN句 を使う
画面のように、部署を複数指定して検索できるようにしてみる。
具体的にはこう。ADO.NETではあれだけ面倒だったIN句がこんなに簡単に・・・
[Query("deptnum IN /*depts*/(1,2,3)")] IList SelectByDepts(int[] depts);
IN句の場合、「IN (/*depts*/1)」とは書かないので注意が必要。
SQLファイルで BEGIN コメントを使う
画面のように、今までの検索条件をANDでつないで検索できるようにしてみる。
メソッドはこう。
IList SelectByAll(bool hasRange, int start, int end, string ename, int[] depts, int[] posts);
肝心のSQLファイルはこんな感じ。
SELECT EMPNO, ENAME, DEPTNUM, POSTNUM FROM EMP /*BEGIN*/WHERE /*IF hasRange*/EMPNO BETWEEN /*start*/1 AND /*end*/1/*END*/ /*IF ename != null*/AND ENAME LIKE /*ename*/'TEST'/*END*/ /*IF depts != null*/AND DEPTNUM IN /*depts*/(1,2,3)/*END*/ /*IF posts != null*/AND POSTNUM IN /*posts*/(1,2,3)/*END*/ /*END*/
これも「埋め込まれたリソース」なので、名前空間に注意が必要。
ファイル名は「Daoインターフェイス名+_+メソッド名.sql」としておくこと。
(この場合は「IEmpDao_SelectByAll.sql」となる)
BEGINコメント(/*BEGIN*/ 〜 /*END*/)は内部のIFコメント(/*IF 条件*/ 〜 /*END*/)の条件がすべて false の場合、WHERE句自体をなかったことにしてくれるものらしい。しかも途中のANDを適切に除去してくれるブラボーな仕様だ。
まとめ
最終的な Dao のソースはこんな感じ。
Daoインターフェイスではメソッドのオーバーロードをサポートしていないらしいので、名前が重複しないように気をつける必要がある。
using System; using System.Collections; using System.Text; using Seasar.Dao.Attrs; using S2DaoTestApp.Entity; namespace S2DaoTestApp.Dao { [Bean(typeof(Emp))] public interface IEmpDao { IList GetAllList(); [Query("ORDER BY EMPNO DESC")] Emp GetMax(); int Insert(Emp emp); int Update(Emp emp); int Delete(Emp emp); [Query("empno BETWEEN /*start*/1 AND /*end*/1")] IList SelectByEmpNo(int start, int end); [Query("ename LIKE /*ename*/'test'")] IList SelectByEname(string ename); [Query("deptnum IN /*depts*/(1,2,3)")] IList SelectByDepts(int[] depts); [Query("postnum IN /*posts*/(1,2,3)")] IList SelectByPosts(int[] posts); IList SelectByAll(bool hasRange, int start, int end, string ename, int[] depts, int[] posts); } }
ここまで実装した時点では、明らかに
S2Dao.NETを使ったデータアクセスの実装時間 << 画面周りの実装時間
となった。データアクセス部分をADO.NETのみで実装していたらそこまで差はなかったはず。
BEGINコメントとかはちょっと癖があるかなとは思うけど、慣れるのにそれほど時間はかからないように思う。あとはストアドかなあ。
もうちょっと早く知っておきたかった・・・orz