论坛首页 Java企业应用论坛

关于dao-zero的版本升级(以后dao-zero的消息)

浏览 19695 次
精华帖 (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已有的代码。
0 请登录后投票
   发表时间: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也可以用,所以没这么做。
0 请登录后投票
   发表时间: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命令行例子程序,用于补充演示基本的使用方法。

我还试着加入了中文的出错信息,希望能对大家有些帮助。
0 请登录后投票
   发表时间:2006-07-17  
自己很少用jdk1.5,昨天把daozero拿到1.5下试了把,结果因为是直接使用了jdk1.4的crimson XML导致编译都过不了,原先在1.4下做好的jar也运行出错,所以赶快修改,发布了这个0.4.1版。
这个版本在jdk1.4和1.5下都可以用。
0 请登录后投票
   发表时间:2006-07-17  
计划0.5版起初步支持hibernate
0 请登录后投票
   发表时间: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打印出来,方便大家调试跟踪。
0 请登录后投票
   发表时间:2007-05-14  
原先计划0.5版起初步支持hibernate版的,现在想还是先把ibatis版先做做好
0 请登录后投票
   发表时间: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)得话要如何实现?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics