SQL取得時にネスト化されたリストオブジェクトに同時にマッピングする方法

# 0.はじめに
ORマッパーとしてMybatisはメジャーと思いますが、これまであまり有効な使い方をしてこなかった方もいるかもしれません。
Java側から変数をバインドさせるとか、受け取ったDB取得結果をオブジェクトにマッピングするとか、if文で条件を可変にするとか。（私はその程度でした。。）
実は、ORマッパーはもっと複雑なこともマッピングしてくれて、その分楽になるんだよというような内容のご紹介になります。

## 1.概要
Model型のListかつ、Modelの中にもList型が内包されているようなリストの中にリストがネストされているオブジェクトの場合にDBから取得したデータを設定していく際には取得結果のForループに加えて、内包されているList型も設定していくためのForループが必要になる為、二重ループさせる必要があります。

もちろんこの実装でも誤りではありませんが、実装が増えることで可読性が下がったり、テストする際の確認ケースが増えたりコードが増えることによるバグのリスクがあがる可能性があるため、減らせるならば極力実装をシンプルにするほうが好ましいと思われます。

MyBatisのORマッパーにはネストされたオブジェクトに対してもマッピングすることができる機能があるため紹介させていただきます。

## 2.参考例
実際にどのようなケースで利用できるものなのかを以下の例をもとに紹介します。
商品とその商品コードに紐づく材料が複数件存在する場合に、複数のマスタからまとめて取得した内容をネスト化しているオブジェクトに設定したいケースです。

##### 商品マスタ
| 商品コード | 商品名 |
|:-:|:-:|
| E001  |  レモンサワー |
| E002  | スクリュードライバー  |

##### 商品材料マスタ
| No | 商品材料コード | 商品コード | 商品名 |材料価格(円)
|:-:|:-:|:-:|:-:|:-:|
| 1  |  E001-01 |E001 |焼酎 | 1000 |
| 2  | E001-02  |E001 |炭酸水 | 50 |
| 3  | E001-03  |E001 |レモン |100 |
| 4  | E002-01  |E002 |ウォッカ | 2000 |
| 5  | E002-02  |E002 |オレンジジュース | 100 |

## 2-1.取得させたいオブジェクト

商品Modelの項目にさらに商品材料Modelのリストをネストして持っている状態。

```Java
/**
 * 商品情報
 */
@Data
public class itemModel{
/** 商品名 **/
private Long itemName;
/** 商品コード **/
private Long itemCode;
/** 商品材料リスト **/
private List<itemMaterialModel> itemMaterialList;
}
```
```Java
/**
 * 商品材料情報
 */
@Data
public class  itemMaterialModel{
/** 商品材料名 **/
private Long itemMaterialName;
/** 商品材料コード **/
private String itemMaterialCode;
/** 材料価格 **/
private BigDecimal materialPrice;
}
```


## 2-2.商品情報取得イメージ
>**商品Modelリスト[0]**
・商品名：レモンサワー
・商品コード：E001
>>・**商品材料リスト**
  **[0]**
    ・商品名：焼酎
    ・商品材料コード：E001-01
    ・価格：1000
  **[1]**
    ・商品名：炭酸水
    ・商品材料コード：E001-02
    ・価格：50
  **[2]**
    ・商品名：レモン
    ・商品材料コード：E001-03
    ・価格：100

>**商品Modelリスト[1]**
・商品名：スクリュードライバー
・商品コード：E002
>>・**商品材料リスト**
  **[0]**
    ・商品名：ウォッカ
    ・商品材料コード：E002-01
    ・価格：2000
  **[1]**
    ・商品名：オレンジジュース
    ・商品材料コード：E002-02
    ・価格：50

## 2-3.SQL
・取得したい要素はresalutMap内でキーとなるidとその他の項目情報をresultタグで指定します。
・collectionタグで囲っている部分が今回ネストしたい取得項目になります。これにより、指定したオブジェクトにネスト化したい要素をマッピングさせることができます。
```SQL
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.dao.ItemMapper">

    <resultMap id="ItemMap" type="com.example.demo.dto.itemMaterialModel">
        <id property="itemCode" column="itemCode"/>
        <result property="itemName" column="itemName" />
        <collection property="itemMaterialList" ofType="com.example.demo.dto.itemMaterialModel">
            <id property="itemMaterialCode" column="itemMaterialCode" />
            <result property="itemMaterialName" column="itemMaterialName" />
            <result property="materialPrice" column="materialPrice" />
        </collection>
    </resultMap>

<select id="search" resultMap="ItemMap">
SELECT 
 mi.itemName
 ,mi.itemCode
 ,mim.itemMaterialName
 ,mim.itemMaterialCode
 ,mim.materialPrice
FROM m_item mi
INNER JOIN m_item_material mim
  ON mim.itemCode = mi.itemCode
</select>
```

## 3.最後に
今回はネスト化されているオブジェクトにMybatisでマッピングさせるための実装のご紹介でした。

ただ実装するだけではなく、今使っているライブラリやフレームワークには実は実装そのものを楽にしたり、可読性を上げたり品質を保つための便利な機能があったりするので、そういったものを探してみるのも面白いかもしれませんね。