论坛首页 Java企业应用论坛

回复:《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》

浏览 4938 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-02-07  
 

前几天我写了《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》。昨天和几个朋友讨论问题的时候,谈到通过DaoSupport封装spring-hibernate的时候,是不是需要提供springhibernate的所有方法的封装,我认为不可。为什么呢?

1、分层的概念

springhibernate的封装就是最好的明证。比较spingHibernateTemplatehibernatesession我们不难发现,session中的许多方法在HibernateTemplate中都没有,也就是说,spring在封装hibernate的时候,并不是将hibernate的所有方法都提供对应的方法给spring的用户。比如,springHibernateTemplate不提供所有hibernatesession中与connection有关的方法,也不提供所有session中与criteriatrasaction有关的方法。Spring为什么不提供这些方法呢?并不是spring不能提供这些方法,而是spring在封装hibernate的时候对更多的关于hibernate进行持久化的这个复杂过程进行了屏蔽,许多在这个过程中的技术细节被进一步封装。当我们在使用spring的封装的时候,就不应当再去考虑hibernate在进行持久化的一些技术细节,因为这已经不是这个层次应当考虑的问题了,或者说这些问题在这个层次上已经透明了。这里就提到了“分层”的概念。这种分层的概念就如同我们的网络分层。众所周知,在网络7层结构中,数据链路层处理的是点对点的通讯传输,它不需要考虑我的通讯传送在什么介质中,这些技术细节是物理层需要考虑的问题。如果一个通讯工程师在设计数据链路层的时候还需要考虑介质的问题,这就不是好的设计。如果在实际设计中真的出现这样的情况,他应当考虑他的设计是不是应当分解,哪部分应当分解到物理层实现,哪部分应当在数据链路层去调用物理层的东西。

2、我们的分层结构

我们的软件设计也一样,在这里我们不妨分为hibernatespringDaoSupport以及那些Daos四个层次。Hibernate是对JDBC的封装,spring是对Hibernate的封装。当spring在封装hibernate的时候,是不是已经把hibernate的一些技术细节屏蔽。比如,它不再考虑对上层客户提供sessionconneciontrasaction了(HibernateTemplate虽然提供了getSession方法,但我们在使用HibernateTemplate通常不会通过getSession得到session以后对session做任何操作,而是在execute方法的内部实现类中使用session)。CritariaQuery也没有提供,甚至没有任何一个方法接受SQLHQL(你只能在execute方法的内部实现类中使用CritariaQuerySQLHQL),因为DAO的思想就是通过对象来处理我们的数据持久化问题。所幸的是,现在hibernate正在向着这方面发展,增删改操作就不必说了,就是关联查询也可以通过值对象的一对一、一对多、多对多关联方便快捷地进行查询。不夸张的说, springHibernateTemplate中的常用方法,就可以完成我们90%的工作(除了那些复杂的查询和统计)。

3DaoSupport的封装

DaoSupport是对spring的封装,也就是在springHibernateTemplate的基础上做进一步封装。DaoSupport在封装的时候也不需要将HibernateTemplate的所以方法都封装一遍,而是仅仅对常用的方法进行封装,而对于不常用的甚至有可能屏弃的方法不用封装。这样做既可以保证我们的系统结构清晰明了,避免过度设计,又可以保证我们的系统可以在spring的各个版本之间自由切换,增加兼容性。这样做还有一个重要意义在于,它使我们的开发变得简单快捷,我们不再沉溺于springhibernate的许多技术问题。我们可以节省出设计DAO的大量时间和精力,更多地去考虑BUS的这种业务逻辑。

以下是我运用这样的体系设计的一个具体的DAO实现的例子,在这个实现中我们完全看不到spring和hibernate的影子,实现也变得非常简单明了:

java 代码

  1. package com.htxx.thps.psb.dao.imp;   
  2.   
  3. import com.htxx.service.dao.BasicDao;   
  4. import com.htxx.service.dao.Condition;   
  5. import com.htxx.service.dao.ResultSet;   
  6. import com.htxx.thps.model.PsPsb;   
  7. import com.htxx.thps.model.PsPsjcd;   
  8. import com.htxx.thps.model.PsWtmx;   
  9. import com.htxx.thps.psb.dao.PsbDao;   
  10.   
  11. /**  
  12.  * @author FanGang  
  13.  *  
  14.  */  
  15. public class PsbDaoImp extends BasicDao implements PsbDao {   
  16.   
  17.     /* (non-Javadoc)  
  18.      * @see com.htxx.thps.psb.dao.PsbDao#getPsb(java.lang.String)  
  19.      */  
  20.     public PsPsb getPsb(String id) {   
  21.         return (PsPsb)this.load(PsPsb.class, id);   
  22.     }   
  23.   
  24.     /* (non-Javadoc)  
  25.      * @see com.htxx.thps.psb.dao.PsbDao#updatePsb(com.htxx.thps.model.PsPsb)  
  26.      */  
  27.     public void updatePsb(PsPsb vo) {   
  28.         this.update(vo);   
  29.     }   
  30.   
  31.     /* (non-Javadoc)  
  32.      * @see com.htxx.thps.psb.dao.PsbDao#getPsb(com.htxx.service.dao.Condition)  
  33.      */  
  34.     public ResultSet getPsb(Condition condition) {   
  35.         return this.query("PsPsb", condition);   
  36.     }   
  37.   
  38.     public PsPsjcd getPsjcd(String id) {   
  39.         return (PsPsjcd)this.load(PsPsjcd.class, id);   
  40.     }   
  41.   
  42.     public ResultSet getPsjcd(Condition condition) {   
  43.         return this.query("PsPsjcd", condition);   
  44.     }   
  45.   
  46.     public PsWtmx getWtmx(String id) {   
  47.         return (PsWtmx)this.load(PsWtmx.class, id);   
  48.     }   
  49.   
  50.     public ResultSet getWtmx(Condition condition) {   
  51.         return this.query("PsWtmx", condition);   
  52.     }   
  53.   
  54.     public void updatePsjcd(PsPsjcd vo) {   
  55.         this.update(vo);   
  56.     }   
  57.   
  58.     public void updateWtmx(PsWtmx vo) {   
  59.         this.update(vo);   
  60.     }   
  61.   
  62. }  
4
DaoSupport的适应范围

DaoSupport是对spring的封装,spring是对hibernate的封装。从整个体系结构我们不难得出结论,DaoSupport只适用于采用DAO的方式进行数据持久化的应用。其它非DAO的应用,比如使用JDBC直接执行SQL,或者执行创建数据库、创建表空间等操作,都不在DaoSupport的适用范围内。

5、如何解决其它问题

但是,我们的开发肯定会遇到使用DaoSupport解决不了的问题,比如我要执行复杂的查询,我要使用SQLHQL。当我们需要使用SQLHQL,甚至我们还要使用session执行一些操作的时候,我们的代码就应当处于我们体系结构的spring同级甚至更低的层次结构上了,就不应当使用DaoSupport,而是根据所写的代码将其放到合理的层次上实现。有的代码可能还会跨越多个层次。比如如果我要使用许多Oracle独有的函数实现一个功能,这些方法可以应用在Oracle数据库中,却不能应用在其它数据库中,那么我是不是应当有一个不考虑具体数据库的应用层以及它对这种数据库的实现层。有的问题不在DaoSupport的应用范围,比如我们使用JDBC直接执行SQL语句,显然不在范围之内,是不是应当把它交给与DaoSupport在同一层次的JDBCSupport,封装springJdbcTemplate

 

总之,DaoSupport是对springHibernateTemplate的封装(假如我们采用spring+hibernate的技术框架),它适用于采用DAO的方式进行数据持久化的应用,解决的是采用继承的方式带来的对springhibernate具体技术框架的依赖。我在《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》中已经给出了这个结构的一个实现,供大家参考。

 

  • 大小: 61.4 KB
   发表时间:2007-02-08  
概念通俗易懂!但是对低偶合的说明似乎不够充分!

我认为Spring 的DaoSupport和HibernateTemplate之间是高偶合的。这么做只是为了简化Dao设计和有针对性锐化s+h的架构!

s的低偶合是体现在结构分层上! 比如 有针对的对Hibernate,JDO提供了接口,对于其他的持久层也可以通过jca注入。web mid, bus都有明显的逻辑上的区分!
0 请登录后投票
   发表时间:2007-02-08  
也许retreat朋友可以看看我的《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》,在这里面我详细描述了我的设计。在这个结构中,DaoSupport是一个接口,它有具体的实现,比如DaoSupportHibernate3Imp,而Daos也不是直接使用DaoSupport,而是通过基础类BasicDao使用DaoSupport。如此结构使得spring的HibernateTemplate与Daos解耦。
0 请登录后投票
论坛首页 Java企业应用版

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