iBATIS.NETでO/RM(コード編)

まえのエントリで設定ファイルはできたんでこっちはコード編。

エンティティクラス

SQLの結果「ResultSet」とマッピングさせるクラス。(DTO

using System;

namespace IBatisNetSample.Domain
{
    public class Zip
    {
        private string _zipCd;
        private string _prefectureNm;
        private string _municipalityNm;

        // プロパティは略
    }
}

DAOインタフェースと実装クラス

ここらはDIのせいというか流行というか。
インタフェースベースの操作なら実装を切り替えることができるから便利といえば便利だけど。
DAOFrameworkはSimpleDAO、SqlMap、NHibernateをサポートしてるんでこれらの切替ができますよ、てことで。

using System;
using System.Collections.Generic;
using IBatisNetSample.Domain;

namespace IBatisNetSample.Persistence.Dao
{
    public interface IZipDao
    {
        IList<Zip> GetAllZip();
    }
}

全郵便番号を検索するメソッド。


実装クラス。

using System;
using System.Collections.Generic;
using IBatisNetSample.Persistence.Dao;
using IBatisNetSample.Domain;

namespace IBatisNetSample.Persistence.MapperDao
{
    public class ZipSqlMapDao : BaseSqlMapDao, IZipDao
    {
        public IList<Zip> GetAllZip()
        {
            IList<Zip> list = new List<Zip>();
            ExecuteQueryForAllObjects("Select", null, list);
            return list;
        }
    }
}

SqlMapperを使った場合の基底クラスのサブクラスとして作成。


基底クラス(BaseSqlMapDao)はこんな感じ。

using System;
using System.Collections.Generic;
using IBatisNet.DataAccess;
using IBatisNet.DataAccess.DaoSessionHandlers;
using IBatisNet.DataAccess.Interfaces;
using IBatisNet.DataMapper;

namespace IBatisNetSample.Persistence.MapperDao
{
    public class BaseSqlMapDao : IDao
    {
        protected SqlMapDaoSession GetContext()
        {
            DaoManager daoManager = DaoManager.GetInstance(this) as DaoManager;
            SqlMapDaoSession sqlMapDaoSession =
                (SqlMapDaoSession)daoManager.LocalDaoSession;
            return sqlMapDaoSession;
        }

        protected SqlMapper GetLoacalSqlMap()
        {
            return GetContext().SqlMap as SqlMapper;
        }

        protected IList<T> ExecuteQueryForAllObjects<T>(
            string statementName, object parameterObject, IList<T> resultObject)
        {
            SqlMapper sqlMap = GetLoacalSqlMap();
            sqlMap.QueryForList<T>(statementName, parameterObject, resultObject);
            return resultObject;
        }
    }
}

これはドキュメントに載ってるベースクラスのまんま。
全件検索用のメソッドとして「ExecuteQueryForAllObjects」を定義。
SqlMapper#QueryForList()の第一引数にMappingファイルで定義したSQL IDを指定。
ジェネリクスを使ってるのは型強制したほうが使いやすいから(個人的)。


SqlMapper使った場合はサンプルのまんまで問題ないんで、とくに難しいことはなし。(たぶん)

サービスクラスの作成

DAOFrameworkの神髄?DIを使ったDAOの取得部分&ファサードクラスとしての役割。
つまりこのメソッド単位でトランザクション境界にしちゃいましょう、てこと。

using System;
using System.Collections.Generic;
using IBatisNet.Common.Utilities;
using IBatisNet.DataAccess;
using IBatisNet.DataAccess.Configuration;
using IBatisNetSample.Domain;
using IBatisNetSample.Persistence.Dao;

namespace IBatisNetSample.Service
{
    public class ZipService
    {
        private static ZipService _instance = new ZipService();
        private DaoManager _daoManager = null;
        private IZipDao _zipDap = null;

        public static ZipService GetInstance()
        {
            return _instance;
        }

        private ZipService()
        {
            _daoManager = ServiceConfig.GetInstance().DaoManager;
            _zipDap = _daoManager.GetDao(typeof(IZipDao)) as IZipDao;
        }

        // トランザクション境界
        public IList<Zip> GetAllZip()
        {
            // トランザクション開始
            //using (IBatisNet.Common.IDalSession session = _daoManager.BeginTransaction())
            //{
                return _zipDap.GetAllZip();
                //session.Complete();
            //}
        }
    }
}

シングルトンクラスとして作成。
DaoManagerクラスがDIコンテナ兼コネクション管理してくれてるやつぽい。
ちなみにServiceConfigクラスはiBAIS.NETのサンプルにあるんでそのままパクったw
DaoManager#GetDat(Type type)でdao.configで定義したDAOが取得できる。


これで完成。
コードビハインドからファサード(サービス)クラスを呼び出して実行すればいいだけ。
ただやっぱりマッピングファイルの作成だけは面倒だったりするので何か手段を講じた方がいいかも。
ある程度ファイルを生成してくれるフリーなツールがあるらしい。


参考:
CodeZine:iBATIS.NETにてO/Rマッピングを行う(DAO Framework編)
肝心なServiceConfigクラスについて「サポートクラスから」としか書いてないのがあれだけど(;´Д`)


おまけ:

- The error occurred in <property name="resource" value="SqlMap.config" xmlns="http://ibatis.apache.org/dataAccess"; />. 

例外で↑こんなのが出たとき、そのpropertyタグがおかしいていってるのはあってるけど「実はそこれ参照してる"SqlMap.config"がおかしい」てのに気づくのに1日かかったorz
InnerExceptionでネストしてるんだもんなぁ…。
そこたどったら、SqlMap.configでエラー出てたorz
これググっても解決法が全然でてこなかったんで、いちおメモ。