Spring Boot/MyBatis/Mapper/ResultMap/One To Many

Spring Boot/MyBatis/Mapper/ResultMap/One To Many

1:N 関係の結合を表すにはどうするか問題。

MyBatis は単に SQL の結果をどのようにオブジェクトに割り当てるかしか考えていないので、 多段結合や N:N には関知しない。

しかし 1:N の関係は結果が逆転する処理なのでどのように記述できるか興味深い。 S2JDBC ではこのへんの詰替えを非常に巧妙に行っていた。しかしページング処理がうまく動かないとかの問題もあった。

これの問題は SELECT したレコード数と実際の結果 List の size が一致しないからである。

Spring Boot/MyBatis/Mapper/ResultMap/Many To One

N:1 の関係性のマッピング。

親子関係があるテーブルで子から見て親を含むような結合をした結果を格納したい場合どうするか?

このような Domain を考える

Mapper で使う Domain には必ず引数の無いコンストラクタが必要になる。

public class Hoge{
    private Long hogeId;
    private List<Piyo> piyoList;
    private String name;
    private String memo;
    // 以下 引数無しコンストラクタ
    // getter setter
}
public class Piyo{
    private Long piyoId;
    private Long hogeId;
    private String name;
    private String memo;
    // 以下 引数無しコンストラクタ
    // getter setter
}

Hoge が Piyo を複数個保持しているような関係。よくありげ

この SQL はこんな感じになる。

  <select id="findByIdWithPiyo" resultMap="hogeResultMapWithPiyo">
    SELECT
        h.hoge_id AS hoge_id,
        h.piyo_id AS piyo_id,
        h.name    AS hoge_name,
        h.memo    AS hoge_memo,
        p.name    AS piyo_name,
        p.memo    AS piyo_memo
    FROM
        hoge h
    LEFT JOIN
        piyo p
        ON
           h.hoge_id = p.hoge_id
    WHERE
        p.hoge_id = #{hogeId}
        AND
        p.deleted = 0
    ;
  </select>

1:N の関係にて piyo を JOIN しているので結果レコード数は piyo のレコード数に従う。

この結果に対してこのようにマッピングする

<resultMap id="hogeResultMapWithPiyo" type="com.unko.domain.Hoge">
  <constructor>
    <idArg column="hoge_id" javaType="long" />
  </constructor>
  <result property="name" column="hoge_name"/>
  <result property="memo" column="hoge_memo"/>
  <collection property="piyoList" ofType="com.unko.domain.Piyo">
    <id property="piyoId" column="piyo_id"/>
    <result property="name" column="piyo_name"/>
    <result property="memo" column="piyo_memo"/>
  </collection>
</resultMap>

まず constructor という指定をしている。 ここは単純に com.unko.domain.Hoge のクラスが持つコンストラクタをどう使うのかを指定している。 この場合だと hoge_id という1つの値を取るコンストラクタを用意しておくということ。

次は今まで通りマッピング指定していく

次にリレーションで引っ張ってきた値に対してもマッピングする。 その時は association というタグを指定する property にはそれを格納するための setter を指定して javaType にはその型を指定する。

中は通常の mapping と同じ様に書く。

これで実行すると、hoge はもちろんその中の piyo も生成されて setPiyo される。

これはそのまま One To One であっても成立する。

java/spring/spring_boot/mybatis/mapper/select/result_map/one_to_many.txt · 最終更新: 2021-06-28 12:55 by ore