経緯
MyBatisで、複数のテーブルを結合しリストを含むオブジェクトを一括で取得する実装を行なったが、情報が点々としておりをまとまったわかりやすい情報が少なかったので、記録として残しておく
概要
id(カテゴリID)を受け取り、
categoriesテーブルとitemsテーブルを結合して、Categoryオブジェクトを作成する。
わかりやすい例として、DBとドメインは以下のように定義する。
↑テーブルイメージ
↑Categoryオブジェクトイメージ
ディレクトリ構成
ディレクトリ構成
.
└── src
└── main
├── java
│ └── com
│ └── example
│ ├── domain
│ │ ├── Category.java
│ │ └── Item.java
│ └── mapper
│ └── CategoriesMapper.java
└── resources
├── application.yml
└── com
└── example
└── mapper
└── CategoriesMapper.xml
実装
CategoriesMapper.java
@Mapper
public interface ItemsMapper {
Item load(int itemId);
}
CategoriesMapper.xml
<select id="load" resultMap="categoryWithItemList">
SELECT
c.id
,c.name
,i,id
,i.name
FROM categories AS c
LEFT OUTER JOIN items AS i
ON
c.id = i.category_id
WHERE
c.id = #{categoryId}
</select>
リザルトマップ
<resultMap type="com.example.domain.Category" id="categoryWithItemList">
<id property="id" column="id"/>
<result property="name" column="name"/>
<collection property="itemList" ofType="com.example.domain.Item">
<id property="id" column="id"/>
<result property="name" column="name"/>
</collection>
</resultMap>
リザルトマップ(省略版)
<resultMap type="com.example.domain.Category"
id="categoryWithItemList" autoMapping="true">
<collection property="itemList" ofType="com.example.domain.Item" autoMapping="true">
</collection>
</resultMap>
オブジェクトの変数名に対応するカラム名が同じであればresultMapタグのautoMappingをtrueにすることでやは省略可能。また、変数名がキャメルケース、カラム名がスネークケースであっても以下のように別途設定を行えば自動マッピング可能。
application.yml
mybatis:
configuration:
map-underscore-to-camel-case: true