今天看到了这篇文章,与大家共享!\前提条件:使用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>
推荐条件:使用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>
解决方案 »
- java新手使用for循环完成数组元素的插入
- 一些面试题 帮忙看下 给个答案或者解释
- 一个异常错误,请问是哪出错了!
- 请问哪位高手教教小弟用Java跟数据库如何连接及它们的驱动下载?
- 请教大吓们:String 与 StringBuffer 有什么区别??!! -- 急切中...
- 多线程的出来
- 100 * 5.11 = 511.00000000000006
- 用java 怎样读写sql server 的 image 字段呢!!!~~~有例子么
- 如果用regsvr32在服务器上注册了一个组件,能从那里看出这个组件已注册在服务器上?
- 请各位大侠指教:如何实现对象的关系表映射?
- 配置文件问题,高手指点!
- 关于环境变量classpath 的问题
代码
<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