コンフィグレーション
ここでは,Kuina-Daoで複数の永続ユニットを使用する場合や,Kuina-Daoをカスタマイズする方法について説明します.
異なった構成を持つ複数の永続ユニットの使用
異なった構成をもつ複数の永続ユニットを使用するには,以下の命名規約とパッケージ構成に従うことを推奨します. 推奨する命名規約とパッケージ構成に従うと,エンティティとマッピングファイルは対応する永続ユニットに自動的に登録されます.
- 推奨する命名規約
-
永続ユニット名は"
persistenceUnit", もしくは"任意のプレフィックスPersistenceUnit"とする.マッピングファイル名は"任意のプレフィックス
Orm.xml"とする. - 推奨するパッケージ構成
-
永続ユニット"
persistenceUnit"に属するエンティティは ルートパッケージ.entityに配置する.永続ユニット"任意のプレフィックス
PersistenceUnit"に属するエンティティは ルートパッケージ.entity.任意のプレフィックスに配置する.永続ユニット"
persistenceUnit"に属するマッピングファイルは ルートパッケージ.entity,もしくはルートパッケージ.daoに配置する.永続ユニット"任意のプレフィックス
PersistenceUnit"に属するマッピングファイルは ルートパッケージ.entity.任意のプレフィックス, もしくはルートパッケージ.dao.任意のプレフィックスに配置する.
例
"persistenceUnit"という名称の永続ユニットと
"hogePerisitenceUnit"という名称の永続ユニットがそれぞれ存在する場合,
推奨されるパッケージ構成は次のようになります.
この例でのルートパッケージはkuina.dao.examleとします.
Emp.class,Dept.class,Sales.classはエンティティとします.
また,登場するxmlファイルはすべてJPAのマッピングファイルとします.
kuina.dao.examle.dao.EmpDao.classkuina.dao.examle.dao.EmpOrm.xmlkuina.dao.examle.dao.DeptDao.classkuina.dao.examle.dao.DeptOrm.xmlkuina.dao.examle.dao.hoge.SalesDao.classkuina.dao.examle.dao.hoge.SalesOrm.xmlkuina.dao.examle.entity.Emp.classkuina.dao.examle.entity.Dept.classkuina.dao.examle.entity.hoge.Sales.class
EmpOrm.xml,DeptOrm.xml,Emp.class,
Dept.classが永続ユニットpersistenceUnitに登録されます.
残りの,SalesOrm.xml,Sales.classが
永続ユニットhogePerisitenceUnitに登録されます.
同一の構成を持つ複数の永続ユニットの使用
同一の構成を持つ複数の永続ユニットを作成する場合,エンティティやDAOを共有したままコンテキストに応じて データベースの接続先を切り替えることができます.
推奨する命名規約とパッケージ構成に従えば,エンティティとマッピングファイルは対応する永続ユニットに 自動的に登録されます.
- 推奨する命名規約
-
永続ユニット名は"
persistenceUnit"以外とする.マッピングファイル名は"任意のプレフィックス
Orm.xml"とする. - 推奨するパッケージ構成
-
エンティティはルートパッケージ
.entityに配置する.マッピングファイルはルートパッケージ
.entity, もしくはルートパッケージ.daoに配置する.
推奨する設定ファイル定義例
まずデータベースの接続先ごとにデータソースの設定を行います. この例ではH2とDerbyを使います. データベースごとの設定ファイルとそれを束ねるひとつの設定ファイルを用意します.
h2-jdbc.diconderby-jdbc.diconjdbc.dion
それぞれのファイルの定義は以下のようになります. 設定上の注意点は太字にしています. 一部定義を省略しています.
h2-jdbc.dicon
namespaceには"jdbc"を指定します.
DataSourceを表すコンポーネントの名前は
"任意のプレフィックスDataSource"にする必要があります.
ここでは"h2DataSource"とします.
<components namespace="jdbc
">
<include path="jta.dicon"/>
<include path="jdbc-extension.dicon"/>
...(略)...
<component name="h2DataSource
"
class="org.seasar.extension.dbcp.impl.DataSourceImpl"
/>
</components>
derby-jdbc.dicon
namespaceには"jdbc"を指定します.
DataSourceを表すコンポーネントの名前は
"任意のプレフィックスDataSource"にする必要があります.
ここでは"derbyDataSource"とします.
<components namespace="jdbc
">
<include path="jta.dicon"/>
<include path="jdbc-extension.dicon"/>
...(略)...
<component name="derbyDataSource
"
class="org.seasar.extension.dbcp.impl.DataSourceImpl"
/>
</components>
jdbc.dicon
データベースごとに用意した設定ファイルをインクルードします.
namespaceには"jdbc"を指定します.
SelectableDataSourceProxyを定義しコンポーネントの名前は
"dataSource"とします.
<components namespace="jdbc
">
<include path="h2-jdbc.dicon"/>
<include path="derby-jdbc.dicon"/>
<component name="dataSource
"
class="org.seasar.extension.datasource.impl.SelectableDataSourceProxy
"/>
</components>
次に永続ユニットごとの設定を用意します.
persistence.xmljpa.diconh2-jpa.diconderby-jpa.dicon
それぞれの設定ファイルは以下のようになります (この例はJPA実装にHibernateを使う場合の設定です).
persistence.xml
永続ユニットを複数定義します. 接続先のデータベースは自動的に切り替えるのでデータソースは同じ名前でかまいません.
<persistence>
<persistence-unit name="h2PersistenceUnit
" transaction-type="JTA">
<jta-data-source>jdbc/dataSource</jta-data-source>
...(略)...
</persistence-unit>
<persistence-unit name="derbyPersistenceUnit
" transaction-type="JTA">
<jta-data-source>jdbc/dataSource</jta-data-source>
...(略)...
</persistence-unit>
</persistence>
h2-jpa.dicon
永続ユニットh2PersistenceUnit用の設定ファイルです.
ContainerPersistenceUnitProviderのabstractUnitNameプロパティには
Seasar2でのデフォルトの永続ユニット名であるpersistenceUnitを,
unitNameプロパティには実際の永続ユニットであるh2PersistenceUnitを設定します.
unitNameプロパティの永続ユニットに自動で検出されたエンティティとマッピングファイルが登録されます.
EntityManagerを表すコンポーネントの名前は
"対応するデータソースのプレフィックスEntityManager"にする必要があります.
<components>
<include path="s2hibernate-jpa.dicon"/>
<component name="h2PersistenceUnitProvider
"
class="org.seasar.framework.jpa.impl.ContainerPersistenceUnitProvider">
<property name="abstractUnitName">"persistenceUnit
"</property>
<property name="unitName">"h2PersistenceUnit
"</property>
</component>
<component name="h2EntityManagerFactory
" class="javax.persistence.EntityManagerFactory">
h2PersistenceUnitProvider
.entityManagerFactory
</component>
<component name="h2EntityManager
"
class="org.seasar.framework.jpa.impl.TxScopedEntityManagerProxy"/>
</components>
derby-jpa.dicon
永続ユニットderbyPersistenceUnit用の設定ファイルです.
ContainerPersistenceUnitProviderのabstractUnitNameプロパティには
Seasar2でのデフォルトの永続ユニット名であるpersistenceUnitを,
unitNameプロパティには実際の永続ユニットであるderbyPersistenceUnitを設定します.
unitNameプロパティの永続ユニットに自動で検出されたエンティティとマッピングファイルが登録されます.
EntityManagerを表すコンポーネントの名前は
"対応するデータソースのプレフィックスEntityManager"にする必要があります.
<components>
<include path="s2hibernate-jpa.dicon"/>
<component name="derbyPersistenceUnitProvider
"
class="org.seasar.framework.jpa.impl.ContainerPersistenceUnitProvider">
<property name="abstractUnitName">"persistenceUnit
"</property>
<property name="unitName">"derbyPersistenceUnit
"</property>
</component>
<component name="derbyEntityManagerFactory
" class="javax.persistence.EntityManagerFactory">
derbyPersistenceUnitProvider
.entityManagerFactory
</component>
<component name="derbyEntityManager
"
class="org.seasar.framework.jpa.impl.TxScopedEntityManagerProxy"/>
</components>
jpa.dicon
永続ユニットごとに用意した設定ファイルをインクルードします.
SelectableEntityManagerProxyを定義しコンポーネントの名前は
"entityManager"とします.
<components>
<include path="h2-jpa.dicon"/>
<include path="derby-jpa.dicon"/>
<component name="entityManager
"
class="org.seasar.framework.jpa.impl.SelectableEntityManagerProxy
"/>
</components>
実行方法
コンテキストを指定して接続先のデータベースを切り替えるには
org.seasar.extension.datasource.DataSourceFactoryコンポーネントの
setSelectableDataSourceName(String)メソッドに,
データソースのプレフィックスを引数として渡して実行します.
例えば,上記の定義に従った場合,Derbyに接続するにはsetSelectableDataSourceName("derby")を呼び出し,
H2に接続するにはsetSelectableDataSourceName("h2")を呼び出します.
値を設定する場所としては,Servelet FilterやAOPのロジックが適しています.
Kuina-Daoのカスタマイズ
Kuina-Daoが提供するインターフェースを実装したクラスを作成し設定ファイルを適切に定義することでKuina-Daoをカスタマイズできます. たとえば,新しい機能を追加する場合次の作業が必要です.
- org.seasar.kuina.dao.internal.Commandインターフェースの実装クラスを作成する.
- org.seasar.kuina.dao.internal.CommandBuilderインターフェースの実装クラスを作成する.
- kuina-dao-builder.diconをコピーした設定ファイルにCommandBuilderの実装クラスを登録する.
- s2container.diconに上記で新しく作成した設定ファイルを使用することを指定する.
設定例
org.seasar.kuina.dao.internal.Commandの実装クラスの作成
Commandインタフェースを実装するクラスを作成しDAOメソッドに適応したい処理を記述します.
このクラスではEntityManagerに対し問い合わせや更新などを実行できます.
executeメソッドの戻り値はDAOメソッドの戻り値となります.
DAOメソッドが戻り値を持たない場合,executeメソッドではnullを返してください.
public class HogeCommand implements Command
{
public Object execute(EntityManager em, Object[] arguments) {
...
return null;
}
}
org.seasar.kuina.dao.internal.CommandBuilderの実装クラスの作成
CommandBuilderインターフェースを実装するクラスを作成しCommandを生成するための処理を記述します.
buildメソッドはDAOメソッドのシグネチャ等の情報から対応するCommandを生成します.
生成しない場合はnullを返してください.
public class HogeCommandBuilder implements CommandBuilder
{
public Command build(Class<?> daoClass, Method method) {
if (!method.getName().startsWith("hoge")) {
return null;
}
...
return new HogeCommand();
}
}
kuina-dao-builder.diconのコピーの作成
kuina-dao-x.x.x.jarに同梱されているkuina-dao-builder.diconをコピーしてカスタマイズ用の設定ファイルを作成し,
新規に作成したCommandBuilderを登録します.
たとえば,コピーしたファイルをmy-kuina-dao-builder.diconという名前にし
次のように新しいCommandBuilderを定義します.
<components namespace="kuinaDaoBuilder"> <include path="convention.dicon"/> <include path="javaee5.dicon"/> <component class="org.seasar.kuina.dao.internal.metadata.DaoMetadataFactoryImpl"/> <component instance="prototype" class="org.seasar.kuina.dao.internal.metadata.DaoMetadataImpl"/> <component class="org.seasar.kuina.dao.internal.builder.SqlCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.SqlUpdateCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.NamedQueryCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.NamedQueryUpdateCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.FindAllQueryCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.ExampleQueryCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.DtoQueryCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.ParameterQueryCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.ConditionalQueryCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.FindCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.GetReferenceCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.ContainsCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.PersistCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.RemoveCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.MergeCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.RefreshCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.ReadLockCommandBuilder"/> <component class="org.seasar.kuina.dao.internal.builder.WriteLockCommandBuilder"/> <component class="kuina.dao.example.HogeCommandBuilder"/> </components>
s2container.diconの設定
S2Containerの振る舞いを制御する設定ファイルであるs2container.diconで
kuina-dao-builder.diconの替わりにカスタマイズ用の設定ファイルを使用することを指定します.
カスタマイズ用の設定ファイルがmy-kuina-dao-builder.diconという名前である場合,次のように記述します.
<components>
<include condition="#ENV == 'ut'" path="hotdeploy.dicon"/>
<include condition="#ENV != 'ut'" path="cooldeploy.dicon"/>
<component class="org.seasar.framework.container.factory.SimplePathResolver">
<initMethod name="addRealPath">
<arg>"kuina-dao-builder.dicon
"</arg>
<arg>"my-kuina-dao-builder.dicon
"</arg>
</initMethod>
</component>
</components>
