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" 
        class="org.seasar.extension.jdbc.types.StringClobType"
    />
    <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"这个名字包含(include)dicon文件时,实际上包含的是'my-dao.dicon'文件。详细情况请参阅「DIContainer」-「替换定义文件」的章节。

S2Dao的改造

改造方法有2种。

第一种,通过在dao.dicon中登录的组件的属性中,设定特殊值使组件动作发生变化的方法。 第二种,把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全体命名规约的组件。 通过更改属性可以实现以下的功能。

  • 更改版本号的属性名
  • 更改时间印戳(timestamp)的属性名
  • 更改Dao接口的命名规约
  • 更改方法(method)的命名规约
  • 更改有关UnlessNull功能的规约
  • 更改有关ModifiedOnly功能的规约

可以设定的属性如下所示。

类型 属性名 说明 缺省值
String versionNoPropertyName 版本号的属性名。 "versionNo"
String timestampPropertyName 时间印戳(timestamp)的属性名。 "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"

通过组件的替换进行改造

在dao.dicon中定义的组件,只要遵循接口定义,全部可以用任意的组件来替换。 S2Dao预先提供了一些有着可代替的实装的组件。以下说明这些S2Dao提供的组件。

对Dao的初始化实现高速化

S2Dao的值为缺省时的动作中,在Dao执行初始化时,虽然哪一个属性是持久化属性, 哪一个属性是主键,这些信息可以通过Bean里指定的注释(annotation)和数据库的元数据(metadata)来判定, 但是我们已经知道,通过RDBMS取得数据库(Oracle等)的元数据的话非常的费时间。 因此,提供了一个不用访问数据库的元数据,只用Bean的注释信息就能快速判断持久化属性或是主键的组件。

要使用这个组件,请把 org.seasar.dao.impl.PropertyTypeFactoryBuilderImpl替换成 org.seasar.dao.impl.FastPropertyTypeFactoryBuilder

仅仅更换组件的话有时候无法动作。 使用FastPropertyTypeFactoryBuilder的场合,请用注释(annotation)使列名或主键的信息与数据库的信息保持一致。

遵循CamelCase命名法的Bean和带下划线的表名之间的自动关联

不用注释进行显式声明的场合,按照缺省规约,Bean将和与Bean同名的表名进行关联。 但是,Java的类名是按照CamelCase命名法表示的,表名则用下划线表示的场合,不能使用这一缺省规约。 因此提供一个组件,把按照CamelCase命名法表示的Java类名变换成用下划线表示的表名。 通过这一变换,S2Dao能够把CamelCase命名法表示的Java类名和用下划线表示的表名进行关联。

例如,把名为hoge.foo.BarBaz的Bean类和BAR_BAZ表进行关联。

要利用这个组件,请把 org.seasar.dao.impl.DefaultTableNaming替换成 org.seasar.dao.impl.DecamelizeTableNaming

遵循CamelCase命名法的属性名和带下划线的列项之间的自动关联

不用注释进行显式声明的场合,按照缺省规约,Bean的属性将和与属性名同名的列项进行关联。 但是,Java的属性名是按照CamelCase命名法表示的,列项名则用下划线表示的场合,不能使用这一缺省规约。 因此提供一个组件,把按照CamelCase命名法表示的Java属性名变换成用下划线表示的列项名。 通过这一变换,S2Dao能够把CamelCase命名法表示的Java属性名和用下划线表示的列项名进行关联。

例如,把名为barBaz的属性和BAR_BAZ列项进行关联。

要利用这个组件,请把 org.seasar.dao.impl.DefaultColumnNaming替换成 org.seasar.dao.impl.DecamelizeColumnNaming

UPDATE时,只把修改过的属性当作更新对象

使用S2Dao的ModifiedOnly功能,只把修改过(调用setter)的属性设定到UPDATE指令的SET子句里的场合,必须对getModifiedPropertyNames方法进行实装。对于检索方法的返回值,BeanEnhancerImpl将使用AOP,对其自动进行实装。

要利用这个组件,请把 org.seasar.dao.impl.NullBeanEnhancer替换成 org.seasar.dao.impl.BeanEnhancerImpl

但是,这一功能与序列化/反序列化功能不相合,要使用序列化/反序列化功能的场合,请不要使用这个功能。详细情况请参阅方法的定义的章节。