论坛首页 Java企业应用论坛

Tapestry+Spring+Hibernate整合工作小结

浏览 23276 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-04-13  
事务代码尽量不要手动写,用Spring Aop的事务声明
就可以了.Spring的事务声明类试与ejb的,
有PROPAGATION_REQUIRED/
PROPAGATION_NEW等等,可以解决你的问题。
把Tx手动写到ThreadLocal里头我以前干过的,
会造成相互调用的困扰,比如别人已经写好了
addCost方法,他自己测试了正常,必然需要
在他的代码边界加上Tx begin/Tx commit,
可是我要是要调用他的代码,就会造成我的麻烦。
我们当时的解决方案是给Tx作一个WrapperTx
tx.begin代码
depth++;
            if (depth == 1) {
                tx.begin();
            }
tx.commit代码
depth--;
            if (depth == 0) {
                tx.commit();
            }
这样我外面的代码可以包他的代码,可是还是麻烦也不Elegant,
还是用aop解决的好。
0 请登录后投票
   发表时间:2004-04-13  
只提一点关于DAO的,它有存在的必要,特别在一些用文件做临时数据库的时候.......而不会因为Hibernate的存在而可以不要了,甚至还有基于内存的数据库

只能说,可以根据项目的实际情况而定,其实用了Spring,就算用了DAO,也不过多了一个接口,一个配置文件而已,但却可以带来更多的灵活
0 请登录后投票
   发表时间:2004-04-13  
robbin 写道
引用
那么我习惯把,abcde五个方法都写道DAO当中。
否则的话,重复的代码会比较多。


这些DAO也可以是Service。所以不会存在你说的重复代码的问题。

确实也可以看作service,除开你的各个Service之间没有代码重复,否则就要重写代码。我所遇到的各个service之间是有部分代码重复的。


robbin 写道

引用
事务中的方法需要递归调用,因为事务不能嵌套,所以不能service中的方法,递归调用自己-否则事务将嵌套。而被递归调用的方法必须写在dao层。


我觉得你这种做法实际上仍然有问题,因为很有可能出现Service调用其他几个Service的嵌套调用,那么仍然会出现你说的事务嵌套问题。解决办法就是把Transaction也放到ThreadLocal里面,向对待Session那样去处理,那么整个世界都清静了。


我就是为了避免避免service的嵌套调用,才搞DAO的,如果要嵌套,就在DAO中嵌套。

如果把tx放到threadlocal,这样有点违背了“事务”的原意,事务本来指一个“全有或者全无”的操作,代表一个业务动作的完成。然而,一个线程当中,我可能要完成几项业务,而这些业务之间并不要求“要么都完成,要么都不完成”。
0 请登录后投票
   发表时间:2004-04-13  
引用
如果把tx放到threadlocal,这样有点违背了“事务”的原意,事务本来指一个“全有或者全无”的操作,代表一个业务动作的完成。然而,一个线程当中,我可能要完成几项业务,而这些业务之间并不要求“要么都完成,要么都不完成”。


当然不会咯。你一样可以在一个线程里面提交多次,切分出来好几个事务。

不过看起来手工方式还是没有上面描述的Spring控制方式优雅,我也倾向于Spring了。
0 请登录后投票
   发表时间:2004-04-14  
just some quick reply, too tired today.

Quake Wang:

我们为每个entity自动生成对应的dao, 这样客户代码不需要cast.
对于查询的处理和你是一样的.
关于修改hardcode的属性名,有一个小tip:
把要更改的属性改为public, 然后用refactor的rename, IDEA自动修改字符串中的属性名(我们用的是IDEA).

我不明白为什么你认为从spring获得action listener要比在page class中直接实现listener方法要好? 我今天做了一个小例子, 完全可以从spring中得到action listener, 因为Tapestry的listener只是一个实现了IActionListener接口的对象而已. 这样作的结果是每一个action都要写一个类, 还要编辑相应的spring配置文件, 而且并不优于直接在page class中实现listener方法, 在page文件中配置navigation. (公司的邮件出了问题, 代码没有发回家, 只好明天详细说明了)

关于权限验证, 我想说明的是secure by hidding will not work! Service中的权限检查是必须的。

robbin的权限检查对我很有启发,我们可以作一个aop,检查访问Service方法的用户(登录用户用ThreadLocal保存)有没有足够的权限。 方法和权限的对应可以是放在配置文件中,也可以是放在数据库中。方法和权限的对应关系则是灵活的,即可以是不同方法对应不同权限,也可以是同一个Service的所有方法对应同一个权限,甚至一个方法的对应多个权限值,这些权限值之间是and或者or的关系。这样就足够灵活了。

其实在我们的架构里,service的方法对应着用例中的一步业务操作,是unit of work,也是事务处理的自然边界。使用Spring的Declarative Transaction Management,可以很优雅地处理事务,包括事务嵌套的问题。

dao对于service来说就是一个处理数据存储的helper类,基于speration of concern的原则,使用dao还是很有好处的,而且Spring对Hibernate DAO的支持非常之好,用了它之后很多数据访问都只是简单的一行代码,并且它会把HibernateException转化成一组定义得非常清晰的RuntimeException(因为数据库异常基本上是Service层无法恢复的),极大地简化异常处理。

工具问题是一件让我非常郁闷的事。我们对IDEA非常熟悉,也非常喜欢,但是IDEA没有想Spindle那样的插件,许多typo要在deploy之后才能发现,幸好Tapestry的错误提示信息异常的详细,甚至精确到某一行某一列,要不然我们就死定了:( 我们项目组没有熟悉Eclipse的成员,项目进展到这个时侯更换开发工具也是不现实的。或许等我有时间了,也作一个IDEA的Spindle:)
0 请登录后投票
   发表时间:2004-04-14  
magician 写道
只提一点关于DAO的,它有存在的必要,特别在一些用文件做临时数据库的时候.......而不会因为Hibernate的存在而可以不要了,甚至还有基于内存的数据库

只能说,可以根据项目的实际情况而定,其实用了Spring,就算用了DAO,也不过多了一个接口,一个配置文件而已,但却可以带来更多的灵活


呵呵,你说的很对,使用DAO的一个很大的好处就是我可以很方便地使用mockDAO代替真正的DAO,这样在单元测试和没有数据库连接的时侯,就会非常方便(前天我在给同事培训的时侯就没有数据库,直接使用mockDAO,一点问题没有)。而且mock和real之间的转换只需要修改一下Spring的配置文件即可,thanks to IOC。
0 请登录后投票
   发表时间:2004-04-14  
cyberwing 写道

我们为每个entity自动生成对应的dao, 这样客户代码不需要cast.
对于查询的处理和你是一样的.
关于修改hardcode的属性名,有一个小tip:
把要更改的属性改为public, 然后用refactor的rename, IDEA自动修改字符串中的属性名(我们用的是IDEA).

嗯, 确实要多写cast的问题. 我从别人的代码看都是一个Entity对应一个自己的DAO, 但是这些DAO的create, update, delete代码又都是很类似的, 所以才会考虑用单个的DAO. 分开除了不用cast以外, 不知道还有没有其他好处.

关于属性的hardcode, Robbin也和我说过这个tip了, 可以用Eclipse的refactor功能, 让eclipse查找所有对应的字符串, , Thanks!

cyberwing 写道

我不明白为什么你认为从spring获得action listener要比在page class中直接实现listener方法要好? 我今天做了一个小例子, 完全可以从spring中得到action listener, 因为Tapestry的listener只是一个实现了IActionListener接口的对象而已. 这样作的结果是每一个action都要写一个类, 还要编辑相应的spring配置文件, 而且并不优于直接在page class中实现listener方法, 在page文件中配置navigation. (公司的邮件出了问题, 代码没有发回家, 只好明天详细说明了)

我的意思是把所有Tapestry Page对象都纳入Spring管理, 而不是直接再写一个类. 这样做的好处是, 由于Page上每个listener method签名都是一样的: void abc(IRequestCycle cycle), 我们很容易就能够做拦截了, 利用AOP来做dirty job(Exception 处理, hit log等等). 但是由于Tapestry Page Listener的概念和Webwork, Structs的Action概念完全不一样, 随着对Tapestry的了解增多, 我发现可以用它良好的OO设计来解决, 比如重载Engine的activateExceptionPage方法做exception处理, 重载setupForRequest和cleanupAfterRequest做hit log, 不一定要赶AOP的时髦,. 准备等对AOP了解再多一些了, 再考虑这些问题.

Spring封装的DAO和事务处理真的非常cool, 确实极大方便了开发. 再回头看看以前自己写的工具代码方法, 不免有一种遗憾: Spring早点出来就好了.

cyberwing 写道

工具问题是一件让我非常郁闷的事。我们对IDEA非常熟悉,也非常喜欢,但是IDEA没有想Spindle那样的插件,许多typo要在deploy之后才能发现,幸好Tapestry的错误提示信息异常的详细,甚至精确到某一行某一列,要不然我们就死定了:( 我们项目组没有熟悉Eclipse的成员,项目进展到这个时侯更换开发工具也是不现实的。或许等我有时间了,也作一个IDEA的Spindle:)

很遗憾你们没有用Spindle, 它不仅仅解决typo的问题, 它的提示功能, 还免去了我查询component reference的烦恼. Create Page生成所有相关文件的功能非常体贴. IDEA的Spindle? plugin 开发好烦......, good luck!

另外问个问题, 有谁可以订阅Tapestry的邮件吗? 我发给它的订阅email地址都是time out, 无法送达, 不知道是什么原因.
0 请登录后投票
   发表时间:2004-04-14  
cyberwing 写道

工具问题是一件让我非常郁闷的事。我们对IDEA非常熟悉,也非常喜欢,但是IDEA没有想Spindle那样的插件,许多typo要在deploy之后才能发现,幸好Tapestry的错误提示信息异常的详细,甚至精确到某一行某一列,要不然我们就死定了:( 我们项目组没有熟悉Eclipse的成员,项目进展到这个时侯更换开发工具也是不现实的。或许等我有时间了,也作一个IDEA的Spindle:)

不会阿?Idea的xml支持很好的阿,在xml里头也会有很多自动完成/自动提示的,还有对xml的校验功能,按右键在弹出的快捷菜单里头选Validate就可以了
可以发现比如一个引用了Id为TestBean,而该Bean声明中错写为Tes?ean这样子的错误。
至于Idea对xml的自动完成/自动提示,需要取得该xml对应的dtd/schema,
如果Idea没有取得对应的dtd/schema,在开头xml开头的dtd引用会标红,比如http://www.springframework.org/dtd/spring-beans.dtd标红,你在
这里按Alter+Enter,他会问你要不要取该Resource,你选确定就ok了。
对于dtl声明只是网址类型,比如
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
这样的,你在配置的Resources里头Configure External Resources:
URI填http://java.sun.com/jstl/core,Path填你把那个dtd/tld拷贝到
本机的目录,他就找得到了。
我很喜欢Idea的,Idea的自己本身的Code 智能就作的很强大了,不过专门
针对Tapestry开发的Spindle的其他功能那Idea就可能没有了,所以打算玩玩Eclipse了~,研究研究
0 请登录后投票
   发表时间:2004-04-14  
Quake Wang 写道
我的意思是把所有Tapestry Page对象都纳入Spring管理, 而不是直接再写一个类. 这样做的好处是, 由于Page上每个listener method签名都是一样的: void abc(IRequestCycle cycle), 我们很容易就能够做拦截了, 利用AOP来做dirty job(Exception 处理, hit log等等). 但是由于Tapestry Page Listener的概念和Webwork, Structs的Action概念完全不一样, 随着对Tapestry的了解增多, 我发现可以用它良好的OO设计来解决, 比如重载Engine的activateExceptionPage方法做exception处理, 重载setupForRequest和cleanupAfterRequest做hit log, 不一定要赶AOP的时髦,. 准备等对AOP了解再多一些了, 再考虑这些问题.


原来你是这个意思阿,还得我瞎忙了半天。不过也是有收获的,感觉基于action或是command模式的事件处理方法不如Tapestry这样把页面数据和事件处理方法放在同一个类中方便、自然。

关于hit log,看看Tapestry的IMoniter接口,就是用来做这个的。在没有使用OpenSessionInView时,还有人用IMoniter来管理Hibernate的Session.

Quake Wang 写道
另外问个问题, 有谁可以订阅Tapestry的邮件吗? 我发给它的订阅email地址都是time out, 无法送达, 不知道是什么原因.

国内的信箱好像都不行,Yahoo和hotmail的帐号可以,网上也有use list的archiver阿。
0 请登录后投票
   发表时间:2004-04-14  
femto 写道

不会阿?Idea的xml支持很好的阿,在xml里头也会有很多自动完成/自动提示的,还有对xml的校验功能,按右键在弹出的快捷菜单里头选Validate就可以了
可以发现比如一个引用了Id为TestBean,而该Bean声明中错写为Tes?ean这样子的错误。
至于Idea对xml的自动完成/自动提示,需要取得该xml对应的dtd/schema,
如果Idea没有取得对应的dtd/schema,在开头xml开头的dtd引用会标红,比如http://www.springframework.org/dtd/spring-beans.dtd标红,你在
这里按Alter+Enter,他会问你要不要取该Resource,你选确定就ok了。
对于dtl声明只是网址类型,比如
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
这样的,你在配置的Resources里头Configure External Resources:
URI填http://java.sun.com/jstl/core,Path填你把那个dtd/tld拷贝到
本机的目录,他就找得到了。
我很喜欢Idea的,Idea的自己本身的Code 智能就作的很强大了,不过专门
针对Tapestry开发的Spindle的其他功能那Idea就可能没有了,所以打算玩玩Eclipse了~,研究研究


呵呵,这些我都知道阿,我也觉得IDEA对XML文件编辑的支持要比Eclipse的强n倍(当然是指Eclipse基本的XML编辑支持)。但是它不能作到Tapestry aware。比如在定义component的时侯,它能自动发现有binding,static-binding, inherited-binding等等元素可用,但是它并不知道对应的component有那些参数可以设置,它不能提供name属性的可选值。

还有就是HTML中定义的component的jwcid和.page文件中定义的name,如果一不小心敲错了,两个不一致,这样的问题就只有在运行时才能发现了。而Spindle可以在build time就发现这种错误,可以节省相当多的时间和精力。
0 请登录后投票
论坛首页 Java企业应用版

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