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