ついカッとなってS2Dao.NETの機能を使わずに検索処理を書いてみた

Seasar+S2Daoを使ったプロジェクトで、
開発終盤、もしくは結合テストなどを行う頃になると
高確率で言われる台詞があります。


「○○の処理でパフォーマンスが出ない。
S2Daoは色々リフレクションとか使ってるから
そのせいで遅いんじゃないの?」


というようなものです。


実際にはS2Daoの中であれこれやっている処理よりも
SQL文そのものに問題があったり
DBアクセスとは関係ない部分がボトルネックだったりすることも
多いのですが、
.NETならADOを直接たたいた場合の方が速いのは事実です。


大まかに以下のような処理を行っているためです。
1.Entityのプロパティなどのメタデータから
 DBアクセスの実行に必要な情報を読み取る。
2.ADO.NETを使ってSQL文を実行する。
3.返ってきた結果をEntity(もしくはそのリスト)に格納する。


1.については大部分がキャッシュされますが
それでも初回実行時にはそれなりにコストがかかります。


なので、初回実行時のコストや
Entityに検索結果を自動的に詰め込む分のコストなど、
少しでもオーバーヘッドを削りたい場合のために、
以下のようなコードを考えてみました。


DBFluteの使用が前提です。
※今のところSeasar.NETでの実装予定はありません。
※厳密にエラー処理等を検証したわけではないので
 参考程度、と思って下さい。


///
/// 最低限の機能のみをもつ検索ハンドラ
///

[Implementation]
public class SimpleSelectHandler
{
(途中省略)
///
/// 検索実行
///

///
///
/// 検索結果
public virtual object Execute(string sql, IDataReaderHandler handler){
IDbConnection connection =
DataSourceUtil.GetConnection(_dataSource);
object ret = null;
try {
ret = ExecuteCommand(sql, handler, connection);
}
finally {
_dataSource.CloseConnection(connection);
}
return ret;
}
(以下略)
}

public class ExampleDataReaderHandler : IDataReaderHandler {
public object Handle(IDataReader dataReader) {
Member member = new Member();
member.MemberId = dataReader["MEMBER_ID"] as int?;
member.MemberName = dataReader["MEMBER_NAME"] as string;
return member;
}
}

検索を実行する場合はSimpleSelectHandlerのExecuteメソッドを呼び出します。


Executeメソッドの中で呼んでいるExecuteCommandの中で
やっている処理は大雑把に言えば
IDataReaderHandler型の引数handlerからHandleメソッドを呼んで
結果を返すことのみです。
Executeメソッドの第2引数IDataReaderHandlerは
上記ExampleDataReaderHandlerのような感じで
自前で実装します。


もう一つの引数には実行したい生のSQL文字列を渡します。


DBFluteのConditionBeanにはToDisplaySqlというメソッドがあり、
戻り値としてそのまま実行可能なSQL文字列が返ってきます。
それを渡せばSQLの組み立て部分については
ある程度タイプセーフは保てる(はず)。


上記実装を含むパフォーマンス比較結果はこちら