Seasar DI Container with AOP

dao.diconとは

dao.diconはS2Daoの動作を設定するファイルです。 このファイルはs2-dao-x.x.x.jar内に含まれているため自動で読み込まれます。

dao.diconは次のように記述されています。

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
  "http://www.seasar.org/dtd/components21.dtd">
<components namespace="dao">
    <include path="j2ee.dicon"/>
    <component class="org.seasar.dao.impl.AnnotationReaderFactoryImpl"/>
    <component class="org.seasar.dao.impl.DaoMetaDataFactoryImpl"/>
    <component
        name="interceptor"
        class="org.seasar.dao.pager.PagerS2DaoInterceptorWrapper">
        <arg>
            <component class="org.seasar.dao.interceptors.S2DaoInterceptor"/>
        </arg>
    </component>
    <component class="org.seasar.dao.impl.ValueTypeFactoryImpl"/>
    <component name="stringClobType">
        @org.seasar.dao.types.ValueTypes@CLOB
    </component>
    <component class="org.seasar.dao.impl.BeanMetaDataFactoryImpl"/>
    <component class="org.seasar.dao.impl.DaoNamingConventionImpl"/>
    <component class="org.seasar.dao.impl.NullBeanEnhancer"/>
    <component class="org.seasar.dao.impl.ResultSetHandlerFactorySelector"/>
    <component class="org.seasar.dao.impl.DtoMetaDataFactoryImpl"/>
    <component class="org.seasar.dao.impl.PropertyTypeFactoryBuilderImpl"/>
    <component class="org.seasar.dao.impl.RelationPropertyTypeFactoryBuilderImpl"/>
    <component class="org.seasar.dao.impl.DefaultTableNaming"/>
    <component class="org.seasar.dao.impl.DefaultColumnNaming"/>
    <component class="org.seasar.dao.impl.ProcedureMetaDataFactoryImpl"/>
</components>

設定の変更

dao.diconに記述された設定を変更することでS2Daoの振る舞いをカスタマイズできます。 ただし、dao.diconはjarファイルに含まれるので直接編集することができません。 次の方法のいずれかを使用し変更を加えた設定が有効になるようにしてください。

  • dao.diconをコピーしコピーしたファイルに変更を加え、s2-dao-x.x.x.jarより優先度の高いclasspathへ配置する
    Seasar2.3とSeasar2.4の両方で使用可能です。 オリジナルのdao.diconとコピーしたdao.diconのどちらがclasspathで優先されるのか確定できない場合には使用しないでください。
  • dao.diconを新しい名前でコピーしコピーしたファイルに変更を加え、他の定義ファイルからは新しい名前で参照する
    Seasar2.3とSeasar2.4の両方で使用可能です。
  • 定義ファイルの差し替え機能を利用する
    Seasar2.4でのみ使用可能です。s2container.diconに次のように設定してください。
    <component class="org.seasar.framework.container.factory.SimplePathResolver">
      <initMethod name="addRealPath">
        <arg>"dao.dicon"</arg>
        <arg>"my-dao.dicon"</arg><!-- 実際に使用する定義ファイル -->
      </initMethod>
    </component>
    
    この設定により,ある定義ファイルが'dao.dicon"という名前でdiconファイルをインクルードすると,実際には'my-dao.dicon'がインクルードされます。詳細は「DIContainer」-「定義ファイルの差し替え」を参照してください。

S2Daoのカスタマイズ

カスタマイズの方法は2種類あります。

1つ目は、dao.diconに登録されているコンポーネントのプロパティに特定の値を設定することでコンポーネントの振る舞いを変化させる方法です。 2つ目は、dao.diconに登録されているコンポーネントを別のコンポーネントに差し替える方法です。 dao.diconに登録されているコンポーネントはすべてインタフェースの実装であるため、同じインタフェースをもつ別の実装に容易に差し替えることができます。

コンポーネントのプロパティの設定によるカスタマイズ

dao.diconに定義されたコンポーネントには設定が可能なプロパティを提供しているものがあります。

DaoMetaDataFactoryImpl

org.seasar.dao.impl.DaoMetaDataFactoryImplのプロパティの変更により次のことが可能になります。

  • ログのカテゴリをDaoクラスで振り分ける
  • SQLファイルのエンコーディング名を指定する

設定可能なプロパティは次の通りです。

プロパティ名 説明 デフォルト値
boolean useDaoClassForLog trueの場合、SQLのログ出力のカテゴリにDaoのクラスが使用されます。 falseの場合、SQLのログ出力のカテゴリにはorg.seasar.extension.jdbc.impl.BasicHandlerが使用されます。 false
String sqlFileEncoding SQLファイルのエンコーディング名です。 ここに指定された文字列はjava.io.InputStreamReader(InputStream, String)の第2引数にそのまま使用されます。 "JISAutoDetect"

DaoNamingConventionImpl

org.seasar.dao.impl.DaoNamingConventionImplはS2Dao全体の命名規約を管理するコンポーネントです。 プロパティの変更により次のことが可能です。

  • バージョン番号のプロパティ名を変更する
  • タイムスタンプのプロパティ名を変更する
  • Daoインターフェースの命名規約を変更する
  • メソッドの命名規約を変更する
  • UnlessNull機能に関する規約を変更する
  • ModifiedOnly機能に関する規約を変更する

設定可能なプロパティは次の通りです。

プロパティ名 説明 デフォルト値
String versionNoPropertyName バージョン番号のプロパティ名です。 "versionNo"
String timestampPropertyName タイムスタンプのプロパティ名です。 "timestamp"
String[] daoSuffixes Daoインタフェースのサフィックスの配列です。 "Dao"
String[] insertPrefixes 追加メソッドのプレフィックスの配列です。 "insert", "create", "add"
String[] updatePrefixes 更新メソッドのプレフィックスの配列です。 "update", "modify", "store"
String[] deletePrefixes 削除メソッドのプレフィックスの配列です。 "delete", "remove"
String[] unlessNullSuffixes UnlessNull機能をもつ更新メソッドのサフィックスの配列です。 "UnlessNull"
String[] modifiedOnlySuffixes ModifiedOnly機能をもつ更新メソッドのサフィックスです。 "ModifiedOnly"
String modifiedPropertyNamesPropertyName ModifiedOnly機能で使用するプロパティの名前です。 "modifiedPropertyNames"

ResultSetHandlerFactorySelector

バージョン1.0.51より、org.seasar.dao.impl.ResultSetHandlerFactorySelectorのプロパティの変更により次のことが可能になります。

  • 返り値がBeanやDTO、Mapのメソッドで、結果が2件以上の時に例外を投げる。

設定可能なプロパティは次の通りです。

プロパティ名 説明 デフォルト値
boolean restrictNotSingleResult trueの場合、org.seasar.dao.NotSingleResultRuntimeExceptionがスローされます。 falseの場合、警告ログが出力されます。 false

コンポーネントの差し替えによるカスタマイズ

dao.diconに定義されたコンポーネントはインタフェースの定義に従う限りすべて任意のコンポーネントに差し替えることが可能です。 いくつかのコンポーネントについてはS2Daoが代替の実装をあらかじめ提供しています。以下では、S2Daoが提供するコンポーネントを説明します。

Daoの初期化を高速化する

S2Daoのデフォルトの振る舞いでは、Daoの初期化時に、どのプロパティが永続的であるのか どのプロパティが主キーであるのかといった情報をBeanに指定されたアノテーションとデータベースのメタデータから判定していますが、 RDBMSによってはデータベースのメタデータの取得にとても時間がかかることが判明しています(Oracleなど)。 そこで、データベースのメタデータにはアクセスせず、Beanのアノテーションの情報のみを使って高速にプロパティの永続性や主キーを判定するコンポーネントが用意されています。

このコンポーネントを利用するには org.seasar.dao.impl.PropertyTypeFactoryBuilderImplorg.seasar.dao.impl.FastPropertyTypeFactoryBuilderに差し替えてください。

単にコンポーネントを入れ替えただけでは動作しない場合があります。 FastPropertyTypeFactoryBuilderを使用する場合は、カラム名や主キーの情報などをデータベースに一致するようにアノテーションを指定してください。

キャメルケースで表された名前をもつBeanとアンダースコア区切りの名前のテーブルを自動で対応付ける

アノテーションで明示しない場合、デフォルトの規約では、BeanはBeanの名前と同じ名前のテーブルに対応付けられます。 しかし、Javaのクラス名は単語の区切りをキャメルケースで表すがテーブル名はアンダースコア区切りで表すと言った場合に、このデフォルトの規約は利用できません。 そこで、キャメルケースで表されたJavaのクラス名をアンダースコア区切りで表されたテーブル名に変換するコンポーネントが用意されています。 この変換によりS2Daoはキャメルケースで表されたJavaのクラス名をアンダースコア区切りで表されたテーブル名に対応付けることができます。

例えば、hoge.foo.BarBazというBeanクラスがBAR_BAZテーブルに対応します。

このコンポーネントを利用するには org.seasar.dao.impl.DefaultTableNamingorg.seasar.dao.impl.DecamelizeTableNamingに差し替えてください。

キャメルケースで表された名前をもつプロパティとアンダースコア区切りの名前のカラムを自動で対応付ける

アノテーションで明示しない場合、デフォルトの規約では、Beanのプロパティはプロパティの名前と同じ名前のカラムに対応付けられます。 しかし、Javaのプロパティ名は単語の区切りをキャメルケースで表すがカラム名はアンダースコア区切りで表すと言った場合に、このデフォルトの規約は利用できません。 そこで、キャメルケースで表されたJavaのプロパティ名をアンダースコア区切りで表されたカラム名に変換するコンポーネントが用意されています。 この変換によりS2Daoはキャメルケースで表されたJavaのプロパティ名をアンダースコア区切りで表されたカラム名に対応付けることができます。

例えば、barBazというプロパティがBAR_BAZカラムに対応します。

このコンポーネントを利用するには org.seasar.dao.impl.DefaultColumnNamingorg.seasar.dao.impl.DecamelizeColumnNamingに差し替えてください。

UPDATE時、修正したプロパティのみを更新対象とする

S2DaoのModifiedOnly機能を使って変更した(setterを呼び出した)プロパティのみをUPDATE文のSET句に指定されるようにする場合、getModifiedPropertyNamesというメソッドを実装する必要があります。これを検索メソッドからの戻り値に対してAOPを使って自動的に実装するのがBeanEnhancerImplです。

このコンポーネントを利用するには、 org.seasar.dao.impl.NullBeanEnhancerorg.seasar.dao.impl.BeanEnhancerImplに差し替えてください。

ただし、この機能はシリアライズ/デシリアライズとの相性が悪いことがありますので、そういった機能を利用する場合には、使用しないようにしてください。詳しくはメソッドの定義を参照してください。