精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-06-15
suntoe 写道 很棒啊,我也考虑着怎么支持hibernate,好像用ibatis的人和hibernate比实在不成比例。
解释一下daozero(for ibatis)的做法,现在的实现也可以用spring interceptor做,之所以自己直接去使用cglib/jdk proxy,有那么1000多行代码,目的是为了简化配置,也就是说把这种可以固定下来的aop配置写死在代码里了,这样就不需要使用者去理解spring aop(我实在不满意spring aop那种绕来绕去的配置方法)。 讨论下把你的东东放进daozero怎么样(强烈期待)? 这几天没有上来看,差点漏掉你的回复。 其实我的实现几乎是可以忽略的,只是利用Spring的工具写了几行代码,你完全可以拿过去用 如果要做一个通用的hibernate dao zero的话,可以将create/udpate/delete/query分离到不同的interceptor,并且允许用户自定义name mapping strategy,比如默认的是method name 和 named query是同名的,用户也可以定义出class name + method name = named query。 另外我不同意你的看法,如果在用户使用方便的角度出发,我们完全可以将前面那样的配置文件放到代码里面,或者打包到jar里面,这样简洁又不失灵活,而且可以最大程度地利用spring已有的代码。 |
|
返回顶楼 | |
发表时间:2006-06-16
Quake Wang 写道 suntoe 写道 很棒啊,我也考虑着怎么支持hibernate,好像用ibatis的人和hibernate比实在不成比例。
解释一下daozero(for ibatis)的做法,现在的实现也可以用spring interceptor做,之所以自己直接去使用cglib/jdk proxy,有那么1000多行代码,目的是为了简化配置,也就是说把这种可以固定下来的aop配置写死在代码里了,这样就不需要使用者去理解spring aop(我实在不满意spring aop那种绕来绕去的配置方法)。 讨论下把你的东东放进daozero怎么样(强烈期待)? 这几天没有上来看,差点漏掉你的回复。 其实我的实现几乎是可以忽略的,只是利用Spring的工具写了几行代码,你完全可以拿过去用 如果要做一个通用的hibernate dao zero的话,可以将create/udpate/delete/query分离到不同的interceptor,并且允许用户自定义name mapping strategy,比如默认的是method name 和 named query是同名的,用户也可以定义出class name + method name = named query。 嗯,是这样。 “create/udpate/delete/query分离”的结构在ibatis版的dao-zero中是类似这么做的。 class name我的理解是可以和ibatis的namespace概念对应起来,named query本身已经有点ibatis的味道了。 对于hibernate版,我还在想的是,因为hibernate里保持着比ibatis多得多的orm信息/metadata,所以dao-zero充分挖掘并利用起来的话可以比ibatis版的做得功能更强、更多、也更“智能”。 Quake Wang 写道 另外我不同意你的看法,如果在用户使用方便的角度出发,我们完全可以将前面那样的配置文件放到代码里面,或者打包到jar里面,这样简洁又不失灵活,而且可以最大程度地利用spring已有的代码。 :)还是想给自己辩解。 “配置文件放到代码里面“的思路和我现在的做法本质上并没不同,打包到jar里面的话可以简洁些,但对于使用者终究是多了些他需要理解的属于内部实现方法的东西。 另外,不知道是不是理解错了你的想法,我的理解,用外部配置好的显式的aop interceptor带来的灵活性一般也就是能允许更改interceptor链,但是对于dao层的东西来说,我怀疑必要性有多大。 从另一个角度讲,daozero这样的东西是作为1个component提供出来的,component对外应该应该是个黑盒,不暴露实现方式,如果使用者真要再做intercept,也可以在这个component外层做。 对于“最大程度地利用spring已有的代码”,因为我是考虑以后脱离spring也可以用,所以没这么做。 |
|
返回顶楼 | |
发表时间:2006-07-05
0.4版发布了,加上了几个新特性:
1.支持dao方法返回iBatis的PaginatedList,或者返回分页后的java.util.List。为此要求遵守两个约定:对于需要返回PaginatedList的dao方法,约定方法的最后一个参数的类型必须是int,用于传递分页大小;对于返回分页后的java.util.List的dao方法,约定方法的末尾两个参数的类型必须是int,用于传递分页起始行位置和分页大小。这两个特性加上以后,对iBatis的支持就只差一个queryForMap了。 2.根据heaven的提议,可以自动地把iBatis返回的java.util.List转换为其他类型,例如java.lang.String[]数组,java bean的数组, java.util.Iterator和java.util.Set等等。 也修改了个大bug:iBatis SQL statement中有用$...$表示的动态parameter时会报错,说是parameter数目与dao方法参数数目不匹配而找不到相应的dao方法。 另外,在zip目录下又加上了个HelloWorld命令行例子程序,用于补充演示基本的使用方法。 我还试着加入了中文的出错信息,希望能对大家有些帮助。 |
|
返回顶楼 | |
发表时间:2006-07-17
自己很少用jdk1.5,昨天把daozero拿到1.5下试了把,结果因为是直接使用了jdk1.4的crimson XML导致编译都过不了,原先在1.4下做好的jar也运行出错,所以赶快修改,发布了这个0.4.1版。
这个版本在jdk1.4和1.5下都可以用。 |
|
返回顶楼 | |
发表时间:2006-07-17
计划0.5版起初步支持hibernate
|
|
返回顶楼 | |
发表时间:2007-05-13
刚发布daozero 0.5。过两天我就会把相关文档更新好,不过看下面这些也足够了。
主要的变化是: 1.允许为某个method手工指定它使用哪个iBatis SQL statement。当然原来的自动指定还是在的。 这样就可以做到允许dao interface里有同名的method了。 譬如说一个userDao bean,它的dao interface是 public interface UserDao { List findUsers( String address ); List findUsers( String address, Date registerDate ); List findUsers( User conditionBean ); } 在0.5版之前,是不允许同一个interface里存在同名的(重载的)method的。现在,我给daozero.ibatis.Dao增加了一个叫methodMap的新属性,这是个map,map的key是method的声明(称为signature),map的value是iBatis SQL statement的名字。 对这个map的最方便的用法是把interface里method的声明直接拷贝到spring xml里,不过也不是非得如此,我尽量把对signature的parser做得了“聪明”些:只要signature能和其它method区分开来,譬如省略掉参数名字,省略掉返回类型,甚至全省略掉只留下个逗号(如果它的参数个数可以用于和其它method区分开来的话),怎么样写都可以。所以,拿List findUsers( String address, Date registerDate )来说,下面这些都是可能被接受的: List findUsers( String address, Date registerDate ) findUsers( String address, Date registerDate ) findUsers( address, Date registerDate ) findUsers( address, registerDate ) findUsers( String, Date ) findUsers( , Date ) findUsers( String, ) findUsers( , ); 另外,里头加上exception声明也没问题(会被parser忽略)。 不过即使这样,还是推荐大家写全了,也许以后可以用参数类型和参数名字做出其它新功能来,譬如说可以用来去除iBatis XML里的statement的参数顺序和method的形参顺序必须保持一致这个限制。 这个功能的实现方式实际上也可以用annotation来做,我准备在接下来的一个版本里加上annotation,同时现在这个做法也能用来保持对jdk1.4的兼容, 具体使用的spring xml的例子是: <bean id="userDao" class="daozero.ibatis.Dao"> <property name="sqlMapClient" ....../> <property name="targetType" value="UserDao"/> <property name="methodMap"> <map> <entry key="List findUsers( String address )" value="FIND_USERS_BY_ADDRESS"/> <entry key="findUsers( String, Date )" value="FIND_USERS_BY_ADDRESS_AND_REGISTER_DATE"/> <entry key="findUsers( User )" value="FIND_USERS"/> </map> </property> </bean> 2.heaven建议可以判断一下返回值,如果是数组的话可以把 queryforlist的结果转成强类型的数组,这个现在做进去了。这些是自动的,大家直接用就是,改接口方法的返回值类型就可以,不需要动spring xml。 我还把这种结果的自动转换扩充了些,现在可以做到把iBatis返回的list自动转成List的子类型、Set的子类型、Iterator、Enumeration。 queryForObject返回的Object是java bean的话也可以被自动转换为别的java bean,daozero会自动判断去做两个java bean间属性的拷贝,不过这个功能可能没太大用处,做进去只是觉得挺有趣的。 3.从heaven的建议触类旁通,我把类型自动转换的想法也用到了处理传入的参数上:现在,对于update/delete/insert方法,如果传入的参数的类型是Collection或Iterator或Enumeration或强类型的数组,那么里面的元素将被提取出来依次用来调用ibatis,而且,如果daozero的属性batchMode是true的话,会调用startBatchMode()启动批处理模式,可能这样性能会好些。 4.改掉了个bug: zhouxuanyi发现的daozero.ibatis.AutoProxy里的m_dao就是null的问题; 5.现在,如果把daozero bean的属性printMethodMap设成true(缺省是false的),那么会把每个method对应到哪个sql statement打印出来,方便大家调试跟踪。 |
|
返回顶楼 | |
发表时间:2007-05-14
原先计划0.5版起初步支持hibernate版的,现在想还是先把ibatis版先做做好
|
|
返回顶楼 | |
发表时间:2007-05-16
Quake Wang 写道 Hi suntoe,
很不错的想法,我用Spring提供的代码库写了一个非常简化的Hibernate DAO Zero 其实就写了一个类: public class GenericInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { HibernateDaoSupport dao = (HibernateDaoSupport) invocation.getThis(); String methodName = invocation.getMethod().getName(); Object[] arguments = invocation.getArguments(); if (methodName.startsWith("find")) { return dao.getHibernateTemplate().findByNamedQuery(methodName, arguments); } else if (methodName.startsWith("create")) { return dao.getHibernateTemplate().save(arguments[0]); } else if (methodName.startsWith("update")) { dao.getHibernateTemplate().update(arguments[0]); return null; } else if (methodName.startsWith("delete")) { dao.getHibernateTemplate().delete(arguments[0]); return null; } return invocation.proceed(); } } 配置文件: <bean id="abstractDao" class="daozero.dao.GenericHibernateDao"> <property name="sessionFactory"><ref local="sessionFactory"></ref></property> </bean> <bean id="genericInterceptor" class="daozero.aop.GenericInterceptor"/> <bean id="accountDao" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"><value>daozero.sample.dao.AccountDao</value></property> <property name="target"><ref local="abstractDao"></ref></property> <property name="interceptorNames"> <list> <value>genericInterceptor</value> </list> </property> </bean> 测试代码: public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("daozero/sample/application_context.xml"); AccountDao dao = (AccountDao) context.getBean("accountDao"); Account account = new Account(); account.setUserName("quake"); account.setPassword("123456"); account.setEmail("quake_wang@iteye.com"); dao.createAccount(account); assertNotNull(account.getId()); account.setPassword("111111"); dao.updateAccount(account); Account loaded = (Account) dao.findAccountsByName("quake").get(0); assertEquals("111111", loaded.getPassword()); assertEquals("quake_wang@iteye.com", loaded.getEmail()); } 还没有仔细看过你的代码,但是觉得也可以像这个简单的例子,用spring提供的SqlMapSupport和interceptor一样搞定,不需要像你的代码里面写那么多,附件是源代码和测试例子,抛砖了... 请问如果要实现getHibernateTemplate().get(Class.ID)得话要如何实现? |
|
返回顶楼 | |