论坛首页 Java企业应用论坛

谈谈应用ORM框架针对遗留数据库做模型设计的一些技巧。

浏览 3461 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-12-30  
很多项目的开发都是基于已有数据库做开发的。遗留数据库的存在增加了java模型和数据模型之间的障碍。
很多朋友为此是否选择hibernate或者别的Jdbc wrapper的开发框架而犹豫不决。

其实,用hibernate类似的orm工具总归是明智的选择,当然不是唯一的明智的选择,我写这篇文章只是希望能够给那些还在犹豫不决的人提供一些自信的力量,可以果断的作出自己的决定。

有一个朋友询问过针对遗留系统做模型设计的问题 。很难简单回答这个问题,但是我可以提供我的一些经验,同时也把这篇帖子作为对那位朋友的一个完整的回答,希望能顾对他有所帮助。


针对统一的业务逻辑,对 业务模型,DAO/Service 分别设计精巧的的继承体系
          很多朋友对此抱很谨慎的态度,因为他们觉得遗留系统很难有效支持业务模型的继承体系。
          他们的担心是有理的,而且通常情况下,遗留系统确实无法支持现有ORM的类继承体系。然而,遗留系统不支持,并不能阻碍我们在业务模型畅通无阻的使用类继承,达到DRY的目标。抽取出的抽象模型可以更容易实现DRY,同时这里面的业务模型的层次设计很多时候也是真正反映了“业务统一处理”的需求。
          这样的设计出现了很有意思的一个局面,业务模型是继承体系的模型,而数据模型是一对一映射的表模型,当用这种设计来处理业务的时候,特别是在处理“统一的抽象的业务逻辑”的时候,比支持继承模型的表模型 付出更多的一些努力才能达到,很多朋友一直担心这个“多付出”的努力是否会很可怕。 真的不用担心,并没有付出多少努力,你只需要在 DAO或者你的Service模块里面,做针对性的继承性的设计。通过这个合理的继承体系的DAO/Service模块,我们就可以在里面减少甚至完美弥补 因为 表模型不支持继承体系的业务模型带来的问题。

          一般来说,DAO/Service最好有这样的层次:

BaseService<----UserService,OrderService

class BaseService { update,create,delete,findById..} 


保证各个子类最终的CRUD都是通过 baseService.CRUD来完成 。

这样的DAO/Service类层次设计,为我们设计的业务模型的继承体系带来了“用武之地” ,在baseService的这个地方,大家可以把一些“需要统一处理的”业务逻辑放在此来做,比较有代表性的一点是 :

class abstract BaseService extends HibernateDAOSupport {

     public void create(Object o){
                 if(o instanceof PublishableModel){
                           publish((PublishableModel)o);
                  }
                 getHibernateTemplate().save(o);
    }

}

似乎很别扭但却很有“意义”的一段代码,PublishableModel这个抽象类代表了业务模型中某个可以统一处理的业务抽象模型,而 这段代码:
   if(o instanceof PublishableModel){
                           publish((PublishableModel)o);
                  }
 

给了这个业务模型抽象体系以真正发挥作用的“用武之地” 。


作为有经验的 开发人员,无论何时何地,都应该始终不渝的坚持并且贯彻“DRY”的宗旨。




   发表时间:2007-12-30  
引用
   1. class abstract BaseService extends HibernateDAOSupport { 
   2.  
   3.      public void create(Object o){ 
   4.                  if(o instanceof PublishableModel){ 
   5.                            publish((PublishableModel)o); 
   6.                   } 
   7.                  getHibernateTemplate().save(o); 
   8.     } 
   9.  
  10. } 

如果按照关联优先于继承的原则,上面代码显示出了优先使用继承的坏味道。:)
0 请登录后投票
   发表时间:2007-12-30  
nihongye 写道
引用
   1. class abstract BaseService extends HibernateDAOSupport { 
   2.  
   3.      public void create(Object o){ 
   4.                  if(o instanceof PublishableModel){ 
   5.                            publish((PublishableModel)o); 
   6.                   } 
   7.                  getHibernateTemplate().save(o); 
   8.     } 
   9.  
  10. } 

如果按照关联优先于继承的原则,上面代码显示出了优先使用继承的坏味道。:)


举个例子,比如遗留系统中的很多表都有一个 create_user,create_time两个字段,表示这个记录的创建者和创建时间 。 创建者表示 登录系统的用户 。

有很多种方式可以统一做这块的处理。 但是一个针对这个业务的继承还是很自然而然的出来了 :

abstract Class BaseEntity{
       User create_user;
       Date create_time
       

}

然后做统一处理的方式就很多了,比如我上面写的“蹩脚”的代码,也有的可能想到用拦截器的方式来做。
无所谓,可能后一种好一些,但是达到“统一有一个地方来处理相似的逻辑”这个目的(DRY)就行了,至于怎么达到,其实可以不用计较了。


我想说的就是类似这样的情况,不知道你说的“关联优先于继承”的观点从何而来? 呵呵
0 请登录后投票
   发表时间:2007-12-30  
单从上面那段示意性代码来说,子类还需要调用create()这个方法,所以可以将这个方法提取为一个工具类去啊。
0 请登录后投票
   发表时间:2007-12-30  
nihongye 写道
单从上面那段示意性代码来说,子类还需要调用create()这个方法,所以可以将这个方法提取为一个工具类去啊。

用继承比工具类更来得自然一些。

即使子类不调用 create() ,也要写这么长长的一行代码吧:

getHibernateTemplate().save(o) ;


用一个 create(o) 来替代这么一行代码,我想很多人都是乐意的吧。
0 请登录后投票
   发表时间:2007-12-30  
firebody 写道
nihongye 写道
单从上面那段示意性代码来说,子类还需要调用create()这个方法,所以可以将这个方法提取为一个工具类去啊。

用继承比工具类更来得自然一些。

即使子类不调用 create() ,也要写这么长长的一行代码吧:

getHibernateTemplate().save(o) ;


用一个 create(o) 来替代这么一行代码,我想很多人都是乐意的吧。

为了让一个长句变成一个短句(相当于别名法)而使用继承,绝对没必要。
但是你的主要观点service的继承体系,当然是赞同,呵呵。我觉得几十种模式该上的上,为了dry,但是技巧用多,用错的问题很让人头痛,该怎样抽象,有什么好的原则,觉得好难把握。
我觉得关键的一点,业务代码的组织跟数据的表示形式是完全分离的,无论数据是二维表还是对象,所以遗留系统也可以使用orm,也可以构造出相对比较好维护的业务处理代码来。
0 请登录后投票
   发表时间:2007-12-31  
我也经常会为了少写一些代码而使用继承,而不是用工具类,这样会在心里上有一种更直观的感觉,呵呵。

目前ORM应该可以适用于多数的遗留系统,将Service,DAO进行严格的区分,并合理设计层次,ORM能够发挥其很大的功效。不过有些遗留系统,有10w行以上的Store Procedure,这些Procedure经过长时间的考验和测试,包含了大量的逻辑,此时我们会采用比较plain的JDBC方案来处理,尽量不去破坏这些逻辑完整的Procedure。此时,可能就需要自己手工去做一些ORM的工作,而不采用比较popular的ORM工具。
0 请登录后投票
   发表时间:2008-04-12  
BaseService extends HibernateDAOSupport?Service缘何继承自DAO?
0 请登录后投票
论坛首页 Java企业应用版

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