てことで、次は1:Nのマッピングについてやってみます。
普通は、1:1のマッピングからスタートだと思いますが
1:1は次の回でやります。(なんでかっていうと、こっちを
先に覚えておかないといけない羽目になったからです ハイw)
複雑なマッピングの場合、以下の点を頭にいれておくといいみたいです。
- resultClass属性では、無理な場合があるのでその場合はresultMap属性を使用
- マッピングをするオブジェクトは普通に作成。(1側にListとかでNを保持)
- 一発で取得しようが、2回に分けて取得しようが自由(SQLを直接かけるのでそこは自由です)
今回は、一回のSQL発行で取得することにします。
まずは、使用するテスト用テーブルを作成します。
create table parent_table (id int primary key, name varchar(100)); create table child_table ( id int ,parent_id int ,name varchar(100) ,primary key (id, parent_id) ,foreign key (parent_id) references parent_table(id) );
当たり前ですが、parent_table側が1で、child_table側がNとなります。
次に、ドメインオブジェクト作成。
今回は、Parent側からChildを取得できる流れのみでいいので、
Child側からParent側への関連は行いません。(親IDのみを保持するだけ
としています)。
// vim:set ts=4 sw=4 et ws is nowrap ft=java fenc=cp932 ff=dos: package gsf.samples.ibatis.sample002; import java.io.*; import java.util.*; import org.apache.commons.lang.builder.*; /** * PARENTテーブルに対応するドメインオブジェクト.<br/> * * @author gsf_zero1 * */ public class Parent{ /** ID */ private Integer id; /** NAME */ private String name; /** CHILDテーブルオブジェクトリスト */ private List<Child> childs; /** * コンストラクタ.<br/> * */ public Parent(){ } /** * Get id. * * @return id as Integer. */ public Integer getId(){ return this.id; } /** * Set id. * * @param id the value to set. */ public void setId(Integer id){ this.id = id; } /** * Get name. * * @return name as String. */ public String getName(){ return this.name; } /** * Set name. * * @param name the value to set. */ public void setName(String name){ this.name = name; } /** * Get childs. * * @return childs as List. */ public List<Child> getChilds(){ return this.childs; } /** * Set childs. * * @param childs the value to set. */ public void setChilds(List<Child> childs){ this.childs = childs; } /** * オブジェクトの文字列表現を返す。<br/> * * @return 文字列表現 * * @see java.lang.Object#toString() * */ @Override public String toString(){ return new ToStringBuilder(this) .append("id", this.getId()) .append("name", this.getName()) .toString(); } }
// vim:set ts=4 sw=4 et ws is nowrap ft=java fenc=cp932 ff=dos: package gsf.samples.ibatis.sample002; import java.io.*; import org.apache.commons.lang.builder.*; /** * CHILDテーブルに対応するドメインオブジェクト.<br/> * * @author gsf_zero1 * */ public class Child implements Serializable{ /** ID */ private Integer id; /** PARENT_ID */ private Integer parentId; /** NAME */ private String name; /** * コンストラクタ.<br/> * */ public Child(){ } /** * Get id. * * @return id as Integer. */ public Integer getId(){ return this.id; } /** * Set id. * * @param id the value to set. */ public void setId(Integer id){ this.id = id; } /** * Get parentId. * * @return parentId as Integer. */ public Integer getParentId(){ return this.parentId; } /** * Set parentId. * * @param parentId the value to set. */ public void setParentId(Integer parentId){ this.parentId = parentId; } /** * Get name. * * @return name as String. */ public String getName(){ return this.name; } /** * Set name. * * @param name the value to set. */ public void setName(String name){ this.name = name; } /** * オブジェクトの文字列表現を返す.<br/> * * @return 文字列表現 * * @see java.lang.Object#toString() */ @Override public String toString(){ return new ReflectionToStringBuilder(this).toString(); } }
つぎは、もっとも大事なSQL設定ファイル.
<?xml version="1.0" encoding="Windows-31J"?> <!-- vim:set ts=4 sw=4 et ws is nowrap ft=xml fenc=cp932 ff=dos: --> <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"> <!-- 1:Nの動作を確認するためのSQL設定ファイル。 データベーステーブルは、PARENTとCHILDの2つが存在し、 PARENTに対して、N件のCHILDが紐づく関連となっている。
-
- >
んで、動作確認といきたいところですが、
SqlMapClient設定ファイル(SqlMapConfig.xml)に
今作成したSQL設定ファイルを定義しておきます。
<sqlMap resource="gsf/samples/ibatis/sample002/ParentAndChild.ibatis.xml"/>
んで、動作確認クラス
// vim:set ts=4 sw=4 et ws is nowrap ft=java fenc=cp932 ff=dos: package gsf.samples.ibatis.sample002; import java.util.*; import com.ibatis.common.resources.*; import com.ibatis.sqlmap.client.*; /** * IBatisSample002の動作確認を行うクラス.<br/> * * @author gsf_zero1 * */ public class IBatisSample002{ /** * アプリケーションエントリーポイント.<br/> * * @param args 起動時引数 * */ public static void main(String[] args) throws Exception{ SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient( Resources.getResourceAsReader("SqlMapConfig.xml")); try{ sqlMap.startTransaction(); sqlMap.delete("deleteChild", null); sqlMap.delete("deleteParent", null); for(int i = 0; i < 10; i++){ Parent aParent = new Parent(); aParent.setId*1; aParent.setName("parent_value_" + (i + 1)); sqlMap.insert("insertParent", aParent); for(int j = 0; j < 10; j++){ Child aChild = new Child(); aChild.setId*2; aChild.setParentId(aParent.getId()); aChild.setName("child_value_" + (j + 1)); sqlMap.insert("insertChild", aChild); } } sqlMap.commitTransaction(); }finally{ sqlMap.endTransaction(); } for(Parent aParent : (List<Parent>) sqlMap.queryForList("getAllParentAndChild", null)){ System.out.println(aParent); for(Child aChild : aParent.getChilds()){ System.out.printf("\t%s\n", aChild); } } } }
上記を実行すると、1個のParentオブジェクトに対して、10個のChildオブジェクトが紐づいて
いるのが確認できます。