回复:《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》
关键字: struts spring hibernate 软件工程 敏捷开发前几天我写了《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》。昨天和几个朋友讨论问题的时候,谈到通过DaoSupport封装spring-hibernate的时候,是不是需要提供spring和hibernate的所有方法的封装,我认为不可。为什么呢?
1、分层的概念
spring对hibernate的封装就是最好的明证。比较sping的HibernateTemplate和hibernate的session我们不难发现,session中的许多方法在HibernateTemplate中都没有,也就是说,spring在封装hibernate的时候,并不是将hibernate的所有方法都提供对应的方法给spring的用户。比如,spring的HibernateTemplate不提供所有hibernate的session中与connection有关的方法,也不提供所有session中与criteria、trasaction有关的方法。Spring为什么不提供这些方法呢?并不是spring不能提供这些方法,而是spring在封装hibernate的时候对更多的关于hibernate进行持久化的这个复杂过程进行了屏蔽,许多在这个过程中的技术细节被进一步封装。当我们在使用spring的封装的时候,就不应当再去考虑hibernate在进行持久化的一些技术细节,因为这已经不是这个层次应当考虑的问题了,或者说这些问题在这个层次上已经透明了。这里就提到了“分层”的概念。这种分层的概念就如同我们的网络分层。众所周知,在网络7层结构中,数据链路层处理的是点对点的通讯传输,它不需要考虑我的通讯传送在什么介质中,这些技术细节是物理层需要考虑的问题。如果一个通讯工程师在设计数据链路层的时候还需要考虑介质的问题,这就不是好的设计。如果在实际设计中真的出现这样的情况,他应当考虑他的设计是不是应当分解,哪部分应当分解到物理层实现,哪部分应当在数据链路层去调用物理层的东西。
2、我们的分层结构
我们的软件设计也一样,在这里我们不妨分为hibernate、spring、DaoSupport以及那些Daos四个层次。Hibernate是对JDBC的封装,spring是对Hibernate的封装。当spring在封装hibernate的时候,是不是已经把hibernate的一些技术细节屏蔽。比如,它不再考虑对上层客户提供session、connecion、trasaction了(HibernateTemplate虽然提供了getSession方法,但我们在使用HibernateTemplate通常不会通过getSession得到session以后对session做任何操作,而是在execute方法的内部实现类中使用session)。Critaria和Query也没有提供,甚至没有任何一个方法接受SQL和HQL(你只能在execute方法的内部实现类中使用Critaria、Query、SQL、HQL),因为DAO的思想就是通过对象来处理我们的数据持久化问题。所幸的是,现在hibernate正在向着这方面发展,增删改操作就不必说了,就是关联查询也可以通过值对象的一对一、一对多、多对多关联方便快捷地进行查询。不夸张的说, spring的HibernateTemplate中的常用方法,就可以完成我们90%的工作(除了那些复杂的查询和统计)。
3、DaoSupport的封装
DaoSupport是对spring的封装,也就是在spring的HibernateTemplate的基础上做进一步封装。DaoSupport在封装的时候也不需要将HibernateTemplate的所以方法都封装一遍,而是仅仅对常用的方法进行封装,而对于不常用的甚至有可能屏弃的方法不用封装。这样做既可以保证我们的系统结构清晰明了,避免过度设计,又可以保证我们的系统可以在spring的各个版本之间自由切换,增加兼容性。这样做还有一个重要意义在于,它使我们的开发变得简单快捷,我们不再沉溺于spring和hibernate的许多技术问题。我们可以节省出设计DAO的大量时间和精力,更多地去考虑BUS的这种业务逻辑。
以下是我运用这样的体系设计的一个具体的DAO实现的例子,在这个实现中我们完全看不到spring和hibernate的影子,实现也变得非常简单明了:
- package com.htxx.thps.psb.dao.imp;
-
- import com.htxx.service.dao.BasicDao;
- import com.htxx.service.dao.Condition;
- import com.htxx.service.dao.ResultSet;
- import com.htxx.thps.model.PsPsb;
- import com.htxx.thps.model.PsPsjcd;
- import com.htxx.thps.model.PsWtmx;
- import com.htxx.thps.psb.dao.PsbDao;
-
- /**
- * @author FanGang
- *
- */
- public class PsbDaoImp extends BasicDao implements PsbDao {
-
- /* (non-Javadoc)
- * @see com.htxx.thps.psb.dao.PsbDao#getPsb(java.lang.String)
- */
- public PsPsb getPsb(String id) {
- return (PsPsb)this.load(PsPsb.class, id);
- }
-
- /* (non-Javadoc)
- * @see com.htxx.thps.psb.dao.PsbDao#updatePsb(com.htxx.thps.model.PsPsb)
- */
- public void updatePsb(PsPsb vo) {
- this.update(vo);
- }
-
- /* (non-Javadoc)
- * @see com.htxx.thps.psb.dao.PsbDao#getPsb(com.htxx.service.dao.Condition)
- */
- public ResultSet getPsb(Condition condition) {
- return this.query("PsPsb", condition);
- }
-
- public PsPsjcd getPsjcd(String id) {
- return (PsPsjcd)this.load(PsPsjcd.class, id);
- }
-
- public ResultSet getPsjcd(Condition condition) {
- return this.query("PsPsjcd", condition);
- }
-
- public PsWtmx getWtmx(String id) {
- return (PsWtmx)this.load(PsWtmx.class, id);
- }
-
- public ResultSet getWtmx(Condition condition) {
- return this.query("PsWtmx", condition);
- }
-
- public void updatePsjcd(PsPsjcd vo) {
- this.update(vo);
- }
-
- public void updateWtmx(PsWtmx vo) {
- this.update(vo);
- }
-
- }
4、DaoSupport的适应范围
- package com.htxx.thps.psb.dao.imp;
- import com.htxx.service.dao.BasicDao;
- import com.htxx.service.dao.Condition;
- import com.htxx.service.dao.ResultSet;
- import com.htxx.thps.model.PsPsb;
- import com.htxx.thps.model.PsPsjcd;
- import com.htxx.thps.model.PsWtmx;
- import com.htxx.thps.psb.dao.PsbDao;
- /**
- * @author FanGang
- *
- */
- public class PsbDaoImp extends BasicDao implements PsbDao {
- /* (non-Javadoc)
- * @see com.htxx.thps.psb.dao.PsbDao#getPsb(java.lang.String)
- */
- public PsPsb getPsb(String id) {
- return (PsPsb)this.load(PsPsb.class, id);
- }
- /* (non-Javadoc)
- * @see com.htxx.thps.psb.dao.PsbDao#updatePsb(com.htxx.thps.model.PsPsb)
- */
- public void updatePsb(PsPsb vo) {
- this.update(vo);
- }
- /* (non-Javadoc)
- * @see com.htxx.thps.psb.dao.PsbDao#getPsb(com.htxx.service.dao.Condition)
- */
- public ResultSet getPsb(Condition condition) {
- return this.query("PsPsb", condition);
- }
- public PsPsjcd getPsjcd(String id) {
- return (PsPsjcd)this.load(PsPsjcd.class, id);
- }
- public ResultSet getPsjcd(Condition condition) {
- return this.query("PsPsjcd", condition);
- }
- public PsWtmx getWtmx(String id) {
- return (PsWtmx)this.load(PsWtmx.class, id);
- }
- public ResultSet getWtmx(Condition condition) {
- return this.query("PsWtmx", condition);
- }
- public void updatePsjcd(PsPsjcd vo) {
- this.update(vo);
- }
- public void updateWtmx(PsWtmx vo) {
- this.update(vo);
- }
- }
DaoSupport是对spring的封装,spring是对hibernate的封装。从整个体系结构我们不难得出结论,DaoSupport只适用于采用DAO的方式进行数据持久化的应用。其它非DAO的应用,比如使用JDBC直接执行SQL,或者执行创建数据库、创建表空间等操作,都不在DaoSupport的适用范围内。
5、如何解决其它问题
但是,我们的开发肯定会遇到使用DaoSupport解决不了的问题,比如我要执行复杂的查询,我要使用SQL和HQL。当我们需要使用SQL和HQL,甚至我们还要使用session执行一些操作的时候,我们的代码就应当处于我们体系结构的spring同级甚至更低的层次结构上了,就不应当使用DaoSupport,而是根据所写的代码将其放到合理的层次上实现。有的代码可能还会跨越多个层次。比如如果我要使用许多Oracle独有的函数实现一个功能,这些方法可以应用在Oracle数据库中,却不能应用在其它数据库中,那么我是不是应当有一个不考虑具体数据库的应用层以及它对这种数据库的实现层。有的问题不在DaoSupport的应用范围,比如我们使用JDBC直接执行SQL语句,显然不在范围之内,是不是应当把它交给与DaoSupport在同一层次的JDBCSupport,封装spring的JdbcTemplate。
总之,DaoSupport是对spring的HibernateTemplate的封装(假如我们采用spring+hibernate的技术框架),它适用于采用DAO的方式进行数据持久化的应用,解决的是采用继承的方式带来的对spring和hibernate具体技术框架的依赖。我在《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》中已经给出了这个结构的一个实现,供大家参考。
- 10:18
- 浏览 (2781)
- 论坛浏览 (2597)
- 评论 (2)
- 分类: spring&hibernate
- 相关推荐
评论
发表评论
该博客是同时发布到论坛的,无法评论在论坛已被锁定的帖子
我的相册
共 4 张
最近加入圈子
最新评论
-
DWR帮助说明-如何编写通 ...
非常遗憾,我们示例中的部门是可以分页的,但员工的分页打错了个字:将initCon ...
-- by fangang -
DWR帮助说明-如何编写通 ...
请详细说说分页实现的过程,我的数据结果集查回来了,但列出的是表中全部数据有35条 ...
-- by jiaweidong_2008 -
再析在spring框架中解决多 ...
楼主这个用来动态切换数据库是可以的,如果是这样一个场景那:用户登录后,会显示一个 ...
-- by javachs -
一个dwr+spring+hibernate ...
正在整理dwr的东西,有时间与lz交流
-- by lengyue -
再析在spring框架中解决多 ...
楼主你的这个解决方案可以说是动态的切换数据源而已!
-- by jayxu







评论排行榜