mybatisのforeachの使い方を詳しく説明します。
mybatisのmapper.xmlファイルを作る時によく使われています。sql文の検索条件を動的に生成します。この時はmybatisのforeachを使うことができます。
foreach元素の属性は主にitem、index、collection、open、separator、closeがあります。 item:セット内の要素反復時の別名であり、このパラメータは必須である。 index:listおよび配列において、indexは要素のシーケンス番号であり、mapにおいて、indexは要素のkeyであり、このパラメータはオプション である。 open:foreachコードの開始記号は、一般的に(close=「)」と併用されます。n()、values()によく使われます。このパラメータはオプション です。 separator:要素間のセパレータ、例えばin()の場合、separator="は、要素の中間に自動的に使用されます。"仕切り、カンマの手動入力によるsqlエラーを避けるために、in(1,2)のように。このパラメータはオプションです close:foreachコードのクローズ記号は、一般的に、オープン=「(」と併用します。n()、values()によく使われます。このパラメータはオプションです collection:foreachを行う対象として、Listオブジェクトはデフォルトではキーとして「list」を使用しています。配列オブジェクトはキーとしての代わりに「array」があります。Mapオブジェクトにはデフォルトのキーがありません。もちろん、参加時には@Param("keyName")を使ってキーを設定することができます。keyNameを設定すると、list、arrayは無効になります。パラメータの対象となるフィールドがある場合を除きます。例えば、Userに属性List idsがあれば。入参はUser対象です。このコレクション=「ids」です。もしUserが属性Ids idsを持っているならば。そのうち、Idsは対象で、Idsは属性List idを持っています。入参はUserオブジェクトで、collection=「ids.id」 foreachを使う時に一番重要なのは間違いやすいのがcollection属性です。この属性は必ず指定しなければなりませんが、その属性の値は違っています。主に次の3つの状況があります。.入力されたのがシングルパラメータであり、パラメータタイプがListである場合、collection属性値はlistである。 入力されたのが単一パラメータであり、パラメータタイプがarray配列である場合、collectionの属性値はarray. である。もし入ってきたパラメータが複数の場合、それらを一つのMapにパッケージする必要があります。もちろんシングルパラメータもmapにパッケージすることができます。実際にあなたがパラメータを入力した時、MyBatisの中にもMapにパッケージされます。mapのkeyはパラメータ名です。このときのcollection属性値は、入ってきたListまたはarrayオブジェクトが自分のパッケージのmapの中にあるkeyである。 最後の条について、公式見解を見てみます。
注意してください。リストの例や配列をパラメータの対象としてMyBatisに送ることができます。そうすると、MyBatisは自動的にMapに包装し、名前をキーにします。Listの例は「list」をキーとし、配列例のキーは「array」とする。
したがって、マルチパラメータであろうと、シングルパラメータであろうと、arrayタイプであろうと、mapにカプセル化して転送することができる。転送がListであれば、mybatisはlistをkey、list値をobjectのmapとしてパッケージ化します。arrayであれば、arrayをkey、arrayの値をobjectのmapとしてパッケージ化します。もし自分でカプセル化するなら、collectionには自分のパッケージ化したmapのkey値を入れます。
ソース分析
公式文書はこれを使っていますので、説明は比較的短く、細部についても見落とされています。多くの学生が使っています。特にforeachという関数の中で、collection属性は何をしますか?注意事項がありますか?文書が不完全なので、これはソースコード解析の方法で各属性の関連要求を分析するしかないです。
collection属性の用途は、入力を受信する配列またはListインターフェースで実現される。しかし、その名前の要求に対して、Mybatisは実現中にはちょっと分かりにくいので、特に注意しなければなりません。
次にソースコードの分析を開始します。(メモはMybatis 3.0.5バージョンを使用しています。)
まずMybatis SQLプロファイル解析を行うための入り口を見つけます。
MapperMethod.javaクラスのpublicObject execute(Object[]args)は、この方法が実行されるエントリです。
n集合クエリに対して、アプリケーションはselectForListまたはSelctForMap方法です。
どの方法を呼び出しても、元JDKから入ってきたパラメータObject[]タイプに対して、getParam法でObjectに変換しますが、この方法は何をしますか?ソースの分析は以下の通りです。
上の図の中で赤い二つのところは、一つのパラメータと複数のパラメータの処理方法が違っていることに驚きました。パラメータの個数が一つより大きい場合、Mapにパッケージされます。key値はMybatisのParam注釈を使用すると、このkey値を使用します。そうでなければ、デフォルトではデータ番号を統一して使用します。1から開始します。この問題を先にメモして、コードの解析を続けます。次はselectForList操作(他の操作は対応方法を適用します)であれば、Default Sql SessionのpublicListselectList(String statement、Object parameter、RowBounds rowBounds)方法を呼び出します。
もう一つの発見がありました。ソースコードは以下の通りです。
上のアイコンの赤い部分をパラメータにもう一度パッケージしました。コードを見てみます。
パラメータタイプがListであれば、colleconでlistとして指定しなければならないことが分かりました。データグループであれば、collection属性でarrayとして指定しなければなりません。
これで問題が明らかになります。パラメータなら、collectionの値はパラメータの種類によって決まります。
複数の値であれば、注釈Paramで指定しない限り、数字の先頭であるため、collectionではどの値を指定しても無駄です。下図はdebug表示結果です。
使い方
シングルパラメータListタイプ
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。
foreach元素の属性は主にitem、index、collection、open、separator、closeがあります。
注意してください。リストの例や配列をパラメータの対象としてMyBatisに送ることができます。そうすると、MyBatisは自動的にMapに包装し、名前をキーにします。Listの例は「list」をキーとし、配列例のキーは「array」とする。
したがって、マルチパラメータであろうと、シングルパラメータであろうと、arrayタイプであろうと、mapにカプセル化して転送することができる。転送がListであれば、mybatisはlistをkey、list値をobjectのmapとしてパッケージ化します。arrayであれば、arrayをkey、arrayの値をobjectのmapとしてパッケージ化します。もし自分でカプセル化するなら、collectionには自分のパッケージ化したmapのkey値を入れます。
ソース分析
公式文書はこれを使っていますので、説明は比較的短く、細部についても見落とされています。多くの学生が使っています。特にforeachという関数の中で、collection属性は何をしますか?注意事項がありますか?文書が不完全なので、これはソースコード解析の方法で各属性の関連要求を分析するしかないです。
collection属性の用途は、入力を受信する配列またはListインターフェースで実現される。しかし、その名前の要求に対して、Mybatisは実現中にはちょっと分かりにくいので、特に注意しなければなりません。
次にソースコードの分析を開始します。(メモはMybatis 3.0.5バージョンを使用しています。)
まずMybatis SQLプロファイル解析を行うための入り口を見つけます。
MapperMethod.javaクラスのpublicObject execute(Object[]args)は、この方法が実行されるエントリです。
n集合クエリに対して、アプリケーションはselectForListまたはSelctForMap方法です。
どの方法を呼び出しても、元JDKから入ってきたパラメータObject[]タイプに対して、getParam法でObjectに変換しますが、この方法は何をしますか?ソースの分析は以下の通りです。
上の図の中で赤い二つのところは、一つのパラメータと複数のパラメータの処理方法が違っていることに驚きました。パラメータの個数が一つより大きい場合、Mapにパッケージされます。key値はMybatisのParam注釈を使用すると、このkey値を使用します。そうでなければ、デフォルトではデータ番号を統一して使用します。1から開始します。この問題を先にメモして、コードの解析を続けます。次はselectForList操作(他の操作は対応方法を適用します)であれば、Default Sql SessionのpublicListselectList(String statement、Object parameter、RowBounds rowBounds)方法を呼び出します。
もう一つの発見がありました。ソースコードは以下の通りです。
上のアイコンの赤い部分をパラメータにもう一度パッケージしました。コードを見てみます。
パラメータタイプがListであれば、colleconでlistとして指定しなければならないことが分かりました。データグループであれば、collection属性でarrayとして指定しなければなりません。
これで問題が明らかになります。パラメータなら、collectionの値はパラメータの種類によって決まります。
複数の値であれば、注釈Paramで指定しない限り、数字の先頭であるため、collectionではどの値を指定しても無駄です。下図はdebug表示結果です。
使い方
シングルパラメータListタイプ
<select id="countByUserList" resultType="_int" parameterType="list">
select count(*) from users
<where>
id in
<foreach item="item" collection="list" separator="," open="(" close=")" index="">
#{item.id, jdbcType=NUMERIC}
</foreach>
</where>
</select>
テストコード:
@Test
public void shouldHandleComplexNullItem() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
Mapper mapper = sqlSession.getMapper(Mapper.class);
User user1 = new User();
user1.setId(2);
user1.setName("User2");
List<User> users = new ArrayList<User>();
users.add(user1);
users.add(null);
int count = mapper.countByUserList(users);
Assert.assertEquals(1, count);
} finally {
sqlSession.close();
}
}
上記のcollectionはarrayであり、対応するMapperコード:
public List dynamicForeach2Test(int[] ids);
対応するテストコード:
@Test
public void dynamicForeach2Test() {
SqlSession session = Util.getSqlSessionFactory().openSession();
BlogMapper blogMapper = session.getMapper(BlogMapper.class);
int[] ids = new int[] {1,3,6,9};
List blogs = blogMapper.dynamicForeach2Test(ids);
for (Blog blog : blogs)
System.out.println(blog);
session.close();
}
3.自分でパラメータをMapにパッケージするタイプ
<select id="dynamicForeach3Test" resultType="Blog">
select * from t_blog where title like "%"#{title}"%" and id in
<foreach collection="ids" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
上記のcollectionの値はidsであり、着信パラメータMapのkeyであり、対応するMapperコードである。
public List dynamicForeach3Test(Map params);
対応テストコード:
@Test
public void dynamicForeach3Test() {
SqlSession session = Util.getSqlSessionFactory().openSession();
BlogMapper blogMapper = session.getMapper(BlogMapper.class);
final List ids = new ArrayList();
ids.add(1);
ids.add(2);
ids.add(3);
ids.add(6);
ids.add(7);
ids.add(9);
Map params = new HashMap();
params.put("ids", ids);
params.put("title", " ");
List blogs = blogMapper.dynamicForeach3Test(params);
for (Blog blog : blogs)
System.out.println(blog);
session.close();
}
注意sql文SELECT*FROM nujobs WHERE id IN()これはエラーとなりますので、最後にIdsの要素があると判断します。以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。