代码改变世界

软件架构乱谈—SSH框架

2011-05-11 04:24  hyddd  阅读(9144)  评论(21编辑  收藏  举报

    不废话,直入主题。SSH框架(Struts + Spring + Hibernate)不用介绍,相信大家非常熟悉了。许多使用SSH进行开发java项目在开发效率和效果上都非常不错,但同时也有人质疑SSH中的Hibernate,指责其速度较慢。但今天,我想从另外一个角度谈谈我对Hibernate的看法,欢迎怕砖:)

    Hibernate是一个ORM框架,主要处理ER(Entity-Relation)的问题。而Hibernate的本质,我认为有2点:

(1). 一个严格满足数据库3范式的框架。

(2). 一个自动化的DML的框架。

 

1. 下面是一个我遇到过的真实应用场景,大家可以参考一下:

        Category(分类)与Goods(商品),Category与Goods是一对多的关系,一个Category分类下可以有多个Goods,一个Goods只能属于一个Category。

    由于Category和Goods的关系,我们在实施的时候马上会碰到这样几个问题(这里先不考虑Hibernate自身的性能问题,因为它可以通过缓存解决。):

(1). Category对象中是否应该有一个Goods List呢?

(2). Goods对象中是应该否有一个Category对象?

……恩,在这种场景下,重点关注点应该是Goods(因为Goods的数量肯定远远大于Category),我的答案是:如果Goods数量不多的情况下, 这样做完全没问题,并且利用 Hibernate的特性我可以很轻易做到这一点,同时在使用Goods和Category的时候也方便。

    但如果在(中,大型系统中)Goods数量较多时,(1)的做法就显然有问题了。同时,(2)的做法也有一些问题,比如:如果Goods对象中存有了一个Category对象,那它是否需要把Type(商品类型)对象,Brand(商品品牌)对象……等等存于Goods对象中呢?等等,这样搞显然不行!那么,你现在应该会马上想到以下方案:

(3). Goods对象中存放category_id。

    恩,你的想法是对的。这里多数人的做法是:Goods表存放category_id,category_name,把category_name作为冗余存在Goods里面

    OK,到这里你发现Hibernate一个很重要的特性(对象关联)在这里用不上了。

 

2. 下面是另外一个问题:你认为在系统中很麻烦,但又经常会遇到的数据库操作是什么呢?

    应该是联表查询/联表操作,特别是中,大型系统,这种问题会经常遇到!显然,Hibernate对此问题都表示无能为力~~

 

3. 总结

    其实,以上两个问题都可以看作是:无法应用3范式的特征/不具备3范式特征,导致Hibernate功能大打折扣,这也和我之前提到的Hibernate本质有关。

    鉴于以上问题,Hibernate在中,大型系统中并不一定能带来多少好处,再加上性能的问题,所以在选用框架前一定要反复权衡!

    WEB应用中,Hibernate多数情况下会用在小型项目。而在ERP中,多数的小,中型项目会应用Hibernate(一般的ERP项目的数据库设计都严格按照范式进行),但大型ERP则一般不用Hibernate,这又涉及到另外一个问题,大型ERP项目数据模型可能有几百个,他们间关系复杂,要修改某个模型影响很大,非常痛苦!所以大型ERP项目多数采用MDA(Model-driven architecture)的方式,统一抽象模型层,他们用统一的接口进行数据查询,如:

 

    Map = Db.find(“Goods”,map{“name”,”id”,”price”};

 

其中代表作有:Ofbiz,用友U9……