Java API
MyBatisの設定方法とマッピングの作成方法を理解したところで、いよいよ本題に入ります。MyBatis Java APIは、これまでの努力の成果を実感できる場所です。ご覧のとおり、JDBCと比較して、MyBatisはコードを大幅に簡素化し、クリーンで理解しやすく、保守しやすいものにしてくれます。MyBatis 3では、SQLマップの操作をさらに向上させるための多くの重要な改善が導入されています。
ディレクトリ構造
Java API自体に深く入る前に、ディレクトリ構造に関するベストプラクティスを理解することが重要です。MyBatisは非常に柔軟性が高く、ファイルに対してほぼ何でも行うことができます。しかし、他のフレームワークと同様に、推奨される方法があります。
一般的なアプリケーションのディレクトリ構造を見てみましょう。
/my_application
/bin
/devlib
/lib <-- MyBatis *.jar files go here.
/src
/org/myapp/
/action
/data <-- MyBatis artifacts go here, including, Mapper Classes, XML Configuration, XML Mapping Files.
/mybatis-config.xml
/BlogMapper.java
/BlogMapper.xml
/model
/service
/view
/properties <-- Properties included in your XML Configuration go here.
/test
/org/myapp/
/action
/data
/model
/service
/view
/properties
/web
/WEB-INF
/web.xml
繰り返しますが、これらは推奨事項であり、必須要件ではありませんが、共通のディレクトリ構造を使用することで、他の人々が感謝してくれるでしょう。
このセクションの残りの例では、このディレクトリ構造に従っていることを前提としています。
SqlSessions
MyBatisを使用するための主要なJavaインターフェースはSqlSessionです。このインターフェースを通じて、コマンドの実行、マッパーの取得、トランザクションの管理を行うことができます。SqlSession自体については後ほど詳しく説明しますが、まずSqlSessionのインスタンスの取得方法を学ぶ必要があります。SqlSessionsはSqlSessionFactoryインスタンスによって作成されます。SqlSessionFactoryには、さまざまな方法でSqlSessionsのインスタンスを作成するためのメソッドが含まれています。SqlSessionFactory自体は、XML、アノテーション、または手動でコーディングされたJava構成からSqlSessionFactoryを作成できるSqlSessionFactoryBuilderによって作成されます。
注記 SpringやGuiceなどの依存性注入フレームワークでMyBatisを使用する場合、SqlSessionsはDIフレームワークによって作成され注入されるため、SqlSessionFactoryBuilderまたはSqlSessionFactoryを使用する必要はなく、SqlSessionセクションに直接進むことができます。詳細については、MyBatis-SpringまたはMyBatis-Guiceのマニュアルを参照してください。
SqlSessionFactoryBuilder
SqlSessionFactoryBuilderには5つのbuild()メソッドがあり、それぞれ異なるソースからSqlSessionFactoryを構築できます。
SqlSessionFactory build(InputStream inputStream)
SqlSessionFactory build(InputStream inputStream, String environment)
SqlSessionFactory build(InputStream inputStream, Properties properties)
SqlSessionFactory build(InputStream inputStream, String env, Properties props)
SqlSessionFactory build(Configuration config)
最初の4つのメソッドは、XMLドキュメント、より具体的には上記で説明したmybatis-config.xmlファイルを指すInputStreamインスタンスを受け取るため、最も一般的です。オプションのパラメータは、環境とプロパティです。環境は、データソースとトランザクションマネージャーを含む、ロードする環境を決定します。例:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
...
<dataSource type="POOLED">
...
</environment>
<environment id="production">
<transactionManager type="MANAGED">
...
<dataSource type="JNDI">
...
</environment>
</environments>
environmentパラメータを受け取るbuildメソッドを呼び出すと、MyBatisはその環境の構成を使用します。もちろん、無効な環境を指定すると、エラーが発生します。environmentパラメータを受け取らないbuildメソッドのいずれかを呼び出すと、デフォルトの環境が使用されます(上記の例ではdefault="development"として指定されています)。
propertiesインスタンスを受け取るメソッドを呼び出すと、MyBatisはこれらのプロパティをロードし、構成で使用できるようにします。これらのプロパティは、構成内のほとんどの値の代わりに、${propName}という構文を使用して使用できます。
プロパティはmybatis-config.xmlファイルから参照することも、直接指定することもできることを思い出してください。そのため、優先順位を理解することが重要です。このドキュメントの前の方で既に言及しましたが、簡単に参照できるようにここで改めて説明します。
複数の場所にプロパティが存在する場合、MyBatisは次の順序でロードします。
- properties要素の本体で指定されたプロパティが最初に読み取られます。
- properties要素のclasspath resourceまたはurl属性からロードされたプロパティが2番目に読み取られ、既に指定されている重複プロパティを上書きします。
- メソッドパラメータとして渡されたプロパティが最後に読み取られ、propertiesの本体とresource/url属性からロードされた重複プロパティを上書きします。
したがって、優先順位が最も高いプロパティは、メソッドパラメータとして渡されたプロパティであり、次にresource/url属性、最後にproperties要素の本体で指定されたプロパティとなります。
要約すると、最初の4つのメソッドはほぼ同じですが、環境と/またはプロパティをオプションで指定できるようにオーバーライドされています。mybatis-config.xmlファイルからSqlSessionFactoryを構築する例を以下に示します。
String resource = "org/mybatis/builder/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
org.apache.ibatis.ioパッケージにあるResourcesユーティリティクラスを使用していることに注意してください。Resourcesクラスは、その名前が示すように、クラスパス、ファイルシステム、またはWeb URLからリソースをロードするのに役立ちます。クラスのソースコードを簡単に確認するか、IDEで検査すると、非常に分かりやすい便利なメソッドセットが表示されます。簡単なリストを以下に示します。
URL getResourceURL(String resource)
URL getResourceURL(ClassLoader loader, String resource)
InputStream getResourceAsStream(String resource)
InputStream getResourceAsStream(ClassLoader loader, String resource)
Properties getResourceAsProperties(String resource)
Properties getResourceAsProperties(ClassLoader loader, String resource)
Reader getResourceAsReader(String resource)
Reader getResourceAsReader(ClassLoader loader, String resource)
File getResourceAsFile(String resource)
File getResourceAsFile(ClassLoader loader, String resource)
InputStream getUrlAsStream(String urlString)
Reader getUrlAsReader(String urlString)
Properties getUrlAsProperties(String urlString)
Class classForName(String className)
最後のbuildメソッドは、Configurationインスタンスを受け取ります。Configurationクラスには、SqlSessionFactoryインスタンスに関するあらゆる必要な情報が含まれています。Configurationクラスは、SQLマップの検索と操作(アプリケーションがリクエストを受け付けている場合は推奨されません)を含む、構成のイントロスペクションに役立ちます。configurationクラスには、既に学習したすべての構成スイッチがあり、Java APIとして公開されています。Configurationインスタンスを手動で作成し、build()メソッドに渡してSqlSessionFactoryを作成する簡単な例を以下に示します。
DataSource dataSource = BaseDataTest.createBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.setLazyLoadingEnabled(true);
configuration.setEnhancementEnabled(true);
configuration.getTypeAliasRegistry().registerAlias(Blog.class);
configuration.getTypeAliasRegistry().registerAlias(Post.class);
configuration.getTypeAliasRegistry().registerAlias(Author.class);
configuration.addMapper(BoundBlogMapper.class);
configuration.addMapper(BoundAuthorMapper.class);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(configuration);
これで、SqlSessionインスタンスの作成に使用できるSqlSessionFactoryができました。
SqlSessionFactory
SqlSessionFactoryには、SqlSessionインスタンスを作成するために使用される6つのメソッドがあります。一般的に、これらのメソッドのいずれかを選択する際に決定することとなるのは次のとおりです。
- トランザクション: セッションに対してトランザクションスコープを使用しますか、それとも自動コミットを使用しますか(ほとんどのデータベースや/またはJDBCドライバでは、通常はトランザクションを使用しないことを意味します)?
- 接続: MyBatisが構成されたDataSourceから接続を取得するか、自分で提供しますか?
- 実行: MyBatisがPreparedStatementsと/またはバッチ更新(挿入と削除を含む)を再利用しますか?
オーバーロードされたopenSession()メソッドのシグネチャセットにより、意味のあるこれらのオプションの任意の組み合わせを選択できます。
SqlSession openSession()
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType, Connection connection)
Configuration getConfiguration();
パラメータを受け取らないデフォルトのopenSession()メソッドは、次の特性を持つSqlSessionを作成します。
- トランザクションスコープが開始されます(つまり、自動コミットではありません)。
- アクティブな環境によって構成されたDataSourceインスタンスから
Connectionオブジェクトが取得されます。 - トランザクションの分離レベルは、ドライバまたはデータソースによって使用されるデフォルトになります。
- PreparedStatementsは再利用されず、更新はバッチ処理されません。
ほとんどのメソッドは、かなり分かりやすいです。自動コミットを有効にするには、オプションのautoCommitパラメータにtrueの値を渡します。独自の接続を提供するには、connectionパラメータにConnectionインスタンスを渡します。ConnectionとautoCommitの両方を設定するオーバーライドはありません。MyBatisは、提供された接続オブジェクトが現在使用している設定を使用するためです。MyBatisは、トランザクション分離レベルに対してTransactionIsolationLevelと呼ばれるJava列挙型ラッパーを使用しますが、それ以外は期待どおりに動作し、JDBCでサポートされている5つのレベル(NONE、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE)があります。
あなたにとって新しい可能性のあるパラメータはExecutorTypeです。この列挙型は3つの値を定義します。
ExecutorType.SIMPLE: このタイプのエグゼキュータは特別なことを何も行いません。ステートメントの実行ごとに新しいPreparedStatementを作成します。ExecutorType.REUSE: このタイプのエグゼキュータはPreparedStatementsを再利用します。ExecutorType.BATCH: このエグゼキュータはすべての更新ステートメントをバッチ処理し、間にSELECTが実行された場合に必要な区切りを付け、分かりやすい動作を確実にします。
注記 言及しなかったSqlSessionFactoryのメソッドがもう1つあり、それはgetConfiguration()です。このメソッドは、実行時にMyBatis構成をイントロスペクトするために使用できるConfigurationインスタンスを返します。
注記以前のバージョンのMyBatisを使用していた場合、セッション、トランザクション、バッチはすべて別個のものであることを思い出してください。これはもはや当てはまりません。これら3つはすべて、セッションのスコープ内にきちんと含まれています。それらのメリットを最大限に享受するために、トランザクションやバッチを個別に処理する必要はありません。
SqlSession
上記のように、SqlSessionインスタンスはMyBatisで最も強力なクラスです。ステートメントを実行し、トランザクションをコミットまたはロールバックし、マッパーインスタンスを取得するためのすべてのメソッドがあります。
SqlSessionクラスには20個以上のメソッドがあるため、より消化しやすいグループに分割しましょう。
ステートメント実行メソッド
これらのメソッドは、SQLマッピングXMLファイルで定義されているSELECT、INSERT、UPDATE、DELETEステートメントを実行するために使用されます。非常に分かりやすく、それぞれステートメントのIDとパラメータオブジェクト(プリミティブ(自動ボックス化またはラッパー)、JavaBean、POJO、またはMap)を受け取ります。
<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<T> Cursor<T> selectCursor(String statement, Object parameter)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)
selectOneとselectListの違いは、selectOneが正確に1つのオブジェクトまたはnull(なし)を返す必要がある点だけです。2つ以上の場合、例外がスローされます。オブジェクトの数が不明な場合は、selectListを使用します。オブジェクトの存在を確認する場合は、カウント(0または1)を返す方が良いでしょう。selectMapは、結果のオブジェクトのプロパティの1つに基づいて、結果のリストをMapに変換するように設計されている特別なケースです。すべてステートメントがパラメータを必要とするわけではないため、これらのメソッドはパラメータオブジェクトを必要としないバージョンでオーバーロードされています。
insert、update、deleteメソッドによって返される値は、ステートメントによって影響を受けた行数を示します。
<T> T selectOne(String statement)
<E> List<E> selectList(String statement)
<T> Cursor<T> selectCursor(String statement)
<K,V> Map<K,V> selectMap(String statement, String mapKey)
int insert(String statement)
int update(String statement)
int delete(String statement)
CursorはIteratorを使用してデータを遅延フェッチすることを除いて、Listと同じ結果を提供します。
try (Cursor<MyEntity> entities = session.selectCursor(statement, param)) {
for (MyEntity entity : entities) {
// process one entity
}
}
最後に、selectメソッドの3つの高度なバージョンがあり、返す行の範囲を制限したり、通常は非常に大きなデータセットに対してカスタムの結果処理ロジックを提供したりできます。
<E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds)
<T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds)
void select (String statement, Object parameter, ResultHandler<T> handler)
void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler)
RowBoundsパラメータにより、MyBatisは指定された数のレコードをスキップし、返される結果の数を特定の数に制限します。RowBoundsクラスには、offsetとlimitの両方を取得するためのコンストラクタがあり、それ以外は不変です。
int offset = 100;
int limit = 25;
RowBounds rowBounds = new RowBounds(offset, limit);
異なるドライバは、この点で異なるレベルの効率を実現できます。最高の性能を得るには、SCROLL_SENSITIVEまたはSCROLL_INSENSITIVEの結果セットタイプを使用します(つまり、FORWARD_ONLYではありません)。
ResultHandlerパラメータを使用すると、行を好きなように処理できます。Listに追加したり、Map、Setを作成したり、各結果を破棄して代わりに計算の合計値のみを保持したりできます。ResultHandlerではほぼ何でも実行でき、MyBatis自体が内部的に結果セットリストを構築するために使用しているものです。
3.4.6 以降、CALLABLE ステートメントに渡されるResultHandlerは、ストアドプロシージャにREFCURSOR出力パラメータが存在する場合、そのすべてで使用されます。
インターフェースは非常にシンプルです。
package org.apache.ibatis.session;
public interface ResultHandler<T> {
void handleResult(ResultContext<? extends T> context);
}
ResultContextパラメータを使用すると、結果オブジェクト自体、作成された結果オブジェクトの数、およびMyBatisによるそれ以上の結果の読み込みを停止するために使用できるBoolean stop()メソッドにアクセスできます。
ResultHandlerの使用には、認識しておくべき2つの制限があります。
ResultHandlerを使用して呼び出されたメソッドから取得されたデータは、キャッシュされません。- 高度な
resultMapを使用する場合、MyBatisはオブジェクトの構築に複数の行を必要とする可能性があります。ResultHandlerを使用すると、関連付けやコレクションがまだ満たされていないオブジェクトが渡される場合があります。
バッチ更新ステートメント フラッシュメソッド
JDBCドライバクラスに格納されているバッチ更新ステートメントをいつでもフラッシュ(実行)するためのメソッドがあります。このメソッドは、ExecutorTypeがExecutorType.BATCHの場合に使用できます。
List<BatchResult> flushStatements()
トランザクション制御メソッド
トランザクションのスコープを制御するための4つのメソッドがあります。もちろん、自動コミットを使用する場合、または外部トランザクションマネージャを使用している場合は、これらは効果がありません。ただし、Connectionインスタンスによって管理されるJDBCトランザクションマネージャを使用している場合は、役立つ4つのメソッドがあります。
void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)
デフォルトでは、MyBatisは、insert、update、delete、またはaffectDataを有効にしたselectへの呼び出しによってデータベースが変更されたことを検出しない限り、実際にはコミットしません。これらのメソッドを呼び出さずに何らかの変更を行った場合は、commitおよびrollbackメソッドにtrueを渡して、確実にコミットされるようにすることができます(ただし、自動コミットモードのセッション、または外部トランザクションマネージャを使用しているセッションを強制することはできません)。ほとんどの場合、rollback()を呼び出す必要はありません。コミットを呼び出さない場合、MyBatisが自動的にロールバックします。ただし、複数のコミットとロールバックが可能なセッションをより細かく制御する必要がある場合は、ロールバックオプションを使用してそれを実現できます。
注記 MyBatis-SpringとMyBatis-Guiceは、宣言的なトランザクション処理を提供します。そのため、SpringまたはGuiceでMyBatisを使用する場合は、それぞれのマニュアルを参照してください。
ローカルキャッシュ
MyBatisは、ローカルキャッシュとセカンダリキャッシュの2つのキャッシュを使用します。
新しいセッションが作成されるたびに、MyBatisはローカルキャッシュを作成し、セッションにアタッチします。セッション内で実行されるすべてのクエリはローカルキャッシュに格納されるため、同じ入力パラメータを持つ同じクエリのさらなる実行はデータベースにヒットしません。ローカルキャッシュは、update、commit、rollback、およびclose時にクリアされます。
デフォルトでは、ローカルキャッシュデータはセッション期間全体で使用されます。このキャッシュは、循環参照を解決し、繰り返しネストされたクエリの速度を向上させるために必要であるため、完全に無効にすることはできませんが、localCacheScope=STATEMENTを設定することで、ステートメント実行の期間のみ使用されるようにローカルキャッシュを構成できます。
localCacheScopeがSESSIONに設定されている場合、MyBatisはローカルキャッシュに格納されている同じオブジェクトへの参照を返します。返されたオブジェクト(リストなど)の変更は、ローカルキャッシュの内容、およびセッションの存続期間中にキャッシュから返される値に影響します。したがって、ベストプラクティスとして、MyBatisによって返されたオブジェクトを変更しないでください。
次の呼び出しによって、いつでもローカルキャッシュをクリアできます。
void clearCache()
SqlSessionのクローズの保証
void close()
最も重要なことは、開いたセッションをすべて閉じることを保証することです。これを実現する最良の方法は、次の作業単位パターンを使用することです。
try (SqlSession session = sqlSessionFactory.openSession()) {
// following 3 lines are pseudocode for "doing some work"
session.insert(...);
session.update(...);
session.delete(...);
session.commit();
}
注記 SqlSessionFactoryと同様に、getConfiguration()メソッドを呼び出すことで、SqlSessionが使用しているConfigurationのインスタンスを取得できます。
Configuration getConfiguration()
マッパーの使用
<T> T getMapper(Class<T> type)
上記のさまざまなinsert、update、delete、selectメソッドは強力ですが、非常に冗長で、型安全ではなく、IDEや単体テストに役立つものではありません。上記の「はじめに」セクションでは、Mapperの使用例を既に示しています。
したがって、マップされたステートメントを実行するより一般的な方法は、Mapperクラスを使用することです。Mapperクラスは、SqlSessionメソッドに一致するメソッド定義を持つインターフェースです。次の例クラスは、いくつかのメソッドシグネチャと、それらがSqlSessionにどのようにマップされるかを示しています。
public interface AuthorMapper {
// (Author) selectOne("selectAuthor", 5);
Author selectAuthor(int id);
// (List<Author>) selectList("selectAuthors")
List<Author> selectAuthors();
// (Map<Integer,Author>) selectMap("selectAuthors", "id")
@MapKey("id")
Map<Integer, Author> selectAuthors();
// insert("insertAuthor", author)
int insertAuthor(Author author);
// updateAuthor("updateAuthor", author)
int updateAuthor(Author author);
// delete("deleteAuthor", 5)
int deleteAuthor(int id);
}
簡単に言えば、各Mapperメソッドシグネチャは、関連付けられたSqlSessionメソッドのシグネチャと一致する必要がありますが、StringパラメータIDは除きます。代わりに、メソッド名はマップされたステートメントIDと一致する必要があります。
さらに、戻り値の型は、単一の結果の場合は期待される結果型と一致する必要があります。複数結果の場合は配列またはコレクション、またはCursorと一致する必要があります。プリミティブ、Maps、POJO、JavaBeansなど、すべての通常の型がサポートされています。
注記 マッパーインターフェースは、インターフェースを実装したり、クラスを拡張したりする必要はありません。メソッドシグネチャを使用して、対応するマップされたステートメントを一意に識別できる限りです。
注記 マッパーインターフェースは他のインターフェースを拡張できます。XMLバインディングをMapperインターフェースに使用する場合は、ステートメントが適切な名前空間に存在することを確認してください。また、唯一の制限は、階層内の2つのインターフェースで同じメソッドシグネチャを持つことができないことです(いずれにしても悪い考えです)。
マッパーメソッドに複数のパラメータを渡すことができます。その場合、デフォルトでは「param」というリテラルに続いてパラメータリストでの位置が付けられます。たとえば、#{param1}、#{param2}などです。パラメータの名前を変更する場合は(複数の場合のみ)、パラメータに@Param("paramName")アノテーションを使用できます。
クエリ結果を制限するために、RowBoundsインスタンスをメソッドに渡すこともできます。
マッパーアノテーション
MyBatisは、当初からXML駆動のフレームワークでした。構成はXMLベースであり、マップされたステートメントはXMLで定義されています。MyBatis 3では、新しいオプションが利用可能になりました。MyBatis 3は、包括的で強力なJavaベースの構成APIを基盤として構築されています。この構成APIは、XMLベースのMyBatis構成と、新しいアノテーションベースの構成の基礎となります。アノテーションは、多くのオーバーヘッドを導入することなく、単純なマップされたステートメントを簡単に実装する方法を提供します。
注記 Javaアノテーションは、表現力と柔軟性に限界があります。多くの調査、設計、試行錯誤を行ったにもかかわらず、最も強力なMyBatisマッピングは、ばかげたものにならない限り、アノテーションでは構築できません。C#属性(例)はこれらの制限を受けないため、MyBatis.NETはXMLに比べてはるかに豊富な代替手段を利用できます。つまり、Javaアノテーションベースの構成には、メリットがないわけではありません。
アノテーションは次のとおりです。
| アノテーション | 対象 | XML相当 | 説明 |
|---|---|---|---|
@CacheNamespace |
クラス |
<cache> |
指定された名前空間(つまり、クラス)のキャッシュを構成します。属性:implementation、eviction、flushInterval、size、readWrite、blocking、properties。 |
@Property |
N/A | <property> |
プロパティ値またはプレースホルダーを指定します(mybatis-config.xmlで定義された構成プロパティで置き換えることができます)。属性:name、value。(MyBatis 3.4.2以降で使用可能) |
@CacheNamespaceRef |
クラス |
<cacheRef> |
使用する別の名前空間のキャッシュを参照します。XMLマッパーファイルで宣言されたキャッシュは、同じFQCNを共有していても、個別の名前空間と見なされます。属性:valueとname。このアノテーションを使用する場合は、valueまたはname属性のいずれかを指定する必要があります。value属性には、名前空間を示すJava型を指定し、name属性(この属性は3.4.2以降で使用可能)には、名前空間を示す名前を指定します。 |
@ConstructorArgs |
メソッド |
<constructor> |
結果オブジェクトコンストラクタに渡される結果のグループを収集します。属性:value(Argの配列)。 |
@Arg |
N/A |
|
ConstructorArgsコレクションの一部である単一のコンストラクタ引数。属性:id、column、javaType、jdbcType、typeHandler、select、resultMap。id属性は、比較に使用されるプロパティを識別するブール値であり、<idArg> XML要素に似ています。3.5.4以降、繰り返しアノテーションとして使用できます。 |
@TypeDiscriminator |
メソッド |
<discriminator> |
実行する結果マッピングを決定するために使用できる値ケースのグループ。属性:column、javaType、jdbcType、typeHandler、cases。cases属性は、Caseの配列です。 |
@Case |
N/A | <case> |
値とその対応するマッピングの単一のケース。属性:value、type、results。results属性は、Resultの配列であるため、このCaseアノテーションは、下記のResultsアノテーションで指定された実際のResultMapに似ています。 |
@Results |
メソッド |
<resultMap> |
特定の結果列がプロパティまたはフィールドにどのようにマップされるかの詳細を含む、結果マッピングのリスト。属性:value、id。value属性は、Resultアノテーションの配列です。id属性は、結果マッピングの名前です。 |
@Result |
N/A |
|
列とプロパティまたはフィールド間の単一の結果マッピング。属性:id、column、property、javaType、jdbcType、typeHandler、one、many。id属性は、プロパティを比較に使用すべきであることを示すブール値であり(XMLマッピングの<id>に似ています)、one属性は<association>と同様の単一の関連付け用であり、many属性は<collection>と同様のコレクション用です。クラス名の競合を避けるために、このように命名されています。3.5.4以降、繰り返しアノテーションとして使用できます。 |
@One |
N/A | <association> |
複合型の単一プロパティ値へのマッピング。属性:select(適切な型のインスタンスを読み込むことができるマップされたステートメント(つまり、マッパーメソッド)の完全修飾名)。fetchType(このマッピングに対してグローバル構成パラメータlazyLoadingEnabledを上書きします)。resultMap(3.5.5以降で使用可能)、これはselect結果から単一コンテナオブジェクトにマップする結果マップの完全修飾名です。columnPrefix(3.5.5以降で使用可能)、ネストされた結果マップでselect列をグループ化する列プレフィックスです。注記 アノテーションAPIでは、結合マッピングはサポートされていないことに注意してください。これは、Javaアノテーションの制限によるもので、循環参照を許可しません。 |
@Many |
N/A | <collection> |
複合型の集合プロパティへのマッピング。属性:select は、適切な型のインスタンスの集合をロードできるマップ済みステートメント(つまり、マッパーメソッド)の完全修飾名。fetchType は、このマッピングに対してグローバル設定パラメーターlazyLoadingEnabledを上書きする。resultMap(3.5.5以降で利用可能)は、select結果から集合オブジェクトにマップするresultMapの完全修飾名。columnPrefix(3.5.5以降で利用可能)は、ネストされたresultMapでselect列をグループ化するための列プレフィックス。注記 アノテーションAPIでは、ジョインマッピングはサポートされていないことに注意してください。これは、Javaアノテーションの制約により、循環参照が許可されないためです。 |
@MapKey |
メソッド |
戻り値の型がMapであるメソッドで使用されます。オブジェクトのプロパティに基づいて、結果オブジェクトのリストをMapに変換するために使用されます。属性:value は、マップのキーとして使用されるプロパティ。 | |
@Options |
メソッド |
マップ済みステートメントの属性。 | このアノテーションは、通常、マップ済みステートメントの属性として存在する幅広いスイッチと設定オプションへのアクセスを提供します。各ステートメントアノテーションを複雑にする代わりに、Optionsアノテーションは、これらにアクセスするための整合性があり明確な方法を提供します。属性:useCache=true、flushCache=FlushCachePolicy.DEFAULT、resultSetType=DEFAULT、statementType=PREPARED、fetchSize=-1、timeout=-1、useGeneratedKeys=false、keyProperty=""、keyColumn=""、resultSets=""、databaseId=""。Javaアノテーションでは、値としてnullを指定する方法がないことを理解することが重要です。そのため、Optionsアノテーションを使用すると、ステートメントはすべてのデフォルト値の影響を受けます。予期しない動作を避けるために、デフォルト値に注意してください。databaseId(3.5.5以降で利用可能)は、DatabaseIdProviderが設定されている場合、MyBatisはdatabaseId属性のないOptionsまたは現在のものと一致するdatabaseIdを持つOptionsを使用します。databaseIdありとなしの両方が見つかった場合、後者は破棄されます。keyColumnは、特定のデータベース(OracleやPostgreSQLなど)でのみ必要です。これらの属性の許容値の詳細については、上記の挿入ステートメントに関する説明でkeyColumnとkeyPropertyに関する説明を参照してください。 |
|
メソッド |
|
これらのアノテーションはそれぞれ、実行される実際のSQLを表します。それぞれ、文字列の配列(または単一の文字列でも可)を受け取ります。文字列の配列が渡された場合、それらはそれぞれを区切るために単一のスペースで連結されます。これは、JavaコードでSQLを構築する場合の「スペースの欠落」問題を回避するのに役立ちます。ただし、必要に応じて単一の文字列を連結することもできます。属性:value は、単一のSQLステートメントを形成する文字列の配列。databaseId(3.5.5以降で利用可能)は、DatabaseIdProviderが設定されている場合、MyBatisはdatabaseId属性のないステートメントまたは現在のものと一致するdatabaseIdを持つステートメントを使用します。databaseIdありとなしの両方が見つかった場合、後者は破棄されます。 |
|
メソッド |
|
動的SQLの作成を可能にします。これらの代替SQLアノテーションを使用すると、実行時に実行するSQLを返すクラスとメソッド名を指定できます(3.4.6以降、メソッドの戻り値の型としてStringの代わりにCharSequenceを指定できます)。マップ済みステートメントを実行すると、MyBatisは指定されたプロバイダーによってクラスをインスタンス化し、メソッドを実行します。マッパーメソッドの引数に渡されたオブジェクト、"Mapperインターフェース型"、"Mapperメソッド"、"Database ID"をProviderContext(MyBatis 3.4.5以降で利用可能)経由でメソッド引数として渡すことができます。(MyBatis 3.4以降では、複数のパラメーターが許可されています)属性:value、type、method、databaseId。valueとtype属性はクラスです(type属性はvalueのエイリアスであり、どちらか一方を指定する必要があります。ただし、グローバル設定としてdefaultSqlProviderTypeを指定する場合は、両方の属性を省略できます)。methodはそのクラスのメソッド名です(3.5.1以降、method属性を省略できます。MyBatisはProviderMethodResolverインターフェースを介してターゲットメソッドを解決します。それによって解決されない場合、MyBatisはprovideSqlという名前の予約済みのフォールバックメソッドを使用します)。databaseId(3.5.5以降で利用可能)は、DatabaseIdProviderが設定されている場合、MyBatisはdatabaseId属性のないプロバイダーメソッドまたは現在のものと一致するdatabaseIdを持つプロバイダーメソッドを使用します。databaseIdありとなしの両方が見つかった場合、後者は破棄されます。注記 このセクションの後に、よりクリーンで読みやすい方法で動的SQLを構築するのに役立つクラスに関する説明があります。 |
@Param |
パラメーター |
N/A | マッパーメソッドが複数のパラメーターを受け取る場合、このアノテーションをマッパーメソッドのパラメーターに適用して、それぞれに名前を付けることができます。それ以外の場合は、複数のパラメーターは、"param"というプレフィックスが付いた位置で名前付けられます(RowBoundsパラメーターは含まれません)。たとえば、#{param1}、#{param2}などはデフォルトです。@Param("person")を使用すると、パラメーターの名前は#{person}になります。 |
@SelectKey |
メソッド |
<selectKey> |
このアノテーションは、@Insert、@InsertProvider、@Update、または@UpdateProviderでアノテーション付けされたメソッドの<selectKey>機能を複製します。他のメソッドでは無視されます。@SelectKeyアノテーションを指定した場合、MyBatisは@Optionsアノテーションまたは設定プロパティを介して設定された生成されたキープロパティを無視します。属性:statementは、実行するSQLステートメントである文字列の配列、keyPropertyは新しい値で更新されるパラメーターオブジェクトのプロパティ、beforeは、SQLステートメントを挿入の前または後に実行する必要があるかどうかを示すtrueまたはfalseのいずれかである必要があります、resultTypeはkeyPropertyのJava型、statementTypeはステートメントの型で、STATEMENT、PREPARED、CALLABLEのいずれかで、それぞれStatement、PreparedStatement、CallableStatementにマップされます。デフォルトはPREPAREDです。databaseId(3.5.5以降で利用可能)は、DatabaseIdProviderが設定されている場合、MyBatisはdatabaseId属性のないステートメントまたは現在のものと一致するdatabaseIdを持つステートメントを使用します。databaseIdありとなしの両方が見つかった場合、後者は破棄されます。 |
@ResultMap |
メソッド |
N/A | このアノテーションは、XMLマッパーの<resultMap>要素のIDを@Selectまたは@SelectProviderアノテーションに提供するために使用されます。これにより、アノテーションされたselectは、XMLで定義されているresultMapを再利用できます。このアノテーションは、アノテーションされたselectに@Resultsまたは@ConstructorArgsアノテーションの両方が指定されている場合、それらを上書きします。 |
@ResultType |
メソッド |
N/A | このアノテーションは、結果ハンドラーを使用する場合に使用されます。その場合、戻り値の型はvoidなので、MyBatisは各行に対して構築するオブジェクトの型を決定する必要があります。XML resultMapがある場合は、@ResultMapアノテーションを使用します。結果型が<select>要素でXMLに指定されている場合、他のアノテーションは必要ありません。その他の場合は、このアノテーションを使用します。たとえば、@Selectでアノテーション付けされたメソッドが結果ハンドラーを使用する場合、戻り値の型はvoidでなければならず、このアノテーション(または@ResultMap)が必要です。このアノテーションは、メソッドの戻り値の型がvoidでない限り、無視されます。 |
@Flush |
メソッド |
N/A | このアノテーションが使用されている場合、マッパーインターフェースで定義されたメソッドを介してSqlSession#flushStatements()を呼び出すことができます。(MyBatis 3.3以降) |
マッパーアノテーションの例
この例は、挿入の前にシーケンスから値を取得するために@SelectKeyアノテーションを使用する方法を示しています。
@Insert("insert into table3 (id, name) values(#{nameId}, #{name})")
@SelectKey(statement="call next value for TestSequence", keyProperty="nameId", before=true, resultType=int.class)
int insertTable3(Name name);
この例は、挿入後にID値を取得するために@SelectKeyアノテーションを使用する方法を示しています。
@Insert("insert into table2 (name) values(#{name})")
@SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class)
int insertTable2(Name name);
この例は、@Flushアノテーションを使用してSqlSession#flushStatements()を呼び出す方法を示しています。
@Flush
List<BatchResult> flush();
これらの例は、@Resultsアノテーションのid属性を指定してResultMapに名前を付ける方法を示しています。
@Results(id = "userResult", value = {
@Result(property = "id", column = "uid", id = true),
@Result(property = "firstName", column = "first_name"),
@Result(property = "lastName", column = "last_name")
})
@Select("select * from users where id = #{id}")
User getUserById(Integer id);
@Results(id = "companyResults")
@ConstructorArgs({
@Arg(column = "cid", javaType = Integer.class, id = true),
@Arg(column = "name", javaType = String.class)
})
@Select("select * from company where id = #{id}")
Company getCompanyById(Integer id);
この例は、SelectProviderアノテーションを使用して単一のパラメーターを使用する方法を示しています。
@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(String name);
class UserSqlBuilder {
public static String buildGetUsersByName(final String name) {
return new SQL(){{
SELECT("*");
FROM("users");
if (name != null) {
WHERE("name like #{value} || '%'");
}
ORDER_BY("id");
}}.toString();
}
}
この例は、Sql Providerアノテーションを使用して複数のパラメーターを使用する方法を示しています。
@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(
@Param("name") String name, @Param("orderByColumn") String orderByColumn);
class UserSqlBuilder {
// If not use @Param, you should be define same arguments with mapper method
public static String buildGetUsersByName(
final String name, final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || '%'");
ORDER_BY(orderByColumn);
}}.toString();
}
// If use @Param, you can define only arguments to be used
public static String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || '%'");
ORDER_BY(orderByColumn);
}}.toString();
}
}
この例は、グローバル設定を使用してすべてマッパーメソッドにsqlプロバイダークラスを共有する方法を示しています(3.5.6以降で利用可能)。
Configuration configuration = new Configuration();
configuration.setDefaultSqlProviderType(TemplateFilePathProvider.class); // Specify an sql provider class for sharing on all mapper methods
// ...
// Can omit the type/value attribute on sql provider annotation
// If omit it, the MyBatis apply the class that specified on defaultSqlProviderType.
public interface UserMapper {
@SelectProvider // Same with @SelectProvider(TemplateFilePathProvider.class)
User findUser(int id);
@InsertProvider // Same with @InsertProvider(TemplateFilePathProvider.class)
void createUser(User user);
@UpdateProvider // Same with @UpdateProvider(TemplateFilePathProvider.class)
void updateUser(User user);
@DeleteProvider // Same with @DeleteProvider(TemplateFilePathProvider.class)
void deleteUser(int id);
}
この例は、ProviderMethodResolverのデフォルトの実装の使用を示しています(MyBatis 3.5.1以降で利用可能)。
@SelectProvider(UserSqlProvider.class)
List<User> getUsersByName(String name);
// Implements the ProviderMethodResolver on your provider class
class UserSqlProvider implements ProviderMethodResolver {
// In default implementation, it will resolve a method that method name is matched with mapper method
public static String getUsersByName(final String name) {
return new SQL(){{
SELECT("*");
FROM("users");
if (name != null) {
WHERE("name like #{value} || '%'");
}
ORDER_BY("id");
}}.toString();
}
}
この例は、ステートメントアノテーションのdatabaseId属性の使用を示しています(3.5.5以降で利用可能)。
@Select(value = "SELECT SYS_GUID() FROM dual", databaseId = "oracle") // Use this statement if DatabaseIdProvider provide "oracle"
@Select(value = "SELECT uuid_generate_v4()", databaseId = "postgres") // Use this statement if DatabaseIdProvider provide "postgres"
@Select("SELECT RANDOM_UUID()") // Use this statement if the DatabaseIdProvider not configured or not matches databaseId
String generateId();
MyBatis