MyBatisを使用したプログラミング方法¶
MyBatisについて¶
MyBatisはデータベースで管理されているレコードとオブジェクトをマッピングするという考え方ではなく、SQLとオブジェクトをマッピングという考え方で開発されたO/Rマッピングフレームワークです。複雑な結合条件、細かいクエリチューニングなど行う必要がある場合などに向いています。MyBatisの詳細については下記を参照してください。コラム
MyBatisは2.x系と3.x系で実装が異なります。TERASOLUNA Global Framework では、MyBatis2.3系を利用して実装します。
プログラミング方法¶
SQLMapの作成¶
- MyBatisの機能を利用するにあたり、実行するクエリを定義するSQLマップを作成する必要があります。例として、以下のようなXMLファイルを作成し、META-INF/mybatis/sql配下に配置します。このとき、ファイル名を 「*-sqlmap.xml」 としてください。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd"> <sqlMap namespace="mycompany"> <!-- ① --> <typeAlias alias="MyCompany" type="my.terasoluna.app.domain.model.MyCompany"/> <!-- ② --> <resultMap id="resultMapMyCompnay" class="MyCompany"> <!-- ③ --> <result property="companyId" column="company_id" /> <result property="name" column="name" /> </resultMap> <insert id="insert" parameterClass="MyCompany"> <!-- ④ --> INSERT INTO my_company (company_id, name) VALUES(#companyId#, #name#) </insert> <update id="update" parameterClass="MyCompany"> <!-- ⑤ --> UPDATE my_company SET name = #name# WHERE company_id = #companyId# </update> <delete id="delete" parameterClass="java.lang.String"> <!-- ⑥ --> DELETE FROM my_company WHERE company_id = #value# </delete> <select id="selectOne" parameterClass="java.lang.String" resultMap="resultMapMyCompnay"> <!-- ⑦ --> SELECT * FROM my_company WHERE company_id = #value# </select> <select id="selectAll" resultMap="resultMapMyCompnay"> <!-- ⑦ --> SELECT * FROM my_company </select> <select id="selectLessId" parameterClass="java.lang.String" resultMap="resultMapMyCompnay"> <!-- ⑧ --> <![CDATA[ SELECT * FROM my_company WHERE company_id < #value# ]]> </select> </sqlMap>
- <sqlMap>タグを定義します。namespace属性にこのSQLマップの任意の名称を付加します。なるべくアプリケーション全体でユニークとなる名称になるようにしてください。
- <typeAlias>タグを任意で配置します。type属性に指定したクラスパスをalias属性に指定した省略名で使用できるようになります。
- <resultMap>タグを任意で配置します。エンティティのフィールド名とカラム名が異なり再マッピングが必要な場合などに使用します。
- INSERT文を定義する場合、<insert>タグを使用します。ここではクエリにエンティティのフィールド値を埋め込むため、parameterClass属性に”MyCompany”(my.terasoluna.app.domain.model.MyCompanyクラス)を使用しています。パラメータを参照する場合は#で囲みフィールド名を指定します。
- UPDATE文を定義する場合、<update>タグを使用します。
- DELETE文を定義する場合、<delete>タグを使用します。ここでは主キーの条件に文字列を使用するため、parameterClassにStringを変数の参照に#value#を使用しています。
- SELECT文を定義する場合、<select>タグを使用します。検索結果は③で定義したresultMapのIDを指定し、値を再マッピングして返却されます。
- 条件分に不等号があるなどエスケープする必要がある場合、クエリまたは該当箇所に<![CDATA[ ]]>で囲みます。
コラム
その他様々なタグや機能がありますので、詳しくは リファレンス を参照してください。
リポジトリクラスの作成¶
- 任意のエンティティに対し、以下のようにリポジトリクラスを実装します。
package my.terasoluna.app.domain.repository; import java.util.List; import jp.terasoluna.fw.dao.QueryDAO; import jp.terasoluna.fw.dao.UpdateDAO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import my.terasoluna.app.domain.model.MyCompany; @Repository public class MyCompanyRepositoryMyBatisImpl implements MyCompanyRepositoryMyBatis { @Autowired UpdateDAO updateDAO; // ① @Autowired QueryDAO queryDAO; // ② @Override public void insert(MyCompany entity) { updateDAO.execute("mycompany.insert", entity); // ③ } @Override public void update(MyCompany entity) { updateDAO.execute("mycompany.update", entity); // ③ } @Override public void delete(String companyId) { updateDAO.execute("mycompany.delete", companyId); // ③ } @Override public MyCompany selectOne(String companyId) { return queryDAO.executeForObject("mycompany.selectOne", companyId, MyCompany.class); // ④ } @Override public List<MyCompany> selectAll(int offset, int pageSize) { return queryDAO.executeForObjectList("mycompany.selectAll", null, offset, pageSize); // ⑤ } @Override public List<MyCompany> selectLessId(String companyId) { return queryDAO.executeForObjectList("mycompany.selectLessId", companyId); } }
- 更新系クエリを使用する場合、UpdateDaoを定義します。
- 選択系クエリを使用する場合、QueryDaoを定義します。
- 更新系クエリを実行する場合、UpdateDao#executeを実行します。第一引数は使用するクエリを選択します。クエリ名は”SQLマップのnamespace属性.クエリのid”で指定します。第二引数はクエリの要求するパラメータクラスのオブジェクトをセットします。
- 単一レコードを検索する場合、QueryDao#executeForObjectを実行します。第一引数をクエリ名、第二引数に条件、 第三引数には検索結果のエンティティクラスを指定します。
- 複数レコードを検索する場合、QueryDao#executeForListを実行します。第一引数をクエリ名、第二引数に条件、 フェッチする場合は第三引数にオフセット、第四引数に取得件数をセットします。
シェアードデータベースの利用¶
applicationContext-im_tgfw_common.xml のsharedDataSourceのコメントアウトを外します。このとき、connectIdに対象シェアードデータベースの接続IDを指定します。<bean id="dataSource" class="jp.co.intra_mart.framework.extension.spring.datasource.TenantDataSource" /> <bean id="sharedDataSource" class="jp.co.intra_mart.framework.extension.spring.datasource.SharedDataSource"> <constructor-arg name="connectId" value="sharedA" /> </bean>applicationContext-im_tgfw_mybatis.xml の下記箇所のコメントアウトを外します。<bean id="sharedSqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean" scope="singleton"> <property name="configLocations" value="classpath*:/META-INF/mybatis/config/*sqlMapConfig.xml" /> <property name="mappingLocations" value="classpath*:/META-INF/mybatis/sql/**/*-sqlmap.xml" /> <property name="dataSource" ref="sharedDataSource" /> </bean> <bean id="sharedQueryDAO" class="jp.terasoluna.fw.dao.ibatis.QueryDAOiBatisImpl"> <property name="sqlMapClient" ref="sharedSqlMapClient" /> </bean> <bean id="sharedUpdateDAO" class="jp.terasoluna.fw.dao.ibatis.UpdateDAOiBatisImpl"> <property name="sqlMapClient" ref="sharedSqlMapClient" /> </bean> <bean id="sharedSpDAO" class="jp.terasoluna.fw.dao.ibatis.StoredProcedureDAOiBatisImpl"> <property name="sqlMapClient" ref="sharedSqlMapClient" /> </bean> <bean id="sharedQueryRowHandleDAO" class="jp.terasoluna.fw.dao.ibatis.QueryRowHandleDAOiBatisImpl"> <property name="sqlMapClient" ref="sharedSqlMapClient" /> </bean>リポジトリ実装クラスでTERASOLUNA DAOのフィールド定義箇所全てに@Qualifierアノテーションを付加し、使用するデータベース毎のbean Idを明示指定します。@Autowired @Qualifier("sharedQueryDAO") QueryDAO queryDAO;コラム
Jugglingプロジェクトの「追加リソースの選択」からTERASOLUNA Global Framework(...)設定ファイルを選択すると上記ファイルを含む設定ファイルがJugglingプロジェクト上に配置されます。チームで開発を行う場合、モジュールプロジェクト上に上記編集ファイルを配置すると他のモジュールプロジェクトに影響を与える可能性があるので、予めJugglingプロジェクト上から設定ファイルの編集を行ってください。