MyBatis の設定ファイルには、MyBatis の動作をカスタマイズするための設定やプロパティが含まれています。ファイルの上位レベルの構造は次のようになっています。
'properties' は、別ファイルで設定することができて上書き可能なプロパティです。よく使われる Java Properties ファイルのインスタンス、または properties 要素の子要素として設定することができます。
例:
<properties resource="org/mybatis/example/config.properties"> <property name="username" value="dev_user"/> <property name="password" value="F2Fa3!33TYyg"/> </properties>
読み込んだプロパティは設定ファイル全体を通して使用可能で、変数を動的に設定することができます。
例:
<dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource>
この例では username と password の値が properties 要素で指定した値に、そして driver と url の値が config.properties 内で定義されている値に置き換えられます。この仕組みによって柔軟な設定が実現可能です。
SqlSessionBuilder.build() メソッドに Properties を渡すこともできます。
例:
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, props); // ... or ... SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, props);
あるプロパティが複数の箇所で指定されている場合、MyBatis は次の順番で値を読み込みます。
従って、メソッド引数として渡されたプロパティが最も優先度が高く、次に resource/url 属性、最も優先度が低いのは properties 要素のボディで指定された値ということになります。
'settings' は、実行時に MyBatis の動作を変更することができる、非常に重要な調整点です。 各設定についての説明と設定可能な値およびデフォルト値を以下の表にまとめてあります。
設定 | 説明 | 設定可能な値 | デフォルト値 |
---|---|---|---|
cacheEnabled | このコンフィグレーション内で定義されている全てのキャッシュの有効/無効を切り替えるグローバルな設定です。 | true | false | true |
lazyLoadingEnabled | Lazy Loading(遅延読み込み)の有効/無効を切り替えるグローバルな設定です。 無効にした場合、association として指定されているデータは直ちに読み込まれます。 association 要素で fetchType 属性が指定されている場合はそちらの指定が優先されます。 | true | false | false |
aggressiveLazyLoading | この設定が有効の場合、Lazy loading が指定されたプロパティが要求されると、そのプロパティを内包するオブジェクト全体が読み込まれます。 無効の場合は、各プロパティはそれぞれ要求時に読み込まれます。 | true | false | true |
multipleResultSetsEnabled | 1つのステートメントから複数の ResultSet を返すことを許可するかどうかを指定します(複数 ResultSet に対応したドライバが必要です)。 | true | false | true |
useColumnLabel | 列名の代わりに列ラベルを使用します。 ドライバによって動作が異なります。 ドライバのドキュメントを参照するか、両方のモードを試して動作を確認してください。 | true | false | true |
useGeneratedKeys | JDBC の generated keys サポートを使用するかどうかを指定します。 Derby のように非互換となっていても動作するドライバに対応するため、true を設定した場合は強制的に generated keys を使用します。 | true | false | False |
autoMappingBehavior | MyBatis の自動マッピング機能(列をフィールド/プロパティに自動的にマッピングする機能)の動作を指定します。 NONE を指定すると自動マッピングは無効となります。 PARTIAL が指定された場合、association や collection などを含まない単純な resultMap のみが自動マッピングの対象となります。 FULL が指定された場合、ネストされた結果などの複雑なものも含めて全てが自動マッピングの対象となります。 | NONE, PARTIAL, FULL | PARTIAL |
defaultExecutorType | デフォルトの executor を指定します。 SIMPLE executor は特別なことは何もしません。 REUSE executor は PreparedStatement を再利用します。 BATCH executor はステートメントを再利用してバッチ更新を実行します。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | ドライバがデータベースからの応答を待ち続ける秒数(タイムアウト)を設定します。 | 正の整数(単位:秒) | なし (null) |
safeRowBoundsEnabled | ネストされたステートメントに対して RowBounds の使用を許可するかどうかを設定します。 | true | false | False |
mapUnderscoreToCamelCase | データベースにある A_COLUMN のようなアンダースコアを含む列を Camel Case の Java プロパティ aColumn に自動的にマッピングする機能の有効/無効を切り替えます。 | true | false | False |
localCacheScope | MyBatis は循環参照の解決やネストされたクエリのスピード向上のためにローカルキャッシュを使用します。 デフォルト(SESSION)では同一セッション内の全てのクエリ結果がキャッシュされます。localCacheScope に STATEMENT を設定した場合、ローカルキャッシュはステートメントごとに適用されます。言い換えると、同一 SqlSession に対する複数の呼び出しでデータが共有されることはありません。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 引数の JDBC タイプが未指定の場合、null 値に対して割り当てられる JDBC タイプを設定します。 ドライバによっては列に対する JDBC タイプの指定が必須な場合もありますが、NULL, VARCHAR, OTHER などの汎用の型を指定すれば動作するものもあります。 | JdbcType 列挙型。一般的には NULL, VARCHAR, OTHER のいずれかです。 | OTHER |
lazyLoadTriggerMethods | Lazy loading のトリガとなる Object のメソッドを指定します。 | カンマ区切りのメソッド名のリスト | equals,clone,hashCode,toString |
defaultScriptingLanguage | ダイナミック SQL を記述する際のデフォルトの言語を指定します。 | タイプエイリアスまたは完全修飾クラス名 | org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
callSettersOnNulls | 取得した値が null の場合にセッターあるいは Map の put メソッドを呼び出すかどうかを指定します。 この設定は Map.keySet() や null 値による初期化を利用している場合に有用です。プリミティブ型(int, boolean, 等)に null がセットされることはありません。 | true | false | false |
logPrefix | MyBatis が出力するログに付加される接頭辞を指定します。 | 任意の文字列 | 未指定 |
logImpl | MyBatis のログ出力に使用するロギング実装を指定します。未指定の場合は自動的検出されます。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未指定 |
proxyFactory | Lazy Loading(遅延読み込み)に対応したオブジェクトを生成する際に使用するプロクシツールを指定します。 | CGLIB | JAVASSIST | CGLIB |
各種設定を含む settings の例:
<settings> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> </settings>
タイプエイリアスとは、Java タイプに対する短縮名です。
XML の中でクラスを指定する際、完全修飾名の記述を最小限で済ませることができます。
例えば、
<typeAliases> <typeAlias alias="Author" type="domain.blog.Author"/> <typeAlias alias="Blog" type="domain.blog.Blog"/> <typeAlias alias="Comment" type="domain.blog.Comment"/> <typeAlias alias="Post" type="domain.blog.Post"/> <typeAlias alias="Section" type="domain.blog.Section"/> <typeAlias alias="Tag" type="domain.blog.Tag"/> </typeAliases>
上記のようにタイプエイリアスを定義しておくと、 domain.blog.Blog と書く代わりに Blog と書くことができます。
全てのクラスを列挙する代わりにパッケージを指定することもできます。
<typeAliases> <package name="domain.blog"/> </typeAliases>
この場合、
domain.blog
というパッケージ内のクラスに対してタイプエイリアスが登録されます。
例えば
domain.blog.Author
というクラスに対しては
author
というタイプエイリアスが登録されます。
@Alias
アノテーションを使うと、登録されるエイリアス名を指定することもできます。
次のようになります。
@Alias("author") public class Author { ... }
汎用の Java タイプには、予めタイプエイリアスが用意されています。
これらは全て Case Insensitive (大文字小文字を区別しない)です。
プリミティブ型の場合は特殊な表記が必要となるので注意してください。
エイリアス | Java タイプ |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
MyBatis が PreparedStatement のパラメーターをセットするとき、あるいは ResultSet から値を取得するときには、必ずその Java タイプに対応する TypeHandler が使用されます。
次の表はデフォルトの TypeHandler の一覧です。
タイプハンドラー | Java タイプ | JDBC タイプ |
---|---|---|
BooleanTypeHandler | Boolean, boolean | BOOLEAN 互換の型 |
ByteTypeHandler | Byte, byte | NUMERIC または BYTE 互換の型 |
ShortTypeHandler | Short, short | NUMERIC または SHORT INTEGER 互換の型 |
IntegerTypeHandler | Integer, int | NUMERIC または INTEGER 互換の型 |
LongTypeHandler | Long, long | NUMERIC または LONG INTEGER 互換の型 |
FloatTypeHandler | Float, float | NUMERIC または FLOAT 互換の型 |
DoubleTypeHandler | Double, double | NUMERIC または DOUBLE 互換の型 |
BigDecimalTypeHandler | BigDecimal | NUMERIC または DECIMAL 互換の型 |
StringTypeHandler | String | CHAR, VARCHAR |
ClobTypeHandler | String | CLOB, LONGVARCHAR |
NStringTypeHandler | String | NVARCHAR, NCHAR |
NClobTypeHandler | String | NCLOB |
ByteArrayTypeHandler | byte[] | byte ストリーム互換の型 |
BlobTypeHandler | byte[] | BLOB, LONGVARBINARY |
DateTypeHandler | Date (java.util) | TIMESTAMP |
DateOnlyTypeHandler | Date (java.util) | DATE |
TimeOnlyTypeHandler | Date (java.util) | TIME |
SqlTimestampTypeHandler | Timestamp (java.sql) | TIMESTAMP |
SqlDateTypeHandler | Date (java.sql) | DATE |
SqlTimeTypeHandler | Time (java.sql) | TIME |
ObjectTypeHandler | Any | OTHER または指定がない場合 |
EnumTypeHandler | Enumeration Type | VARCHAR インデックスではなくコードが保存されるので、String 互換の型 |
EnumOrdinalTypeHandler | Enumeration Type | コードではなく位置(ordinal)が保存されるので、NUMERIC または DOUBLE 互換の型 |
標準のタイプハンドラーをオーバーライドしたり、自ら作成したタイプハンドラーを使って未対応あるいは非標準の型を扱うことも可能です。自作する場合は、BaseTypeHandler クラスのサブクラスを作成します。必要に応じて対応する JDBC タイプを指定してください。
例:
// ExampleTypeHandler.java @MappedJdbcTypes(JdbcType.VARCHAR) public class StringTypeHandler extends BaseTypeHandler<String> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return rs.getString(columnName); } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return rs.getString(columnIndex); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getString(columnIndex); } }
<!-- mybatis-config.xml --> <typeHandlers> <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/> </typeHandlers>
上記のようにして登録された TypeHandler は、String 型のプロパティと VARCHAR 型の引数または結果のマッピング時に使用されるデフォルトのタイプハンドラーよりも優先的に使用されます。 MyBatis はデータベースメタデータを参照してタイプを判断している訳ではないので、正しいタイプハンドラーが使用されるよう、パラメーター設定時にフィールドが VARCHAR 型であることを明示する必要があります。MyBatis は実際にステートメントが実行されるまで、データ型のチェックなどは行いません。
MyBatis は、このタイプハンドラーの総称型(Genric Type)から適用対象の Java タイプを自動判定しますが、この動作をオーバーライドする方法が2つあります。
typeHandler 要素に jdbcType 属性を追加することで適用対象の JDBC タイプを指定することもできます(例:jdbcType=VARCHAR)。jdbcType 属性が指定されている場合、@MappedJdbcTypes の指定は無視されます。
適用対象の JDBC タイプを指定する方法は二つあります。
また、MyBatis にタイプハンドラーを自動検出させることもできます。
<!-- mybatis-config.xml --> <typeHandlers> <package name="org.mybatis.example"/> </typeHandlers>
自動検出機能を使う場合、適用対象の JDBC タイプの指定はアノテーションで行う必要があります。
@MappedTypes(BigInteger.class) public class BigIntegerHandler implements TypeHandler<BigInteger> { ... }
複数のクラスを扱う汎用の TypeHandler を作成することもできます。 引数に Class を受け取るコンストラクタを定義しておくと、MyBatis が TypeHandler のインスタンスを作成する際に実際のクラスが渡されます。
//GenericTypeHandler.java public class GenericTypeHandler<E extends MyObject> extends BaseTypeHandler<E> { private Class<E> type; public GenericTypeHandler(Class<E> type) { if (type == null) throw new IllegalArgumentException("Type argument cannot be null"); this.type = type; } ...
この後の節では汎用の TypeHandler である EnumTypeHandler と EnumOrdinalTypeHandler について解説します。
Enum (列挙型)をマップする場合、 EnumTypeHandler または EnumOrdinalTypeHandler のどちらかを使うことになります。
例えば数値の丸めモード(java.math.RoundingMode)を格納する場合、デフォルトでは EnumTypeHandler が使われ、各 Enum は名前の文字列(DOWN, HALF_UP, etc.)に変換されます。
他の TypeHandler が特定のクラスを対象としているのに対し、EnumTypeHandler は Enum を継承した任意のクラスを対象とする特別な TypeHandler です。では名前以外の値を格納したい場合、例えばデータベース管理者が数値で格納して欲しいと言ってきた場合はどうすれば良いのでしょうか。 簡単です:設定ファイルの typeHandlers に EnumOrdinalTypeHandler を追加すれば RoundingMode は ordinal の数値に変換されてマップされます。
<!-- mybatis-config.xml --> <typeHandlers> <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="java.math.RoundingMode"/> </typeHandlers>
では、同じ Enum を、あるテーブルには文字列として格納し、別のテーブルには数値として格納したいといった場合はどうでしょう。
上の設定により自動マッピングでは EnumOrdinalTypeHandler が使われますので、 EnumTypeHandler を使いたい箇所ではこれを明示的に指定する必要があります。
(Mapper ファイルについては次の章で解説していますので、このドキュメントを初めて読む方はこの部分を後回しにした方が良いかも知れません)
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.apache.ibatis.submitted.rounding.Mapper"> <resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="funkyNumber" property="funkyNumber"/> <result column="roundingMode" property="roundingMode"/> </resultMap> <select id="getUser" resultMap="usermap"> select * from users </select> <insert id="insert"> insert into users (id, name, funkyNumber, roundingMode) values ( #{id}, #{name}, #{funkyNumber}, #{roundingMode} ) </insert> <resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap2"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="funkyNumber" property="funkyNumber"/> <result column="roundingMode" property="roundingMode" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/> </resultMap> <select id="getUser2" resultMap="usermap2"> select * from users2 </select> <insert id="insert2"> insert into users2 (id, name, funkyNumber, roundingMode) values ( #{id}, #{name}, #{funkyNumber}, #{roundingMode, typeHandler=org.apache.ibatis.type.EnumTypeHandler} ) </insert> </mapper>
typeHandler を指定するため、select 要素では resultType ではなく resultMap を使う必要があります。
MyBatis が新しい結果オブジェクトのインスタンスを作るときは ObjectFactory が使われます。
デフォルトの ObjectFactory は、対象クラスのデフォルトコンストラクタまたは引数付きのコンストラクタを使ってインスタンスを作成するだけです。
ObjectFactory を自作することで、デフォルトの ObjectFactory の動作をオーバーライドすることもできます。
例:
// ExampleObjectFactory.java public class ExampleObjectFactory extends DefaultObjectFactory { public Object create(Class type) { return super.create(type); } public Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs) { return super.create(type, constructorArgTypes, constructorArgs); } public void setProperties(Properties properties) { super.setProperties(properties); } public <T> boolean isCollection(Class<T> type) { return Collection.class.isAssignableFrom(type); }}
<!-- mybatis-config.xml --> <objectFactory type="org.mybatis.example.ExampleObjectFactory"> <property name="someProperty" value="100"/> </objectFactory>
ObjectFactory のインターフェイスは非常にシンプルです。
2つある create メソッドのうち1つはデフォルトコンストラクタを扱うもので、もうひとつは引数を取るコンストラクタを扱います。
もう1つのメソッド setProperties は ObjectFactory を設定するために使うことができます。
設定ファイルの objectFactory 要素のボディで定義されているプロパティは、ObjectFactory が初期化された後に setProperties メソッドの引数として渡されます。
MyBatis が Mapped Statement を実行する際、いくつかのタイミングで処理をインターセプトすることができます。 デフォルトでは、プラグインを使って下記のメソッド呼び出しをインターセプトすることができるようになっています。
これらのクラスおよびメソッドに関する詳細は、各メソッドのシグネチャや MyBatis のリリースに含まれているソースコードを参照してください。 単にメソッドの呼び出しを監視する以上のことをしたいのなら、その動作について十分に理解しておく必要があります。 メソッドのデフォルトの動作を変更したりオーバーライドするということは、MyBatis のコア部分の動作に影響を与える可能性があるということを忘れないでください。これらのクラスやメソッドは非常に低レベルのものなので、プラグインを使うときは注意が必要です。
プラグインはとても強力ですが、使うのは比較的簡単です。 Interceptor インターフェイスを実装したら、インターセプト対象のメソッドシグネチャを指定するだけです。
// ExamplePlugin.java @Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class ExamplePlugin implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { return invocation.proceed(); } public Object plugin(Object target) { return Plugin.wrap(target, this); } public void setProperties(Properties properties) { } }
<!-- mybatis-config.xml --> <plugins> <plugin interceptor="org.mybatis.example.ExamplePlugin"> <property name="someProperty" value="100"/> </plugin> </plugins>
上記のプラグインは Executor インスタンスの update メソッド呼び出しをインターセプトします。Executor は、低レベルで mapped statement を実行する内部オブジェクトです。
NOTE Configuration クラスをオーバーライドする
プラグインによって MyBatis の動作を変更する以外に、Configuration クラスをオーバーライドすることもできます。 方法は単純で、Configuration のサブクラスを作って任意のメソッドをオーバーライドし、sqlSessionFactoryBuilder.build(myConfig) のようにして呼び出すだけです。 繰り返しになりますが、これは MyBatis の動作に重大な影響を与える可能性があるので注意してください。
MyBatis では複数の環境設定を定義することができます。これは、同じ SQL Map を複数のデータベースに対して使いたいとき役に立ちます。例えば、開発環境、デモ環境、本番環境で、それぞれ異なる設定場合や、本番環境の同じスキーマを持つ複数のデータベースがあり、両方に対して同じ SQL Map を使いたい場合など、様々な用途が考えられます。
ひとつだけ注意しなくてはならないことは、複数の環境設定を扱うことはできますが、一つの SqlSessionFactory インスタンスに対しては一つの環境しか割り当てることができない、ということです。
もし二つのデータベースに接続したいのなら、それぞれの接続に対して一つずつ、合計二つの SqlSessionFactory を作る必要があります。データベースが三つなら SqlSessionFactory も三つ必要、といった具合です。実に簡単なルールです。
SqlSessionFactoryBuilder に envrionment を渡すことで、どの環境に対する SqlSessionFactory をビルドするか指定することができます。 envrionment を引数に取るシグネチャは下記の2つです。
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment); SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment,properties);
environment が省略された場合、デフォルトの environment がロードされます。
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader); SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader,properties);
environment の具体的な設定は、environments 要素で行います。
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"> <property name="..." value="..."/> </transactionManager> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments>
ここでのポイントは以下の通りです。
デフォルト環境と環境 ID は自明です。 各環境の ID は自由に命名して構いませんが、デフォルトとして指定した環境 ID を必ず定義しておいてください。
transactionManager
MyBatis では二種類のトランザクションマネージャー(JDBC と MANAGED)が用意されています。
<transactionManager type="MANAGED"> <property name="closeConnection" value="false"/> </transactionManager>
NOTE MyBatis を Spring と組み合わせて使う場合、トランザクションマネージャーの設定は不要です(設定しても Spring 側で用意したトランザクションマネージャーによって上書きされます)。
トランザクションマネージャーに必須のプロパティはありませんが、これらはともにタイプエイリアスです。つまり、TransactionFactory インターフェイスの実装クラスの完全修飾クラス名を指定すれば、MyBatis が用意した二種類のトランザクションマネージャーの代わりに独自に実装したトランザクションマネージャーを利用することが可能です。
public interface TransactionFactory { void setProperties(Properties props); Transaction newTransaction(Connection conn); Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit); }
XML ファイルの中で properties 要素で指定されたプロパティは、インスタンスが作成された後、setProperties() メソッドに渡されます。 トランザクションマネージャーの他に Transaction の実装クラスが必要となります。 こちらも非常にシンプルなインターフェイスです。
public interface Transaction { Connection getConnection() throws SQLException; void commit() throws SQLException; void rollback() throws SQLException; void close() throws SQLException; }
これらのインターフェイスを使えば、MyBatis のトランザクション管理方法を完全にカスタマイズすることが可能です。
dataSource
dataSource 要素では、JDBC 標準の DataSource インターフェイスを実装している JDBC Connection オブジェクトの取得元を指定します。
MyBatis では、3つのデータソースタイプが用意されています (type="????")
UNPOOLED – このデータソースは、リクエストごとに接続のオープン/クローズを実行します。 少々遅いですが、即時の接続を必要としないシンプルなアプリケーションの場合は良い選択肢です。 パフォーマンスに関しては、お使いのデータベースによっても変わってきます。 接続プールの重要性が低いデータベースの場合はこの設定が最適となります。 UNPOOLED データソースは5つのプロパティで設定できます。
オプションとして、データベースドライバーのプロパティを設定することもできます。
この場合、プロパティ名に接頭辞 "driver." を付加します。
例:
上記の例では、DriverManager.getConnection(url, driverProperties) メソッド経由でドライバーに渡されるプロパティとして "encoding=UTF8" が追加されます。
POOLED – このデータソースは新規接続開始時に必要となる初期接続と認証の時間を省くため JDBC 接続をプールします。 Web アプリケーションでは応答速度向上のために良く使われる設定です。
POOLED データソースには、UNPOOLED の設定で見た5つの他に様々なプロパティを指定することができます。
JNDI – JNDI 経由でデータソースを取得する EJB やアプリケーションサーバーと併用することを想定したデータソースです。 設定に必要なプロパテイは2つだけです。
他の DataSource 設定と同様に、"env." という接頭辞を付けることで InitialContext にそのまま渡されるプロパティを設定することができます。
例:
上記のように指定すると、"encoding=UTF8" というプロパティが InitialContext のインスタンス生成時にコンストラクタに渡されます。
上記以外の DataSource を利用する場合は org.apache.ibatis.datasource.DataSourceFactory インターフェイスを実装したアダプタを作成します。
public interface DataSourceFactory { void setProperties(Properties props); DataSource getDataSource(); }
アダプタを作成する際は org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory を継承することもできます。 下記は C3P0 のデータソースを利用する場合の実装例です。
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0DataSourceFactory extends UnpooledDataSourceFactory { public C3P0DataSourceFactory() { this.dataSource = new ComboPooledDataSource(); } }
作成したアダプタを設定する場合は property 要素を使って必要なプロパティを指定します。 上述のアダプタを使って PostgreSQL に接続する場合の設定例を挙げておきます。
<dataSource type="org.myproject.C3P0DataSourceFactory"> <property name="driver" value="org.postgresql.Driver"/> <property name="url" value="jdbc:postgresql:mydb"/> <property name="username" value="postgres"/> <property name="password" value="root"/> </dataSource>
MyBatis では、利用するデータベースによって異なるステートメントを実行することができます。 複数データベースサポート機能は、各ステートメントの databaseId 属性によって実現されます。 MyBatis は定義されているステートメントの中で databaseId 属性が指定されていないステートメントおよび現在の設定と一致する databaseId 属性を持ったステートメントをロードします。 同じステートメントで、databaseId 属性が指定されているものと指定されていないものが両方定義されていた場合、指定がないステートメントは無視されます。 複数データベースサポート機能を有効にするには、mybatis-config.xml に databaseIdProvider を追加します。
<databaseIdProvider type="DB_VENDOR" />
databaseIdProvider に DB_VENDOR が指定された場合は VendorDatabaseIdProvider がプロバイダとして使われます。 この実装は、DatabaseMetaData#getDatabaseProductName() から返される製品名の文字列を「現在の databaseId」として返します。この文字列は長すぎる上にバージョンによって異なる値を返すことがあるので、次のようにプロパティを指定して短い文字列に変換できるようになっています。
<databaseIdProvider type="DB_VENDOR"> <property name="SQL Server" value="sqlserver"/> <property name="DB2" value="db2"/> <property name="Oracle" value="oracle" /> </databaseIdProvider>
プロパティが指定された場合、VendorDatabaseIdProvider は DatabaseMetaData#getDatabaseProductName() から返された製品名に name 属性で指定された文字列が含まれているかどうかチェックし、含まれている場合は value 属性で指定されている文字列を「現在の databaseId」として返します。指定された name が一つも含まれていない場合は "null" を返します。 上記の例で、getDatabaseProductName() が "Oracle (DataDirect)" という文字列を返す場合、現在の databaseId は "oracle" となります。
DatabaseIdProvider を自作することも可能です。org.apache.ibatis.mapping.DatabaseIdProvider インターフェイスを実装したクラスを作成し、mybatis-config.xml で databaseIdProvider の type 属性の値として、作成したクラスの完全修飾クラス名を指定します。
public interface DatabaseIdProvider { void setProperties(Properties p); String getDatabaseId(DataSource dataSource) throws SQLException; }
上記のように configuration 要素を設定することで MyBatis の動作設定は完了したので、Mapped SQL Statement の定義を行う準備ができました。
まず、定義ファイルの場所を指定する必要があります。
Java にはこのような場合に利用できる自動検出の仕組みがないので、単純にマッピングファイルの場所を指定します。
相対パスでクラスパスリソースへの参照を指定することもできますし、文字列リテラルでフルパスか完全修飾 URL 形式(file:/// でも可)を指定することも可能です。
例:
<!-- Using classpath relative resources --> <mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers>
<!-- Using url fully qualified paths --> <mappers> <mapper url="file:///var/mappers/AuthorMapper.xml"/> <mapper url="file:///var/mappers/BlogMapper.xml"/> <mapper url="file:///var/mappers/PostMapper.xml"/> </mappers>
<!-- Using mapper interface classes --> <mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/> </mappers>
<!-- Register all interfaces in a package as mappers --> <mappers> <package name="org.mybatis.builder"/> </mappers>
これらの設定は、単に MyBatis にマッピングファイルの場所を伝えているだけで、その先は各 SQL マップファイルの定義次第ということになります(次の章で説明します)。