MyBatisでネストしたオブジェクトマッピングするサンプルあんまり見かけないので、残しておく。
例えばこんなデータを
person
id | name | address_id |
---|---|---|
1 | yamada | 11 |
2 | sato | 11 |
address
id | city |
---|---|
11 | tokyo |
book
id | title |
---|---|
21 | hoge |
22 | fuga |
23 | piyo |
person_book
person_id | book_id |
---|---|
1 | 21 |
1 | 22 |
2 | 23 |
こんなオブジェクトにマッピングしたい時。。
public class Person { private Address address; private List<Book> books; // アクセサは省略 }
こんな感じになる
<mapper> <resultMap id="personMap" type="Person"> <id column="person_id"/> <association property="address" javaType="Address"> <id property="id" column="address_id"/> <result property="city" column="address_city" /> </association> <collection property="books" ofType="Book"> <id property="id" column="book_id"/> <result property="title" column="book_title"/> </collection> </resultMap> <select id="selectPerson" resultMap="personMap"> select person.id AS person_id address.id AS address_id, address.city AS address_city, book.id AS book_id, book.title AS book_title from person person inner join address address on person.address_id = address.id inner join person_book person_book on person.id = person_book.person_id inner join book book on person_book.book_id = book.id where person.id = 1 </select> </mapper>
<id>
の指定を忘れない
TooManyResultsExceptionなどが発生してマッピングが期待通りに行かない時は、<id>
の指定が漏れていないか確認してみる。
Personクラスではあえてネストしたオブジェクト以外のフィールドを持たせていないが、その場合でも必須になる。(オブジェクトにマッピングする必要がなくても、idは必要)
これはMyBatis側で生成するインスタンスを一意に判別する必要があるからだと思われる。