5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MyBatisを用いたMapping その1 #memo

Last updated at Posted at 2019-07-12

Mapper XMLファイル

Mapped StatementこそMyBatisの強みである。JDBCで同じ処理を書くのと比べると9割のコードが省略できるだろう。
Mapper XMLファイルの第一階層の要素は下記の通りである。(この順番で定義する必要がある)

  • cache: 指定されたネームスペースに対するキャッシュの設定
  • cache-ref: 別のネームスペースで定義されているキャッシュ設定を参照
  • resultMap: DBから取得した結果セットをJavaオブジェクトにマッピングするための情報を記述する。最も複雑だが重要な要素。
  • sql: 他のステートメントから参照することができる。再利用可能なSQL文字列。
  • insert: マップされたINSERTステートメント。
  • update: マップされたUPDATEステートメント。
  • delete: マップされたDELETEステートメント。
  • select: マップされたSELECTステートメント。

select

selectステートメントは、MyBatisで最も頻繁に使われる要素の一つ。insert, update, deleteのそれぞれに対して、多くのselectがあるはずだ。これはMyBatisの大原則の一つであり、クエリ発行と結果のマッピングに注力している理由でもある。シンプルなケースでは、select要素は非常に簡単である。

sample.xml
<select id="selectPerson" parameterType="int" resultType="hashmap">
   SELECT * FROM PERSON WHERE ID = #{id}
</select>

これはselectPersonというステートメントで、int(またはInteger)型の引数を取り、列名をkey、値をvalueとして保持するHashMapを返す。

// Similar JDBC code, NOT MyBatis...
String selectPerson = "SELECT * FROM PERSON WHERE ID=?";
PreparedStatement ps = conn.preoareStatement(selectPerson);
ps.setInt(1,id);

JDBC単体でselect結果を展開してオブジェクトのインスタンスにマップするためにはもっと多くのコードが必要だが、MyBatisを使えばそうしたコードは書かずに済む。ステートメントに関しては細かい設定ができるように、select要素には多くの属性がある。

   id="selectPerson"
   parameterType="int"
   resultType="hashmap"
   resultMap="personalResultMap"
   flushCache="false"
   useCache="true"
   timeout="10"
   fetchSize="256"
   statementType="PREPARED"
   resultSetType="FORWARD_ONLY">

Select Attributes

属性 説明
id このネームスペース内で固有な識別子。ステートメントを参照する際に使用
parameterType このステートメントに渡される引数の型。
resultType このステートメントから返されるオブジェクトの型。
resultMap 別の場所で定義されているresultMapを参照する。
flushCache trueを指定した場合、ステートメント実行時にローカルキャッシュおよび2次キャッシュがフラッシュ(クリア)される。selectステートメントではデフォルト値false
useCache trueを指定した場合、ステートメントの結果が2次キャッシュに保存される。
timeout 例外を投げるまでの最大待機時間。
fetchSize ドライバーが結果を返す際に内部的に使用するキャッシュのサイズ指定
statementType                  MyBatisがクエリを実行する際に使用するStatementの種類を指定。設定可能な値はSTATEMENT,PREPARED,CALLABLEで、それぞれStatement,PreparedStatement,CallableStatementが使用される。
resultSetType FORWARD_ONLY,SCROLL_SENSITIVE,SCROLL_INSENSITIVE,DEFAULTを指定。
databaseId databaseIdProviderが設定されている場合、MyBatisは定義されているステートメントの中でdatabaseId属性が指定されていないステートメントおよび現在の設定と一致するdatabaseId属性を持ったステートメントをロードする。
resultOrdered この属性は結果がネストされたselectステートメントでのみ有効である。trueが設定された場合、MyBatisはクエリの結果が正しい順番にソートされているという前提でマッピングを実行する。
resultSets 複数のResultSetを利用する場合にのみ有効。ステートメントが返すResultSetにそれぞれ任意の名前を付けてリストアップする。名前はカンマで区切る。

insert, update and delete

データを変更するステートメントであるinsert, update, deleteは非常によく似た実装となっている。

<insert
   id="insertAuthor"
   parameterType="domain.blog.Author"
   flushCache="true"
   statementType="PREPARED"
   keyProperty=""
   keyColumn=""
   userGeneratedKeys=""
   timeout="20">
<update
   id="updateAuthor"
   parameterType="domain.blog.Author"
   flushCache="true"
   statementType="PREPARED"
   timeout="20">
<delete
   id="deleteAuthor"
   parameterType="domain.blog.Author"
   flusjCache="true"
   statement="PREPARED"
   timeout="20">

Insert, Update and Delete Attributes

Attributes
id
parameterType
flushCache
timeout
statementType
useGeneratedKeys
keyProperty
keyColumn
databaseId
以下、insert, update, deleteステートメントの例をいくつか挙げる。
<insert id="insertAuthor">
   insert into Author (id, username, password, email, bio)
   values (#{id}, #{username}, #{password}, #{email}, #{bio})
</insert>
<update id="updateAuthor">
   update Author set
      username = #{username},
      password = #{password},
      email = #{email},
      bio = #{bio},
   where id = #{id}
</update>
<delete id="deleteAuthor">
   delete from Author where id = #{id}
</delete>

前述のように、insertは自動生成されたキーを扱うため、追加の属性や子要素を持つことができるようになっている。
MySQLにおいては、単純にuseGeneratedKeysにtrueを設定し、keyPropertyでキーが格納されるプロパティを指定する。例えば、上記のAuthorテーブルでid列に自動生成が設定されていた場合、ステートメントは次のように書く。

<insert id="insertAuthor" useGeneratedKeys="true" KeyProperty="id">
   insert into Author (username, password, email, bio)
   values (#{username}, #{password}, #{email}, #{bio})
</insert>

sql

この要素を使うと、再利用可能なSQLコードのスニペット(断片)を定義しておいて他のステートメントにインクルードすることができる。

   <sql id="userColumns"> ${alias}.id, ${alias}.username, ${alias}.

上記のSQLスニペットを他のステートメントにインクルードするには次のように記述する。

<select id="selectUsers" resultType="map">
   select
      <include refid="userColumns"><property name="alias" value="t1"/></include>,
      <include refid="userColumns"><property name="alias" value="t2"/></include>
   from some_table t1
   cross join some_table t2
</select>

呼び出し側のproperty要素で指定された値を、sql要素に内包されたinclude要素のrefid属性、やproperty要素のvalue属性として指定することも可能。

<sql id="sometable">
   ${prefix}Table
</sql>
<sql id="someinclude">
   from
      <include refid="${include_target}"/>
</sql>
<select id="select" resultType="map">
   select
      field1, field2, field3
   <include refid="someinclude">
      <property name="prefix" value="Some"/>
      <property name="include_target" value="sometable"/>
   </include>
</select>

Parameters

これまでのステートメントの例では、すべて単純なパラメータを利用していた。

<select id="selectUsers" resultType="User">
   select id, username, password
   from users
   where id = #{id}
</select>

上記は、名前を指定してパラメータを参照する単純型の例だが、パラメータとして複合型を渡した場合はもう少し複雑である。

<insert id="insertUser" parameterType="User">
   insert into users (id, username, password)
   values (#{id}, #{username}, #{password})
</insert>
5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?