今天看到了这篇文章,与大家共享!\前提条件:使用iBatis,用一个statement的名字来代表一个(组)SQL;而DAO接口的方法名必须与statement名字一一对应; 
推荐条件:使用Spring,允许用一个FactoryBean生成一个实现了DAO接口的动态proxy思路:DAO接口的方法名与statement名字一一对应,所以可以在动态proxy的invoke()方法中截获对DAO接口方法的调用,用方法名作为statement名,用方法的参数组成statement的parameter map,然后就可以调用iBaits的queryForObject()等API了。这样,许多dao接口的实现代码就可以不需要了,定义一个DAO接口,一个Spring Bean和一个SQL mapping xml文件即可。 
当然,有时候还是需要允许手工写的DAO代码覆盖这个动态proxy接口的,所以可以让这个动态proxy只拦截abstract方法。所以我视被proxy的类是否是接口分别用jdk的proxy和cglib的enhancer实现。 
不过,因为iBatis API不提供其statement的meta data,所以现在的实现代码中hack了iBatis的API,感觉不好。 
大家觉得值得讨论的话我争取明天晚上整理好代码传上来。比如拿spring的jpetstore中的用户账号接口来说 
代码
public interface AccountDao {   
  
  Account getAccountByUsername(String username)                        throws DataAccessException;    
  
    List getUsernameList() throws DataAccessException;   
    //其他方法省略   
}   
它使用到的iBatis SQL Mapping XML如下: 代码
<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">  
  
<sqlMap namespace="Account">  
  
  <resultMap id="result" class="daozero.sample.jpetstore.domain.Account">  
    <result property="username" column="userid" columnIndex="1"/>  
    <result property="email" column="email" columnIndex="2"/>  
    <!-- 其它属性声明省略 -->  
  </resultMap>  
  
  <select id="getAccountByUsername" resultMap="result">  
    select   
          signon.username as userid,   
          account.email,                             account.firstname,   
          account.lastname,          account.status,   
          account.addr1,          account.addr2,   
          account.city,          account.state,   
          account.zip,          account.country,   
          account.phone,          profile.langpref,   
          profile.favcategory,          profile.mylistopt,   
          profile.banneropt,          bannerdata.bannername   
    from account, profile, signon, bannerdata   
    where account.userid = #value#   
      and signon.username = account.userid   
      and profile.userid = account.userid   
      and profile.favcategory = bannerdata.favcategory   
  </select>  
  
  <select id="getUsernameList" resultClass="java.lang.String">  
    select username as value from signon   
  </select>  
  
  <!- 其它statement声明省略 -->  
  
</sqlMap>  

解决方案 »

  1.   

    在spring bean定义中这么定义 
    代码
           
    <bean id="baseDao" abstract="true"  class="daozero.Dao">  
            <property name="sqlMapClient" ref="sqlMapClient"/>  
        </bean>  
           
        <bean id="accountDao" parent="baseDao">  
            <property name="targetType" value="org.springframework.sample.jpetstore.dao.ibatis.auto.SqlMapAccountDao" />  
            <property name="namespace" value="Account"/>  
        </bean>  
    其中daozero.Dao就是我说的能自动实现dao接口的动态proxy。 
    在这个例子中,对于accountDao这个bean来说,它只需要定义一个将接口类型
    代码
    org.springframework.sample.jpetstore.dao.ibatis.auto.SqlMapAccountDao  
    设到bean的属性targetType即可,一行实现类代码都不需要。真正自己写的source只是daozero一个包。 
    jpetstore的例子是改自spring 1.2.7带的那个jpetstore例子。 
    自己感觉是有些实用价值的(虽然很小),准备放到sourceforge上去,所以,已经写上了一些license声明(APL 2.0)带了很多库文件,还自带了ant,所以压缩后还有5.8兆之多,所以只能用rar分成几个文件分别上传。第一个文件是exe,所以如果担心中病毒就别双击直接执行,用鼠标右键的Open With WinRAR打开就可以了(废话?:) )。使用方法:解开后看根目录下的readme.txt中。第一个文件。没有rar的话可以把这第一个文件的后缀名(rar)改成exe,再双击执行。这个方案看起来很过瘾,大家提点建议,感谢!转:http://www.javaeye.com/topic/19732