いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

iBatis.NET奮闘記-007 (1対1のデータ取得) (Mapper, ISqlMapper, QueryForObject, resultMap, resultMapping)


大分間があいてしまいましたが、第7回です。


今回は、1対1の関連を取得してみます。
前回、1対Nをやっていますので、実際1対1は同じ事をやるだけです。
違いは、resultMapにgroupByが付いているかいないかくらいです。


今回も、ポイントはresultMapの設定にあります。
取得SQLの結果を大元のresultMapに渡し、その中からさらに他のresultMapに渡す事で
JOINの設定ができます。

以下、サンプルです。
今回のサンプルでは、MemosテーブルにあらかじめMemoIdが1のデータが存在し、Authorsテーブルに
あらかじめAuthorIdが1のデータが存在している事を前提としています。


[Author.cs]

using System;
using System.Collections.Generic;

namespace Gsf.Samples.IBatisNet.Models {

    public class Author {

        int    _authorId;
        string _name;
        int    _age;

        public int AuthorId{
            get{ return _authorId; }
            set{
                _authorId = value;
            }
        }

        public string Name{
            get{ return _name; }
            set{
                _name = value;
            }
        }

        public int Age{
            get{ return _age; }
            set{
                _age = value;
            }
        }

        public override string ToString() {
            return string.Format("id:{0}, name:{1}, age:{2}", AuthorId, Name, Age);
        }
    }
}

[MemoAndAuthor.cs]

using System;
using System.Collections.Generic;

namespace Gsf.Samples.IBatisNet.Models {

    public class MemoAndAuthor {

        int    _memoId;
        Author _author;
        string _title;
        string _memoData;

        public int MemoId{
            get{ return _memoId; }
            set{
                _memoId = value;
            }
        }

        public Author MemoAuthor{
            get{ return _author; }
            set{
                _author = value;
            }
        }

        public string Title{
            get{ return _title; }
            set{
                _title = value;
            }
        }

        public string MemoData{
            get{ return _memoData; }
            set{
                _memoData = value;
            }
        }

        public override string ToString() {
            return string.Format("memo-id:{0}, author-[{1}], title:{2}, data:{3}", MemoId, MemoAuthor, Title, MemoData);
        }
    }
}

[MemoAndAuthor.ibatis.xml]

<?xml version="1.0" encoding="utf-8" ?>
<sqlMap namespace="MemoAndAuthor"
        xmlns="http://ibatis.apache.org/mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <alias>
        <typeAlias type="Gsf.Samples.IBatisNet.Models.Author"        alias="Author"/>
        <typeAlias type="Gsf.Samples.IBatisNet.Models.MemoAndAuthor" alias="MemoAndAuthor"/>
    </alias>

    <resultMaps>
        <!--
            MemoAndAuthor用の結果マッピング設定です。
        -->
        <resultMap id="find-memo-result" class="MemoAndAuthor">
            <result column="MemoId"       property="MemoId"/>
            <!--
                MemoAndAuthorクラス内にて定義されているAuthor型へのマッピング設定。
                別のresultMapに、現在の情報を引き渡し、その結果をマッピングする。
                その際に、resultMapping属性に指定する値は必ず名前空間付きで指定すること。
            -->
            <result property="MemoAuthor" resultMapping="MemoAndAuthor.find-author-result"/>
            <result column="MemoTitle"    property="Title"/>
            <result column="MemoData"     property="MemoData"/>
        </resultMap>

        <!--
            Author用の結果マッピング設定です。
        -->
        <resultMap id="find-author-result" class="Author">
            <result column="AuthorId"   property="AuthorId"/>
            <result column="AuthorName" property="Name"/>
            <result column="AuthorAge"  property="Age"/>
        </resultMap>
    </resultMaps>

    <statements>
        <!--
            指定されたMemoIdを条件として、該当するメモデータと作者データを取得します。
        -->
        <select id="FindMemoAndAuthor" parameterClass="int" resultMap="find-memo-result">
            <![CDATA[
                select
                      m.MemoId    as MemoId
                     ,a.AuthorId  as AuthorId
                     ,a.Name      as AuthorName
                     ,a.Age       as AuthorAge
                     ,m.Title     as MemoTitle
                     ,m.MemoData  as MemoData
                from
                     Authors a
                    ,Memos   m
                where
                    m.MemoId   = #value#
                    and
                    m.AuthorId = a.AuthorId
            ]]>
        </select>
    </statements>
</sqlMap>


上記のような設定で、以下のようにテストコードを記述したとします。

using System;
using System.Collections.Generic;

using NUnit.Framework;

using Gsf.Samples.IBatisNet.Models;

using IBatisNet.DataMapper;
using IBatisNet.Common;

namespace Gsf.Samples.IBatisNet {

    [TestFixture]
    public class IBatisSample007 {

        [Test]
        public void JOINの動作を確認してみる_1_to_1(){
            //
            // 対象となるデータを取得し、出力.
            //
            MemoAndAuthor data = Mapper.Instance().QueryForObject("MemoAndAuthor.FindMemoAndAuthor", 1);

            Assert.IsNotNull(data);
            Assert.IsNotNull(data.MemoId);
            Assert.IsNotNull(data.MemoAuthor.AuthorId);

            Console.WriteLine(data);
        }
    }


    class DummyEntryPoint007{

        static void Main(){
            //
            // nop;
            //
        }
    }
}


例えば、以下のようなデータがデータベース上にあった場合

  • Authors
AuthorId Name Age Inserted Updated
1 gsf_zero1 28 2007/11/12 15:53:38 2007/11/12 15:53:38
  • Memos
MemoId AuthorId CategoryId Title MemoData Inserted Updated
1 1 1 Title-001 MemoData-001 2007/11/12 15:00:00 2007/11/12 15:00:00


以下のように表示されます。

memo-id:1, author-[id:1, name:gsf_zero1, age:28], title:Title-001, data:Memo-001