今回は2つのテーブル結合をやってみました。
1対1の場合
Entity
<親Entityクラス>
Player.java
package com.mybatis.test.domain;
import java.util.List;
import lombok.Data;
@Data
public class Player {
private String id;
private String name;
private String age;
//子クラスの要素を定義(1対1)
private Detail detailIds;
}
<子Entityクラス>
Detail.java
package com.mybatis.test.domain;
import lombok.Data;
@Data
public class Detail {
private String detailId;
private String work;
}
テーブルの親子関係はdetail_idで結びつくので、Player.javaに子要素の変数を用意する。
XML
xml
<?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.mybatis.test.domain.MyBatisMapper">
<select id="selectItem" resultMap="playerMap">
SELECT
player.id
,player.name
,player.detail_id
,detail.work
FROM
player
JOIN
detail
ON
player.detail_id=detail.detail_id
WHERE
player.id=#{id}
</select>
<!-- テーブルのSELECT結果をどのようにマッピングするか指定 -->
<resultMap id="playerMap" type="com.mybatis.test.domain.Player">
<id property="id" column="id" />
<result property="name" column="name" />
<association property="detailIds" resultMap="detailResult"/>
</resultMap>
<resultMap id="detailResult" type="com.mybatis.test.domain.Detail">
<result property="detailId" column="detail_id" />
<result property="work" column="work" />
</resultMap>
</mapper>
テーブル結合する条件(detail_id)は必ずSQLに盛り込むこと。
検索の結果は resultMap要素で別途定義する。
resultMapでは、実際に検索結果で得たい内容(今回はPlayer)に対する結果のマッピングを行う。
property は Javaクラス側のプロパティ(変数)を指す。
columnはSQLのカラムを指す。
また、今回は1:1の関係なので、associationを使用する。
associationのresultMapで子要素と対応付けする。
Interface
MyBatisMapper.java
package com.mybatis.test.domain;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface MyBatisMapper {
//JOINのテスト用
public Player selectItem(String id);
Service
MyBatisService.java
package com.mybatis.test.domain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MyBatisService {
@Autowired
MyBatisMapper mapper;
//JOIN
@Transactional
public Player selectItem(String id) {
return mapper.selectItem(id);
}
Controller
Controller
@Controller
public class MybatisController {
@Autowired
MyBatisService myBatisService;
Player player = new Player();
player = myBatisService.selectItem("002");
model.addAttribute("playerDetail", player);
return "index";
}
Jsp
<div th:object="${playerDetail}">
<div>
<label><b>名前</b></label>
<p th:text="${playerDetail.name}">
</div>
<div>
<label><b>仕事</b></label>
<p th:text="${playerDetail.detailIds.work}">
</div>
</div>
1対多の場合
Entity
<親Entity>
Player.java
package com.mybatis.test.domain;
import java.util.List;
import lombok.Data;
@Data
public class Player {
private String id;
private String name;
private String age;
private Detail detailIds;
//子クラスの要素定義(1対多)
private List<Item> items;
}
1対多なので、フィールドにList型を定義した。
<子Entity>
Item.java
package com.mybatis.test.domain;
import lombok.Data;
@Data
public class Item {
private String id;
private String item;
}
XML
xml
<?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.mybatis.test.domain.MyBatisMapper">
<select id="selectChoice" resultMap="itemMap">
select
player.id
,player.name
,item.items
from
player
join
item
on
player.id = item.id
where
player.id=#{id}
</select>
<!-- テーブルのSELECT結果をどのようにマッピングするか指定 -->
<resultMap id="itemMap" type="com.mybatis.test.domain.Player">
<id property="id" column="id" />
<result property="name" column="name" />
<collection property="items" ofType="com.mybatis.test.domain.Item">
<result property="id" column="id" />
<result property="item" column="items" />
</collection>
</resultMap>
</mapper>
1対多の場合は、collectionタグを使用する。(1対1の場合はassociationタグ)
collectionタグのpropertyには、子クラス(Item.java)を束ねる親クラス(Player.java)のフィールド(items)を設定する。
ofTypeで、子クラスを指定する。
ここでも、
テーブル結合する条件(detail_id)は必ずSQLに盛り込むこと。
interfaceやserviceなどは割愛。
Controller
MybatisController.java
@Controller
public class MybatisController {
@Autowired
MyBatisService myBatisService;
@GetMapping()
public String index(Model model) {
Player playerChoise = myBatisService.selectChoice("002");
//Item型のリストに詰めなおす
List<Item> itemsList = playerChoise.getItems();
model.addAttribute("itemsList", itemsList);
Jsp
<!-- th:eachで要素を1つずつ取得する -->
<div th:each="item : ${itemsList}">
<p th:text="${item.item}">
</div>