概要
Domaに対する設定は、Configインタフェースの実装クラスで表現します。
Configの実装クラスは@Daoのconfig要素に指定します。
次の事柄を設定で変更できます。
- データソース
- データソースの名前
- データベースの方言
- JDBC関連のログ出力に使用するロギングフレームワークへのアダプタ
- SQLファイルのキャッシュ戦略
- トランザクション属性がREQUIRES_NEWであるトランザクションとの連動方法
- 使用するアプリケーションサーバやフレームワークに依存した仕方でのクラスの取得
- 例外メッセージに含めるSQLのタイプ
- クエリ時に使用するパラメータ(タイムアウト、最大件数、フェッチ件数、バッチサイズ)
- Entityに定義が存在しないカラムが結果セットに含まれていた場合に無視するかどうか
設定クラスの作成
Configインタフェースを直接実装する場合
Configインタフェースの実装クラスは、publicなデフォルトコンストラクタ(引数なしのコンストラクタ)を持たねばいけません。
また、どのメソッドも nullを返してはいけません。
ここでは、代表的な設定項目について説明します。
データソースの設定
javax.sql.DataSourceを、getDataSourceメソッドで返します。
学習等でごく簡易的なデータアクセスを行うだけであれば、
SimpleDataSource
を使用できます。
データソース名の設定
データソース名をあらわすStringを、getDataSourceNameメソッドで返します。
データソース名は、複数のデータソースを利用する環境で重要です。
データソース名はデータソースごとに自動生成される識別子を認識するために使用されます。
複数データソースを利用する場合は、それぞれ異なる名前を返すようにしてください。
RDBMS方言の設定
org.seasar.doma.jdbc.dialect.Dialectを、getDialectメソッドで返します。
DialectはRDBMSの方言をあらわすインタフェースです。
実装クラスには次のものがあります。
| データベース | 方言クラスの名前 | 説明 |
|---|---|---|
| DB2 | org.seasar.doma.jdbc.dialect.Db2Dialect |
|
| H2 Database Engine 1.2.126 | org.seasar.doma.jdbc.dialect.H212126Dialect |
H2 Database Engine 1.2.126で稼動実績あり |
| H2 Database Engine | org.seasar.doma.jdbc.dialect.H2Dialect |
H2 Database Engine 1.3.171以降に対応 |
| HSQLDB | org.seasar.doma.jdbc.dialect.HsqldbDialect |
|
| Microsoft SQL Server 2008 | org.seasar.doma.jdbc.dialect.Mssql2008Dialect |
Microsoft SQL Server 2008に対応 |
| Microsoft SQL Server | org.seasar.doma.jdbc.dialect.MssqlDialect |
Microsoft SQL Server 2012以降に対応 |
| MySQL | org.seasar.doma.jdbc.dialect.MySqlDialect |
|
| Oracle Database | org.seasar.doma.jdbc.dialect.OracleDialect |
|
| PostgreSQL | org.seasar.doma.jdbc.dialect.PostgresDialect |
|
| SQLite | org.seasar.doma.jdbc.dialect.SqliteDialect |
接続先のRDBMSにあわせて、実装クラスを選んでください。
ロガーの設定
org.seasar.doma.jdbc.JdbcLoggerを、getJdbcLoggerメソッドで返します。
JdbcLoggerはデータベースアクセスに関するログを扱うインタフェースです。
実装クラスには次のものがあります。
UtilLoggingJdbcLoggerは、java.util.loggingのロガーを使用してログ出力する実装です。
多くの場合、アプリケーションで使用するcommons-loggingなどのロガーに出力する実装クラスを別途作ったほうがよいでしょう。
SQLファイルのリポジトリの設定
org.seasar.doma.jdbc.SqlFileRepositoryを、getSqlFileRepositoryメソッドで返します。
SqlFileRepositoryはSQLファイルのリポジトリを扱うインタフェースです。
実装クラスには次のものがあります。
GreedyCacheSqlFileRepositoryは、読み込んだSQLファイルの内容をパースし、その結果をメモリが許す限り最大限にキャッシュします。
NoCacheSqlFileRepositoryは、一切キャッシュを行いません。毎回、SQLファイルからSQLを読み取りパースします。
メモリの利用に厳しい制限がある環境や、扱うSQLファイルが膨大にある環境では、適切なキャッシュアルゴリズムをもった実装クラスを作成し使用してください。
REQUIRES_NEWの属性をもつトランザクションを制御するための設定
org.seasar.doma.jdbc.RequiresNewControllerを、getRequiresNewControllerメソッドで返します。
RequiresNewControllerはREQUIRES_NEW の属性をもつトランザクションを制御するインタフェースです。
実装クラスには次のものがあります。
NullRequiresNewControllerは、実質的になにも行いません。
REQUIRES_NEWの属性をもつトランザクションの最適な制御方法は、環境ごとに異なるため、適切な実装クラスを作成し使用してください。
ただし、このインタフェースは、@TableGeneratorで、識別子を自動生成する際にしか使われません。
@TableGeneratorを利用しない場合は、NullRequiresNewControllerを使用してもかまいません。
また、@TableGeneratorを利用する場合であっても、識別子を採番するための更新ロックが問題にならない程度のトランザクション数であれば、NullRequiresNewControllerを使用してもかまいません。
クラスの扱いに関する設定
org.seasar.doma.jdbc.ClassHelperを、getClassHelperメソッドで返します。
ClassHelperはクラスの扱いに関してアプリケーションサーバやフレームワークの差異を抽象化するインタフェースです。
実装クラスには次のものがあります。
DefaultClassHelperは、java.lang.Class.forName(name) を用いてクラスをロードします。
例外メッセージに含めるSQLのタイプの設定
例外メッセージに含めるSQLのタイプをあらわす、org.seasar.doma.jdbc.ExceptionSqlLogTypeをgetExceptionSqlLogTypeメソッドで返します。
この値は、UniqueConstraintExceptionなどの例外にどのような形式のSQLを含めるかを決定します。
クエリタイムアウト(秒)の設定
クエリタイムアウト(秒)をあらわす、intをgetQueryTimeoutメソッドで返します。
この値は、Daoインタフェースの@Delegate以外の問い合わせで使用されます。
クエリタイムアウト(秒)はjava.sql.Statement.setQueryTimeout(int)に渡されます。
SELECT時のフェッチサイズの設定
SELECT時のフェッチサイズをあらわす、intをgetFetchSizeメソッドで返します。
この値は、Daoインタフェースの@Selectが注釈されたメソッドの実行で使用されます。
フェッチサイズはjava.sql.Statement.setFetchSize(int)に渡されます。
SELECT時の最大行数の設定
SELECT時の最大行数をあらわす、intをgetMaxRowsメソッドで返します。
この値は、Daoインタフェースの@Selectが注釈されたメソッドの実行で使用されます。
最大行数はjava.sql.Statement.setMaxRows(int)に渡されます。
バッチ更新のバッチサイズの設定
バッチサイズをあらわす、intをgetBatchSizeメソッドで返します。
この値は、Daoインタフェースの@BatchUpdateなどが注釈されたバッチ系のメソッドの実行に使用されます。
Entityに定義が存在しないカラムが結果セットに含まれていた場合に無視するかどうか
無視するかどうかをあらわすbooleanをignoreUnknownColumnメソッドで返します。
trueを返すと、org.seasar.doma.jdbc.MappedPropertyNotFoundExceptionのスローを抑制できます。
この値は、Daoインタフェースの@Selectが注釈されたメソッドの実行に使用されます。
DomaAbstractConfigを継承する場合
Configインタフェースを直接実装してもかまいませんが、
いくつかのデフォルトの設定をもつ DomaAbstractConfigを継承するのが簡単です。
最初は、このクラスを使い、慣れてきたらConfigインタフェースを直接実装するのがよいでしょう。
public class AppConfig extends DomaAbstractConfig {
...
}
DomaAbstractConfigを利用する場合、必要な設定は次の3つです。
- データソースの設定
- データソース名の設定
- RDBMS方言の設定
上記以外の設定については、デフォルトの実装やデフォルトの値が使用されます。
| 設定項目 | デフォルトの実装クラス/値 |
|---|---|
| ロガーの設定 | org.seasar.doma.jdbc.UtilLoggingJdbcLogger |
| SQLファイルのリポジトリの設定 | org.seasar.doma.jdbc.GreedyCacheSqlFileRepository |
| REQUIRES_NEWの属性をもつトランザクションを制御するための設定 | org.seasar.doma.jdbc.NullRequiresNewController |
| クラスの扱いに関する設定 | org.seasar.doma.jdbc.DefaultClassHelper |
| 例外メッセージに含めるSQLのタイプの設定 | org.seasar.doma.jdbc.ExceptionSqlLogType.FORMATTED_SQL |
| クエリタイムアウト(秒)の設定 | 0 (0以下の値は明示的に設定しないことをあらわします) |
| SELECT時のフェッチサイズの設定 | 0 (0以下の値は明示的に設定しないことをあらわします) |
| SELECT時の最大行数の設定 | 0 (0以下の値は明示的に設定しないことをあらわします) |
| バッチ更新のバッチサイズの設定 | 10 |
| Entityに定義が存在しないカラムが結果セットに含まれていた場合に無視するかどうか | false |
JDBCドライバの設定
通常、クラスパスが通っていれば、JDBC 4.0 ドライバはサービスプロバイダメカニズムにより自動でロードされます。
しかし、たとえばTomcatでは、WEB-INF/libの下のJDBCドライバを自動でロードしません。 自動でロードされない条件下では、Class.forNameを使ってJDBCドライバをロードしてください。
Class.forNameを実行する場所は、設定クラスのstatic初期化子が1つの候補です。 たとえば、H2 DatabaseのJDBCドライバを明示的にロードする場合には次のようにします。
public class AppConfig extends DomaAbstractConfig {
static {
try {
Class.forName("org.h2.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
...
}
設定クラスの利用
設定クラスは@Daoのconfig要素で指定します。
設定クラスをAppConfigという名前で作成した場合、次のようになります。
@Dao(config = AppConfig.class)
public interface EmployeeDao {
...
}
DIコンテナを利用する場合の設定例
DIコンテナを利用する場合、Daoの実装クラスや設定クラスのインスタンスをDIコンテナに管理させるとよいでしょう。
設定クラスのインスタンスのインジェクション
Daoの実装クラスのインスタンスに設定クラスのインスタンスをインジェクションするには、
@Daoのconfig要素に何も指定しないでください。
この場合、Config型のインスタンスを受け取るコンストラクタがDaoの実装クラスに生成されます。
コンストラクタインジェクションをサポートするDIコンテナであれば、設定ファイルなどによりインジェクションが可能です。
@Dao
public interface EmployeeDao {
...
}
上のインタフェースに対する実装クラスのソースコードは、aptにより次のように生成されます。
public class EmployeeDaoImpl extends org.seasar.doma.jdbc.DomaAbstractDao implements example.EmployeeDao {
public EmployeeDaoImpl(org.seasar.doma.jdbc.Config config) {
super(config);
}
...
}
aptにより生成されるソースコードに対するアノテーションの注釈
@AnnotateWithを使用することで、インジェクションのためのアノテーションをDaoの実装クラスのソースコードに注釈できます。
これにより、DIコンテナがサポートしていれば、アノテーションによるインジェクションも可能になります。
たとえば、 Guiceのアノテーションを注釈するには次のように記述します。
@Dao
@AnnotateWith(annotations = {
@Annotation(target = AnnotationTarget.CONSTRUCTOR, type = Inject.class),
@Annotation(target = AnnotationTarget.CONSTRUCTOR_PARAMETER, type = Named.class, elements = "\"sales\"") })
public interface EmployeeDao {
...
}
上のインタフェースに対する実装クラスのソースコードは、aptにより次のように生成されます。 コンストラクタとコンストラクタのパラメータにアノテーションが注釈されていることに注目してください。
public class EmployeeDaoImpl extends org.seasar.doma.jdbc.DomaAbstractDao implements example.EmployeeDao {
@com.google.inject.Inject()
public EmployeeDaoImpl(@com.google.inject.name.Named("sales") org.seasar.doma.jdbc.Config config) {
super(config);
}
...
}
@AnnotateWithを任意のアノテーションに注釈し、そのアノテーションをDaoインタフェースに注釈することも可能です。
たとえば、@InjectConfigというアノテーションに@AnnotateWithを注釈するとします。
@AnnotateWith(annotations = {
@Annotation(target = AnnotationTarget.CONSTRUCTOR, type = Inject.class),
@Annotation(target = AnnotationTarget.CONSTRUCTOR_PARAMETER, type = Named.class, elements = "\"sales\"") })
public @interface InjectConfig {
...
}
@InjectConfigをDaoインタフェースに注釈すれば、@AnnotateWithを直接Daoインタフェースに注釈しているのと同じ効果が得られます。
@Dao
@InjectConfig
public interface EmployeeDao {
...
}
