结合脚本生成 实现 ibatis sqlmap 的"继承"

在使用ibatis实现数据库层映射时, sqlmap提供了很好的灵活性,可以方便的调试,改进sql语句的性能。将ibatis访问数据库操作作了一层封装后,原来的ibatis sqlmap 生成工具就不能很好的满足要求了。对于很多的表都对应于业务实体,需要手工一个个的写过来,这个实在是有点…… 后来使用了一款代码生成工具,编写脚本,自动生成自定义格式的dao和sqlmap,感觉还不错。不过美中不足的是,自动生成的sqlmap只是实现了基本的增、删、改、查功能,若需要自定义的sql脚本,就必须修改生成的sqlmap文件,一旦数据库修改,再次生成后就不能简单的覆盖了事,还需要手工修改,誊抄,这样一来就比较烦,也容易乱。

后来,就想,要是sqlmap文件也能像类那样能够继承,有修改或添加只需要修改“派生类”的sqlmap文件,而“父类”sqlmap文件可以多次自动生成, 那多好。查看相关资料后,发现派生org.springframework.orm.ibatis.SqlMapClientFactoryBean类,实现mappingLocations的重载,可以将多个目录中的sqlmap文件按次序加载,当然,加载的先后次序一定要保证“父类”的sqlmap文件先于“派生类”的sqlmap文件。

 

1. 为org.springframework.orm.ibatis.SqlMapClientFactoryBean派生类的部分代码:

/**
* 用于生成SqlMapClient,但增加设置sqlExecutor属性,以便用于扩展ibatis使用数据库物理分页
*
*/
public class SqlMapClientFactoryBeanEx extends org.springframework.orm.ibatis.SqlMapClientFactoryBean{
    。。。。。。

private Resource[] extMappingLocations;

private Resource[] mappingLocations;

/**
* 将截获的mappingLocations,和扩展的extMappingLocations合并,再调用父类的set函数,完成mappingLocations的注入
* @param extMappingLocations
*/
public void setExtMappingLocations(Resource[] extMappingLocations) {
    this.extMappingLocations = extMappingLocations;
   
    List<Resource> lists = new ArrayList<Resource>();
   
    if(this.mappingLocations.length >0){
        for(Resource r : this.mappingLocations){
            lists.add(r);
        }
    }
   
    for(Resource r : this.extMappingLocations){
        lists.add(r);
    }
   
    Resource[] extMaps = lists.toArray(new Resource[0]);
    super.setMappingLocations(extMaps);
}

/**
* 重载父类的mappingLocations注入,截获Resource[],已被和扩展的extMappingLocations组合
*/
@Override
public void setMappingLocations(Resource[] mappingLocations) {
    this.mappingLocations = mappingLocations;
}

。。。。。。

}

 

2.有关ibatis的配置文件片断:

    <!-- sqlMapClient -->
    <bean id="sqlMapClient" class="com.cgnw.sns.dbaccess.ibatis.SqlMapClientFactoryBeanEx">

        <property name="configLocation">
            <value>WEB-INF/conf/SqlMapConfig.xml</value>
        </property>
        <!-- 自动解析*_sqlmap.xml文件, 注意先后顺序,不能搞反了-->
        <property name="mappingLocations">
            <value>classpath:com/cgnw/sns/dbaccess/sqlmapxml/*_SqlMap.xml</value>
        </property>
        <property name="extMappingLocations">
            <value>classpath:com/cgnw/sns/businessweb/sqlmapxmlExt/*_SqlMap.Ext.xml
            </value>
        </property>
        <property name="dataSource" ref="dataSource" />
        <!--指定数据库分页方言Dialect -->
        <property name="sqlExecutor">
            <bean class="com.cgnw.sns.dbaccess.ibatis.LimitSqlExecutor">
                <property name="dialect">
                    <bean class="com.cgnw.sns.dbaccess.ibatis.OracleDialect" />
                </property>
            </bean>
        </property>

      </bean>

3. sqlmap文件样本

<!--
    File: com.cgnw.sns.domain.City_SqlMap.xml.
    Description:These codes were generated by CodeSmith.
    Copyright 2006-2011 cgnw Corporation. All rights reserved.
-->
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="City">
    <typeAlias alias="City" type="com.cgnw.sns.dbaccess.domain.City" />
    <resultMap class="City" id="CityMap">
        <result property="cityCd" column="city_cd"  />
        <result property="stateCd" column="state_cd"  />
        <result property="cityName" column="city_name"  />
        <result property="cityClass" column="city_class"  />
        <result property="parentCity" column="parent_city"  />
        <result property="cityOrder" column="city_order"  />
        <result property="cityNote" column="city_note"  />
    </resultMap>
   
    <!-- INSERT -->
    <insert id="insert" parameterClass="City">
       INSERT INTO
       <dynamic prepend="t_city" open="(" close=")">
                city_cd,
                state_cd,
                city_name,
                <isNotNull prepend="," property="cityClass">city_class</isNotNull>
                <isNotNull prepend="," property="parentCity">parent_city</isNotNull>
                <isNotNull prepend="," property="cityOrder">city_order</isNotNull>
                <isNotNull prepend="," property="cityNote">city_note</isNotNull>
        </dynamic>
        <dynamic open="(" close=")" prepend="VALUES">
        s_t_city.nextval,
                #stateCd#,
                #cityName#,
                <isNotNull prepend="," property="cityClass">#cityClass#</isNotNull>
                <isNotNull prepend="," property="parentCity">#parentCity#</isNotNull>
                <isNotNull prepend="," property="cityOrder">#cityOrder#</isNotNull>
                <isNotNull prepend="," property="cityNote">#cityNote#</isNotNull>
        </dynamic>
        <selectKey resultClass="String">
        SELECT s_t_city.CURRVAL FROM DUAL
        </selectKey>
    </insert>
   
    <!-- UPDATE -->
    <update id="update" parameterClass="City" >
        UPDATE t_city
        <dynamic prepend="SET">
            <isNotNull prepend="," property="stateCd" removeFirstPrepend="true">state_cd=#stateCd#</isNotNull>
            <isNotNull prepend="," property="cityName" removeFirstPrepend="true">city_name=#cityName#</isNotNull>
            <isNotNull prepend="," property="cityClass" removeFirstPrepend="true">city_class=#cityClass#</isNotNull>
            <isNotNull prepend="," property="parentCity" removeFirstPrepend="true">parent_city=#parentCity#</isNotNull>
            <isNotNull prepend="," property="cityOrder" removeFirstPrepend="true">city_order=#cityOrder#</isNotNull>
            <isNotNull prepend="," property="cityNote" removeFirstPrepend="true">city_note=#cityNote#</isNotNull>
        </dynamic>
            WHERE city_cd=#cityCd#
    </update>
   
    <!-- select an object by primaryKey -->
    <select id="selectByPrimaryKey" resultMap="CityMap" parameterClass="String">
        SELECT * FROM T_CITY WHERE CITY_CD=#cityCd#
    </select>
   
    <select id="select" resultMap="CityMap" parameterClass="Map">
        SELECT * FROM  T_CITY
        <dynamic prepend="WHERE">
            <isNotNull prepend=" AND " property="stateCd" removeFirstPrepend="true">state_cd=#stateCd#</isNotNull>
            <isNotNull prepend=" AND " property="cityName" removeFirstPrepend="true">city_name=#cityName#</isNotNull>
            <isNotNull prepend=" AND " property="cityClass" removeFirstPrepend="true">city_class=#cityClass#</isNotNull>
            <isNotNull prepend=" AND " property="parentCity" removeFirstPrepend="true">parent_city=#parentCity#</isNotNull>
            <isNotNull prepend=" AND " property="cityOrder" removeFirstPrepend="true">city_order=#cityOrder#</isNotNull>
            <isNotNull prepend=" AND " property="cityNote" removeFirstPrepend="true">city_note=#cityNote#</isNotNull>
        </dynamic>
        <dynamic prepend="ORDER BY">
            <isNotNull property="orderBy">$orderBy$</isNotNull>
        </dynamic>
    </select>
   
    <select id="count" resultClass="Integer" parameterClass="Map">
        SELECT COUNT(*) FROM T_CITY
        <dynamic prepend="WHERE">
                <isNotNull prepend=" AND " property="stateCd" removeFirstPrepend="true">state_cd=#stateCd#</isNotNull>
                <isNotNull prepend=" AND " property="cityName" removeFirstPrepend="true">city_name=#cityName#</isNotNull>
                <isNotNull prepend=" AND " property="cityClass" removeFirstPrepend="true">city_class=#cityClass#</isNotNull>
                <isNotNull prepend=" AND " property="parentCity" removeFirstPrepend="true">parent_city=#parentCity#</isNotNull>
                <isNotNull prepend=" AND " property="cityOrder" removeFirstPrepend="true">city_order=#cityOrder#</isNotNull>
                <isNotNull prepend=" AND " property="cityNote" removeFirstPrepend="true">city_note=#cityNote#</isNotNull>
        </dynamic>
    </select>
       
    <!-- DELETE -->
    <delete id="delete" parameterClass="String">
        DELETE FROM T_CITY WHERE
        city_cd=#cityCd#
    </delete>
</sqlMap>

<!-- Generating End -->

 

4. sqlmapex文件样本

<?xml version="1.0" encoding="UTF-8"?>
<!--
    File: com.cgnw.sns.domain.City_SqlMap.Ext.xml.
    Description:These codes were generated by CodeSmith.
    Copyright 2006-2011 cgnw Corporation. All rights reserved.
-->
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="City"><!--注意namespace和“父类”的相同,共用resultmap-->
    <!--
        <resultMap class="City" id="CityMap">
            <result property="cityCd" column="city_cd"  />
            <result property="stateCd" column="state_cd"  />
            <result property="cityName" column="city_name"  />
            <result property="cityClass" column="city_class"  />
            <result property="parentCity" column="parent_city"  />
            <result property="cityOrder" column="city_order"  />
            <result property="cityNote" column="city_note"  />
        </resultMap>
    -->
   
    <!-- Here are your's codes... -->
   
</sqlMap>

这样,开发时可以只修改sqlmapex文件,而sqlmap文件有工具来维护,感觉比较方便。

 

5. 参考文章

http://www.iteye.com/topic/930092 让sqlmap文件 "继承" 起来

posted on 2011-09-30 14:41  agefish  阅读(1032)  评论(0编辑  收藏  举报