`
jiming
  • 浏览: 274137 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

我为什么选择 iBatis 而不是 Hibernate(对于正在选型的人的建议)

    博客分类:
  • java
阅读更多
[注意]清在回复之前认真地看一下我的帖子,结合你的实际项目经验考虑一下,看看你是否能比较好地解决我所提出的Hibernate 的缺点。最好不要提一些大家都知道的泛泛的观点,这样会很浪费读者的时间并且分散大家的注意力。

非常感谢有几位对 hibernate 有深入了解的朋友给出了我这里提出的问题的 hibernate 解决方案。我提出这几个问题的初衷不是说 hibernate 无法实现这些功能。而是说他的实现比较不美,呵呵。比如说把一些 sql 嵌入到 java 代码中,我觉得这是非常不好的习惯。

v0.3 - 2007-1-1 21:1:1



我在最初的选型的时候是打算选择 Hibernate 的,在研究的过程中发现了 iBatis,经过
分析比较之后我选择了 iBatis。现在我已经使用 iBatis 完成了一个中小型的项目。这个
项目在性能、可维护性、可扩展性方面都非常令我满意。

在这个过程中我也不断的与使用过或者正在使用 Hibernate 的人进行过探讨。而且我本身
也在不断的跟进 Hibernate 的发展。

最终,我的结论是 iBatis 的选择非常正确,而且越用越喜欢它了。

当然了,我对 Hibernate 的理解还是非常有限的,所以这里的关于 Hibernate 的一些观
点的错误之处希望能够得到 Hibernate 高手的指正。


1. iBatis 易于掌握。拿来文档看半天到两天就可以掌握了。
   Hibernate 可能需要 3 倍以上的时间来掌握。
  
2. iBatis 更容易进行 sql 的 优化。

   这个应该大家都有共识了。另外 Hibernate 生成的 sql 也实在是太难看了。鉴
   于有的朋友提到了 sql 不太重要。我想在这里强调一下我的经验,一般系统性能
   的瓶颈都在数据库上。所以这一点是 iBatis 非常重要的一个优势。
  
3. iBatis 可以进行细粒度的优化

   3.1 比如说我有一个表,这个表有几个或者几十个字段,我需要更新其中
       的一个字段,iBatis 很简单,执行一个sql
       UPDATE TABLE_A SET column_1=#column_1# WHERE id=#id#
       但是用 Hibernate 的话就比较麻烦了,缺省的情况下 hibernate 会更新所有字段。
       当然我记得 hibernate 有一个选项可以控制只保存修改过的字段,但是我不太确
       定这个功能的负面效果。
      
   3.2 我需要列出一个表的部分内容,用 iBatis 的时候,这里面的好处是可以少从数据
     库读很多数据,节省流量
       SELECT ID, NAME FROM TABLE_WITH_A_LOT_OF_COLUMN WHERE ...

     3.2.1 一般情况下
     Hibernate 会把所有的字段都选出来。比如说有一个上面表有8个字段,
     其中有一两个比较大的字段,varchar(255)/text。上面的场景中我为什么要把他
     们也选出来呢?

     3.2.2 用 hibernate 的话,你又不能把这两个不需要的字段设置为 lazy load,因
     为还有很多地方需要一次把整个 domain object 加载出来。这个时候就能显现出
     ibatis 的好处了

     3.2.3 Hibernate 还有一个方案,就是生成 javabean/map/object[](感谢
     leelun/cjmm),但是这样的话就可能会产生大量的多余 class。map/object[] 的方式
     应该不错,我比较喜欢这种方式。
      
   3.3 如果我需要更新一条记录(一个对象),如果使用 hibernate,需要现把对
     象 select 出来,然后再做 update。这对数据库来说就是两条 sql。而 iBatis
     只需要一条 update 的 sql 就可以了。减少一次与数据库的交互,对于性能的
     提升是非常重要。

4. 开发方面
   4.1 开发效率上,我觉得两者应该差不多
   4.2 可维护性方面,我觉得 iBatis 更好一些。因为 iBatis 的 sql 都保存到
       单独的文件中。而 Hibernate 在有些情况下可能会在 java 代码中保存
       sql/hql。


5. 运行效率
   5.1 在不考虑 cache 的情况下,iBatis 应该会比hibernate 快一些或者很多
      (根据实际情况会有所不同)。


      
当然 iBatis 也有比较大的缺点
1. 不同数据库类型的支持不好,如果你要开发的系统是要在对中数据间移植,那可能用 hibernate 比较好。
2. 缺省的 cache 支持不好,但是 hibernate 的 cache 支持其实也不是很好,而且很复杂。尤其是对于大并发量的应用。所以我更倾向于自己管理 cache。


    非常感谢这么多朋友对这个话题很感兴趣。但是我感觉大家并没有对我第三部分提到的问题进行更深入的思考。我晚些时候会提交一些 ibatis 的代码。欢迎大家一起来讨论。
  

分享到:
评论
49 楼 together 2007-01-01  
简单一点说,很多人选择A而不选择B,都是因为先入为主。

客观的说,从长远来考虑,还是应该采用HB。比如现在我们的系统,如果需要部署到oracle/mssql/db2/mysql/pg/hsql/firebird,所需要做的只是加一个JDBC驱动,再改一下hb.cfg.xml中连接数据库的配置。这一点是IBATIS无论如何也做不到的。
48 楼 jiming 2007-01-01  
勘误

但是诸位所提到的 hibernate 地解决方案却没有一个如此优雅的。直接使用 hsql/nativeSQL 不错,但是他会影响到系统的数据库移植性。这可是我认为唯一需要考虑使用 hibernate 的情况:)
47 楼 jiming 2007-01-01  
总有朋友说 hibernate 的开发效率比ibatis 高,对此我非常的不认同。我想我们举个小例子来比较一下。

以我第4页中贴出的代码为例,我需要更新用户的 status 字段。

我只需要在 UserDao.java 中添加方法

在配置文件中 user.xml 添加

     public int updateStatus(int mender_id, byte status, long id) {  
         Map params = new HashMap();  
         params.put("status", status);  
         params.put("id", id);  
         return template.update("updateUserStatusById", params);  
     }  
      


   <update id="updateUserStatusById" parameterClass="java.util.Map">  
   UPDATE auth_user SET   
     status=#status#  
     , updated_date=#updatedDate#  
     , touch_date=#touchDate#  
   WHERE id=#id#  
   </update>  
  



瞧,多简洁,多优雅。

但是诸位所提到的 hibernate 地解决方案却没有一个如此优雅的。直接使用 hsql/nativeSQL 不错,但是他会影响到系统的数据库一致性。这可是我认为唯一需要考虑使用 hibernate 的情况:)

对于我的第三部分提出的问题,很多位高手都给出了方案。但是正向我在正文中指出的那样,我不是说 hibernate 做不到,而是使用hibernate的方案都相对比较复杂。

我希望大家能再说的时候能够给出一小段代码:)这样更清楚,而且大家说hibernate 很快,我写上面的代码之花了很短的时间,远比我写文字块多了,我向大家也可以花一点点写点代码来说明观点。

我的一贯主张就是程序才是程序员的语言。










46 楼 zwm 2007-01-01  
综合治理-最美
45 楼 cjmm 2007-01-01  
dada 写道
jiming 写道
非常感谢 cjmm 中肯的回帖。其中的大部分观点我都相当认同。

但是我想我先前对 3.1/3.3 地描述可能不是太清楚。所以你的方案并不太适合。我重新详细地描述了一下这两个问题。如果方便的话请重新看看。

3.1没有什么负面作用,自己用反射也能实现。
3.3DML可以解决。如果只是简单的处理的话差一条也无所谓,如果是批量的话hibernate性能确实不如ibatis。但是我觉得问题的关键还是性能是否符合需求,而不是简单的性能比较。


hibernate在性能上最大的问题不是update操作,而是insert操作。呵呵。对insert的限制比较大。还有一些过于严格的检查使得某些数据库优化方面的设计不适用。具体可以见我的space,不过现在连不上。
44 楼 lllyq 2007-01-01  
jiming 写道
3. iBatis 可以进行细粒度的优化

3.1 比如说我有一个表,这个表有几个或者几十个字段,我需要更新其中
的一个字段,iBatis 很简单,执行一个sql
UPDATE TABLE_A SET column_1=#column_1# WHERE id=#id#
但是用 Hibernate 的话就比较麻烦了,缺省的情况下 hibernate 会更新所有字段。
当然我记得 hibernate 有一个选项可以控制只保存修改过的字段,但是我不太确
定这个功能的负面效果。

3.2 我需要列出一个表的部分内容,用 iBatis 的时候,这里面的好处是可以少从数据
库读很多数据,节省流量
SELECT ID, NAME FROM TABLE_WITH_A_LOT_OF_COLUMN WHERE ...

3.2.1 一般情况下
Hibernate 会把所有的字段都选出来。比如说有一个上面表有8个字段,
其中有一两个比较大的字段,varchar(255)/text。上面的场景中我为什么要把他
们也选出来呢?

3.2.2 用 hibernate 的话,你又不能把这两个不需要的字段设置为 lazy load,因
为还有很多地方需要一次把整个 domain object 加载出来。这个时候就能显现出
ibatis 的好处了

3.2.3 Hibernate 还有一个方案,就是生成 javabean/map/object[](感谢
leelun/cjmm),但是这样的话就可能会产生大量的多余 class。map/object[] 的方式
应该不错,我比较喜欢这种方式。

3.3 如果我需要更新一条记录(一个对象),如果使用 hibernate,需要现把对
象 select 出来,然后再做 update。这对数据库来说就是两条 sql。而 iBatis
只需要一条 update 的 sql 就可以了。减少一次与数据库的交互,对于性能的
提升是非常重要。


3.1, 3.3 build update解决,不赘述
3.2 lazy load
3.2.2 lazy load与整个domain object load并不冲突,即使不用lazy loading,也可以通过不同映射或其他方法解决
一般情况下,hibernate可以在90%的应用上给开发上带来数倍的效率提高,剩余的部分也在致力不降低效率,整体来看,比ibatis提升的效率还是很多的
43 楼 dada 2007-01-01  
jiming 写道
非常感谢 cjmm 中肯的回帖。其中的大部分观点我都相当认同。

但是我想我先前对 3.1/3.3 地描述可能不是太清楚。所以你的方案并不太适合。我重新详细地描述了一下这两个问题。如果方便的话请重新看看。

3.1没有什么负面作用,自己用反射也能实现。
3.3DML可以解决。如果只是简单的处理的话差一条也无所谓,如果是批量的话hibernate性能确实不如ibatis。但是我觉得问题的关键还是性能是否符合需求,而不是简单的性能比较。
42 楼 cjmm 2007-01-01  
jiming 写道

  
3. iBatis 可以进行细粒度的优化

   3.1 比如说我有一个表,这个表有几个或者几十个字段,我需要更新其中
       的一个字段,iBatis 很简单,执行一个sql
       UPDATE TABLE_A SET column_1=#column_1# WHERE id=#id#
       但是用 Hibernate 的话就比较麻烦了,缺省的情况下 hibernate 会更新所有字段。
       当然我记得 hibernate 有一个选项可以控制只保存修改过的字段,但是我不太确
       定这个功能的负面效果。

  这个用hql (也就是我刚刚说得bulk update)或者用native sql都可以实现你的需求。
  当然也可以用触发器机制。
    hql:
         String hqlUpdate = "update A a set culumn_1 = :column1 where id=:id"
               Query query = session.createQuery(hqlUpdate);
                  query.setParameter("column1", column1);
                   query.setParameter("id", id);
                     query.excuteUpdate();

   3.3也是同样的处理方式。
 
jiming 写道
    
   3.2 我需要列出一个表的部分内容,用 iBatis 的时候,这里面的好处是可以少从数据
     库读很多数据,节省流量
       SELECT ID, NAME FROM TABLE_WITH_A_LOT_OF_COLUMN WHERE ...

     3.2.1 一般情况下
     Hibernate 会把所有的字段都选出来。比如说有一个上面表有8个字段,
     其中有一两个比较大的字段,varchar(255)/text。上面的场景中我为什么要把他
     们也选出来呢?

     3.2.2 用 hibernate 的话,你又不能把这两个不需要的字段设置为 lazy load,因
     为还有很多地方需要一次把整个 domain object 加载出来。这个时候就能显现出
     ibatis 的好处了
    


    可以对单个字段设为lazy load,在需要一次加载出来的时候再把lazy属性给取消,查询时直接设置
    load mode
 
jiming 写道
  
     3.2.3 Hibernate 还有一个方案,就是生成 javabean/map/object[](感谢
     leelun/cjmm),但是这样的话就可能会产生大量的多余 class。map/object[] 的方式
     应该不错,我比较喜欢这种方式。
       

 
     不需要产生大量多余class,呵呵。设置属性的时候不是所有属性都需要设置的,你还是可以使用原来map的class。
     map成javabean的时候除了使用constructor之外还有一种方式是直接使用setter方法,使用alias成属性名加上setResultTransformer(Transformers.aliasToBean(XXX.class))

    个人建议,你还是对hibernate多加了解再对hibernate进行评述。

    hibernate最大的缺点还是学习曲线过长,其他没啥好弊病的。原始的方式还是高层次的方式都已经提供了很好的支持。
41 楼 daquan198163 2007-01-01  
flyspider 写道

帖子里是人家对ORM的一些看法,怎么就成了“臆想和猜测”了?软件设计过程中必然存在审时度势的折衷,走极端往往过犹不及,如果您很会用hibernate,请给兄弟们说说你如何让Hibernate很少在POJO与RDBMS Model之间转换?

如果采用“领域建模-〉写XDoclet或ejb3.0标注-〉自动生成数据库模式”的流程来使用hibernate就可以免去这个麻烦
40 楼 jiming 2007-01-01  
非常感谢 cjmm 中肯的回帖。其中的大部分观点我都相当认同。

但是我想我先前对 3.1/3.3 地描述可能不是太清楚。所以你的方案并不太适合。我重新详细地描述了一下这两个问题。如果方便的话请重新看看。
39 楼 lllyq 2007-01-01  
jiming 写道
3. iBatis 可以进行细粒度的优化

3.1 比如说我有一个表,我需要更新其中的一个字段,iBatis 很简单,执行一个sql
UPDATE TABLE_A SET column_1=#column_1# WHERE id=#id#
但是用 Hibernate 的话就比较麻烦了

3.2 我需要列出一个表的部分内容,用 iBatis 的时候,这里面的好处是可以少从数据
库读很多数据,节省流量
SELECT ID, NAME FROM TABLE_WITH_A_LOT_OF_COLUMN WHERE ...


不说别的,这两个特性hql直接支持,相比而已还多了兼容性,优劣自己判断吧。
38 楼 cjmm 2007-01-01  
    我hibernate用了2年,使用过程中也碰到过很多乱七八糟的问题,或者解决或者绕过了。
ibatis看了一个晚上,大致了解。
    如果让我在ibatis和hibernate都不熟的基础上对项目的orm框架做选择,我应该
会选择ibatis而不是hibernate。不过在对hibernate比较熟悉的情况下确实是选择hibernate
开发效率会高。
    hibernate是一个重量级的orm框架,其功能的强大使得其灵活性打了一定折扣,可控性也打了一定
折扣。多少显得有点“怪异”的sql重写机制,使得hql的使用受限不少而只能使用native sql。secondary
cache,我看能真正用好的人不多,呵呵。我一贯的做法是自己做cache,而不是用hibernate的cache。

jiming 写道


1. iBatis 易于掌握。拿来文档看半天到两天就可以掌握了。
   Hibernate 可能需要 3 倍以上的时间来掌握。
  
   其中有一些与我探讨的人跟我说 Hibernate 也很容易学,但是在与他们的更深一步的
   讨论中,我发现他们只是使用了 Hibernate 最简单的一部分功能,更深一些的功能,
   和我提出来的一些疑虑他们并没有考虑到。我想绝大部分的人应该都在这个层次内,
   包括我。


  这个是我说会选择ibatis的主要原因,keep it simple stupid,事实上我只需要能满足我自己需求的框架。

jiming 写道


2. iBatis 更容易进行 sql 的 优化。

   这个应该大家都有共识了。另外 Hibernate 生成的 sql 也实在是太难看了。鉴
   于有的朋友提到了 sql 不太重要。我想在这里强调一下我的经验,一般系统性能
   的瓶颈都在数据库上。所以这一点是 iBatis 非常重要的一个优势。

  hibernate生成的sql语句难看点是难看点,人家本来就不是给你看得。如果要做sql的优化,可以用hql或者native sql,这个应该算不上hibernate的缺点了。

jiming 写道

 
3. iBatis 可以进行细粒度的优化

   3.1 比如说我有一个表,我需要更新其中的一个字段,iBatis 很简单,执行一个sql
       UPDATE TABLE_A SET column_1=#column_1# WHERE id=#id#
       但是用 Hibernate 的话就比较麻烦了

             这个hibernate可以用bulk update,不会有额外工作两。


jiming 写道

    
   3.2 我需要列出一个表的部分内容,用 iBatis 的时候,这里面的好处是可以少从数据
     库读很多数据,节省流量
       SELECT ID, NAME FROM TABLE_WITH_A_LOT_OF_COLUMN WHERE ...
  

            hibernate可以做到,可以把结果直接封装成javabean,map或Object[]等等。
    还是挺优美的。
jiming 写道


   3.3 如果我需要更新一条记录(一个对象),如果使用 hibernate,需要现把对
     象 select 出来,然后再做 update。这对数据库来说就是两条 sql。而 iBatis
     只需要一条 update 的 sql 就可以了。减少一次与数据库的交互,对于性能的
     提升是非常重要。

 

    不需要,见我对3.1的评价。

jiming 写道


4. 开发方面
   4.1 开发效率上,我觉得两者应该差不多
   4.2 可维护性方面,我觉得 iBatis 更好一些。因为 iBatis 的 sql 都保存到
       单独的文件中。而 Hibernate 在有些情况下可能会在 java 代码中保存
       sql/hql。


   开发效率上熟悉hibernate的开发效率肯定会比熟悉ibatis的高,至少很多情况下我都没必要动手写sql代码,呵呵。简单的通过pojo的设计直接生成map文件即可。

   可维护性方面,保存在单独文件和在java代码中保存没有本质区别。对我本人来说,我不喜欢在配置文件中保存这些玩意。


jiming 写道


5. 运行效率
   5.1 在不考虑 cache 的情况下,iBatis 应该会比hibernate 快一些或者很多
      (根据实际情况会有所不同)。


    不管是ibatis还是hibernate归根结底还是对数据库访问。用得好的话,就算不考虑cache hibernate是不会比ibatis慢的。

 
jiming 写道

    
当然 iBatis 也有比较大的缺点
1. 不同数据库类型的支持不好,如果你要开发的系统是要在对中数据间移植,那可能用 hibernate 比较好。
2. 缺省的 cache 支持不好,但是 hibernate 的 cache 支持其实也不是很好,而且很复杂。尤其是对于大并发量的应用。所以我更倾向于自己管理 cache。


    非常感谢这么多朋友对这个话题很感兴趣。但是我感觉大家并没有对我第三部分提到的问题进行更深入的思考。我晚些时候会提交一些 ibatis 的代码。欢迎大家一起来讨论。
  


    我的做法也是自己管理cache。
    其实不管是hibernate还是ibatis,终究只是一个工具,人是不能被工具给约束了的。
    hibernate查询方面提供了多种查询方式,如criteria,hql,native sql,只要灵活应用,基本上能涵括数据库查询的需求了。hibernate在oo方面确实是做得挺好了。同时,在某些时候还可以直接使用jdbc(用spring的话可以使用jdbcTemplate),人对hibernate了解不足而不能灵活使用,不能成为hibernate自身的缺点。当然,学习曲线比较长可以成为其缺点的。呵呵。

37 楼 flyspider 2007-01-01  
ahuaxuan 写道
flyspider 写道
ahuaxuan 写道
我觉得楼主应该没有用过hibernate吧,lz并没有写hibernate的优点,而是一个劲的写缺点,ibatis和hibernate其实应该可以看成是互不的两个东西,hibernate学习成本高于ibatis,但是hibernate的效率也高于ibatis,用hibernate也更oo,我看到lz说ibatis更容易优化芸芸,其实一般的系统要优化的sql语句有多少??一般的项目用hibernate是没有问题的,遗留系统或者性能要求非常苛刻的系统应该用ibatis,这两者没有绝对的好和坏的问题,只有不同的系统不同的项目用哪个更合适的问题,如果lz说hibernate不适合你们的系统,那请讲讲理由好吗

hibernate的效率高于iBATIS?请讲讲理由。

1,自动组装对象
2,简化查询(这一点最提高效率)
3,更少的sql
4,更加面向对象
5,学习hibernate对比学习ibatis来说虽然成本高但是收获更加大,因为学习hibernate学习到的其实是一种orm思想,这一点尤其重要,对一个人的发展来说比较有利(这一点扯大了)。
6,对二级缓存良好的支持
7,使多数据库版本的规模不大的产品的实现更加容易

倒,原来是说开发效率。
36 楼 flyspider 2007-01-01  
daquan198163 写道
iceant 写道
我不喜欢Hibernate,也不喜欢所谓的OO,大家可以冷静的想想,有多少系统是真正使用的 OO 方式来设计和实现的呢

OO只是一种思考方式,它可以有助于开发人员了解和分析系统,抽象出系统中的各种元素。但是真正实现,还是要使用传统的各种方法与技术。OO不能解决你所有的问题,言必谈OO,不一定真正的了解OO.

我说个简单点的,有谁能用纯OO实现一个系统,然后又能很好的控制事务的? 

Hibernate 也是一样,它也有自己适用的范围和区间。Hibernate 要应用得好,真的是要花很多的时间,我是从JDBC开始写应用的,所以我不喜欢Hibernate,因为它在实现系统时的思维方式与我的不一样~ 我使用 RDBMS 做为 Storage,Hibernate 将 RDBMS 中的 Table 转换为 POJO,在做系统时,我要不停的在 RDBMS Model 和 POJO 之间转换,为的是了解系统底层发生了什么,系统是否能进一步优化,为了能更好的让 Hibernate 发挥效率,我要试很多不同的方式,最终才能确定哪一种在这个情况下可能更合适~ 说句实话,累啊~ 感觉就像是在计算机里不停的切换两个线程~

iBatis简单,最重要的是,我的模型是用 RDBMS 描述的,我能继续用 RDBMS 的方式来处理数据,对于我这种人来说,存贮过程在很多情况下仍然是最好的选择。也许有人会说,你们把业务放在存贮过程中,可扩展性很差。呵~ 所以这就要看你应用的 scope 了,如果性能很重要,使用存贮过程还是很好的选择。而且对我们的应用,除了 Oracle,不可能用别的数据库。

我觉得很多人把精力花在系统的可扩展性和可移植性上了,就我接触过的系统来说,这方面的需求还是很少的。一来有些系统的生命周期非常短,没有必要;再来,系统运行的时间长了,对它进行替换的成本是很高的。

因此我偏向于对一个具体的应用,采取最有效最简单的方式来完成。就像如果需求只是要打印 123,那就 System.out.println("123”)就好了,不要再来个 System.out.println(124-1)

Hibernate 对于熟悉它的人,是一样非常好的工具,Hibernate 的作者也说过,只要是 Hibernate Team 的人,做出来的系统肯定性能不会差~ 但是不熟悉的人就很难说了~ 我建议使用它的人还是读读它的代码,别盲目使用。很难相象一个程序员,对它的工具做了什么都不知道,还能用好它。

Hibernate 还有一样我最不能接受的,就是它的作者。他根本不能接受别人的意见,只想听奉承。对于别人提出的意见示而不见。最有名的就是在 web 系统里 redeploy 时, Hibernate 会因为内存不能得到释放,引起 web 容器down掉(OutofMemoryExcepiton)。很多人都报告过这个问题,但是开发团队从来不承认这是 Hibernate 引起的。一下说是 commons-log.jar的问题,一下又说是 dom4j的问题,一下又说是 tomcat 的问题(已经证实jboss/weblogic/websphere也会出这问题),一下又说是cglib的问题,呵~ 反正理由多得是~ 就是不关 Hibernate 的问题~ 有人在 JIRA 里开了个BUG,被作者以 Session没有 close 为由给close了,他连测都没测一下~ 我经过测试,证明就算是调用了Session.close还是一样会出现这个问题,只要把Hibernate.jar去掉,一切就可以很好的工作。 Hibernate 的论坛上本来有一个贴子就是说这个问题的,很多人都关注过,但是后来不知道为什么这个贴子不在了。这个问题存在很久了,到最新版的Hibernate也没有解决。我很难理解,JBoss为什么要把它引入到 AS 里面去,它就不怕 Hibernate 引起 redeploy 失效吗?这和JBoss AS的 7*24 不相符啊~


最后我想说,在没有ORM的时候,我们一样能做出系统,而且性能也不差,系统一样可以维护,为什么一定要用ORM?有个朋友说,这些技术只是让程序员舒服了,但是软件不见得就强壮多少。我想这句话很有道理

通篇是你的臆想和猜测
另外,如果你"要不停的在 RDBMS Model 和 POJO 之间转换",说明你还不知道如何用hibernate

帖子里是人家对ORM的一些看法,怎么就成了“臆想和猜测”了?软件设计过程中必然存在审时度势的折衷,走极端往往过犹不及,如果您很会用hibernate,请给兄弟们说说你如何让Hibernate很少在POJO与RDBMS Model之间转换?
35 楼 jiming 2007-01-01  
上面的两个文件就是用 ibatis 的解决方案。

多优美。

本来想打包上传的,不知道为什么不能上传文件,所以直接贴代码了。

好像多贴了一个 xml 的代码,请 robbin 方便的话帮我把多余的删了吧,谢谢。
34 楼 jiming 2007-01-01  
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">





<!-- Created by Jiming Liu -->
<!-- Flag: 0.5 -->
<!-- Including primary operation definition of auth_user-->
<sqlMap namespace="auth_user">
  <typeAlias alias="type_User" type="com.jiming.community.shoubo.auth.domain.User" />
  
  <resultMap id="user" class="type_User">
    <result property="id" column="id" />
    <result property="name" column="name" />
    <result property="password" column="password" />
    <result property="mid" column="mid" />
    <result property="msisdn" column="msisdn" />
    <result property="regDate" column="reg_date" />
    <result property="updatedDate" column="updated_date" />
    <result property="lastVisitDate" column="last_visit_date" />
    <result property="birthday" column="birthday" />
    <result property="score" column="score" />
    <result property="country" column="country" />
    <result property="province" column="province" />
    <result property="city" column="city" />
    <result property="gender" column="gender" />
    <result property="hasBlog" column="has_blog" />
    <result property="status" column="status" />
    <result property="postCount" column="post_count" />
    <result property="replyCount" column="reply_count" />
    <result property="groups" column="groups" />
    <result property="sig" column="sig" />
    <result property="intro" column="intro" />
    <result property="productId" column="product_id" />
    <result property="pagesize" column="pagesize" />
    <result property="creatorId" column="creator_id" />
    <result property="touchDate" column="touch_date" />
    <result property="ratio" column="ratio" />
    <result property="money" column="money" />
  </resultMap>

  <!-- Get element by unique keys - begin -->
      

  <select id="getUserById" parameterClass="long" resultMap="user">
    SELECT * FROM auth_user 
     WHERE id=#value#
  </select>
    
      

  <select id="getUserByName" parameterClass="java.lang.String" resultMap="user">
    SELECT * FROM auth_user 
     WHERE name=#value#
  </select>
    
      

    
  <!-- Get element by unique keys - end -->

  <insert id="insertUser" parameterClass="type_User">
    INSERT INTO auth_user (
      name
      , password
      , mid
      , msisdn
      , reg_date
      , updated_date
      , last_visit_date
      , birthday
      , score
      , country
      , province
      , city
      , gender
      , has_blog
      , status
      , post_count
      , reply_count
      , groups
      , sig
      , intro
      , product_id
      , pagesize
      , creator_id
      , touch_date
      , ratio
      , money
    ) VALUES (
      #name#
      , #password#
      , #mid#
      , #msisdn#
      , #regDate#
      , #updatedDate#
      , #lastVisitDate#
      , #birthday#
      , #score#
      , #country#
      , #province#
      , #city#
      , #gender#
      , #hasBlog#
      , #status#
      , #postCount#
      , #replyCount#
      , #groups#
      , #sig#
      , #intro#
      , #productId#
      , #pagesize#
      , #creatorId#
      , #touchDate#
      , #ratio#
      , #money#
    )
    <selectKey resultClass="int" keyProperty="id" >
    SELECT @@IDENTITY AS id
    </selectKey>
  </insert>
  
  <select id="getUser" resultMap="user">
    SELECT * FROM auth_user
  </select>


  <select id="getUserCount" resultClass="java.lang.Integer">
    SELECT COUNT(1) FROM auth_user
  </select>


  <select id="getUserIdWithCondition"
    resultClass="long" parameterClass="searchClause">
    SELECT id FROM auth_user
    $clauseWithoutLimit$
    <isGreaterEqual property="startIndex" compareValue="0">
    LIMIT #startIndex#,#pageSize#
    </isGreaterEqual>
  </select>


  <!-- Delete element by unique keys - begin -->
  <delete id="deleteUserById" parameterClass="long">
    DELETE FROM auth_user 
     WHERE id=#value#
  </delete>
    
  <delete id="deleteUserByName" parameterClass="java.lang.String">
    DELETE FROM auth_user 
     WHERE name=#value#
  </delete>
    
    
  <!-- Delete element by unique keys - end -->


  
  <update id="updateUser" parameterClass="type_User">
  UPDATE auth_user SET 
    name=#name#
    , password=#password#
    , mid=#mid#
    , msisdn=#msisdn#
    , reg_date=#regDate#
    , updated_date=#updatedDate#
    , last_visit_date=#lastVisitDate#
    , birthday=#birthday#
    , score=#score#
    , country=#country#
    , province=#province#
    , city=#city#
    , gender=#gender#
    , has_blog=#hasBlog#
    , status=#status#
    , post_count=#postCount#
    , reply_count=#replyCount#
    , groups=#groups#
    , sig=#sig#
    , intro=#intro#
    , product_id=#productId#
    , pagesize=#pagesize#
    , creator_id=#creatorId#
    , touch_date=#touchDate#
    , ratio=#ratio#
    , money=#money#
   WHERE id=#id#
  </update>
  
  
  
  
  
  
  
  
  
  
  
  
  
  // 上面的部分已经可以解决绝大部分的问题了
  // 下面的部分是为了细化的调优,不要因此认为 ibatis 配置很复杂,你可以忽略这部分
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  <update id="updateUserStatusById" parameterClass="java.util.Map">
  UPDATE auth_user SET 
    status=#status#
    , updated_date=#updatedDate#
    , touch_date=#touchDate#
  WHERE id=#id#
  </update>
  
  
  <select id="listUser" resultClass="java.util.HashMap">
    SELECT id 
      , name 
      , msisdn 
      , reg_date AS regDate 
      , updated_date AS updatedDate 
      , last_visit_date AS lastVisitDate 
      , birthday 
      , score 
    FROM auth_user
  </select>

  


  
    
  <select id="user_listIdName" resultClass="java.util.HashMap" parameterClass="java.util.Map">
    SELECT id
      , name
     WHERE name = #name#
  </select>
  
  
  <update id="user_addVisitCount"  parameterClass="java.util.Map">
    UPDATE auth_user SET
      post_count=post_count+#amount#      
      WHERE id=#id#      
  </update>
  <update id="user_addVisitCountByIdName"  parameterClass="java.util.Map">
    UPDATE auth_user SET
      post_count=post_count+#amount#      
     WHERE id=#id#      
       AND name=#name#      
  </update>
  


  
    
  <select id="user_listIdName" resultClass="java.util.HashMap" parameterClass="java.util.Map">
    SELECT id
      , name
     WHERE name = #name#
  </select>
  
  

  
  <update id="user_addVisitCount"  parameterClass="java.util.Map">
    UPDATE auth_user SET
      post_count=post_count+#amount#      
     WHERE id=#id#      
  </update>

</sqlMap>







33 楼 jiming 2007-01-01  
/**
 *
 * $Id$
 * Flag: 0.5
 *
 */


package com.jiming.community.shoubo.auth.persistence.sqlmapdao.base;

import java.util.List;
import java.util.Map;
import java.sql.Date;
import java.sql.Timestamp;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

import jm.lib.common.db.SqlUtil;
import jm.lib.common.db.Order;
import jm.lib.util.DateUtil;
import jm.lib.util.StrUtil;
import jm.lib.common.db.ConditionOperation;
import jm.lib.common.db.SearchClause;
import jm.lib.common.db.SimpleSearchCondition;
import jm.lib.collections.map.TinyMap;

import com.jiming.community.shoubo.auth.domain.User;
import com.jiming.community.shoubo.auth.persistence.iface.UserDao;


/**
 * @author Jiming Liu
 *
 */
public abstract class BaseUserSqlMapDao extends SqlMapClientDaoSupport implements UserDao {

    private static final Log logger = LogFactory
        .getLog(BaseUserSqlMapDao.class);

    protected SqlMapClientTemplate template = this.getSqlMapClientTemplate();

    // Get element by unique keys -- begin
    public User getById(int user_id, long id) {
        return (User)template.queryForObject("getUserById", id);

    }

    public User getByName(int user_id, String name) {
        return (User)template.queryForObject("getUserByName", name);

    }


    // Get element by unique keys -- end


    /**
     * equals <code>insert(value, true)</code>
     * @param mender_id
     * @param value
     * @return
     */
    public Object insert(int mender_id, User value) {
        return insert(mender_id, value, true);
    }


    @SuppressWarnings("unchecked")
    public List<User> getList(int user_id) {
        return (List<User>)template.queryForList("getUser", null);
    }


    public int getTotalCount() {
        Integer result = (Integer)template.queryForObject("getUserCount", null);
        return result.intValue();
    }


    public int getCount(int user_id, SearchClause clause) {
        Integer result = (Integer)template.queryForObject("getUserCountWithCondition", clause);
        return result.intValue();
    }

    @SuppressWarnings("unchecked")
    public List<Long> getId(int user_id, SearchClause clause) {
        return (List<Long>)template.queryForList("getUserIdWithCondition", clause);
    }

    @SuppressWarnings("unchecked")
    public List<Map> list(int user_id) {
        return (List<Map>)template.queryForList("listUser", null);
    }


    public List<Map> list(int user_id, int startIndex, int pageSize) {
        SearchClause clause = new SearchClause();
        clause.setStartIndex(startIndex);
        clause.setPageSize(pageSize);
        return list(user_id, clause);
    }


    @SuppressWarnings("unchecked")
    public List<Map> list(int user_id, SearchClause clause) {
        List result = template.queryForList("listUserWithCondition", clause);
        return (List<Map>)result;
    }

    @SuppressWarnings("unchecked")
    public List<Map> list(int user_id, String[] columns, SearchClause clause) {
        Map params = new TinyMap(2);
        params.put("clause", clause);
        params.put("columns", SqlUtil.getColumnsInSql(columns));
        return (List<Map>)template.queryForList("listUserCustomized", params);
    }


    // Delete element by unique keys -- begin
    @SuppressWarnings("unchecked")
    public int deleteById(int mender_id, long id) {
        return template.delete("deleteUserById", id);
    }

    @SuppressWarnings("unchecked")
    public int deleteByName(int mender_id, String name) {
        return template.delete("deleteUserByName", name);
    }

    // Delete element by unique keys -- end



    /**
     * equals <code>update(mender_id, value, true)</code>
     * @param value
     * @return
     */
    public int update(int mender_id, User value) {
        return update(mender_id, value, true);
    }



    public int updateStatus(int mender_id, byte status, long id) {
        Map params = new TinyMap();
        params.put("status", status);
        params.put("id", id);
        return template.update("updateUserStatusById", params);
    }















    @SuppressWarnings("unchecked")
    public List<Map> listIdName(int user_id, String name) {
        Map params = new TinyMap();
        params.put("name", name);
        return (List<Map>)template.queryForList("user_listIdName", params);
    }

    @SuppressWarnings("unchecked")
    public List<Map> listIdNameByDescGroup(int user_id, String name) {
        Map params = new TinyMap();
        params.put("name", name);
        return (List<Map>)template.queryForList("user_listIdNameByDescGroup", params);
    }





    @SuppressWarnings("unchecked")
    public int addVisitCount(int user_id, int amount, long id) {
        Map params = new TinyMap();
        params.put("id", id);
        params.put("amount", amount);
        return template.update("user_addVisitCount", params);
    }

}

















32 楼 jiming 2007-01-01  
引用
从你的分析来看,我觉得你可以稍微花点时间在如何解决你所分析出来的问题上面。你所提到的问题都是可以解决的。

ORM框架各有各的好处,不用过分强调谁行谁不行。老实说,iBatis在做持久化的笨拙就令人受不了。一张表有30个字段,你用ibatis去做一次insert试试?不过在查询方面,iBatis的确有很多优势的地方。


这几个问题不是说 hibernate 无法解决,而是他的解决方案太难看,或者执行效率太低了。
31 楼 daquan198163 2007-01-01  
iceant 写道
我不喜欢Hibernate,也不喜欢所谓的OO,大家可以冷静的想想,有多少系统是真正使用的 OO 方式来设计和实现的呢

OO只是一种思考方式,它可以有助于开发人员了解和分析系统,抽象出系统中的各种元素。但是真正实现,还是要使用传统的各种方法与技术。OO不能解决你所有的问题,言必谈OO,不一定真正的了解OO.

我说个简单点的,有谁能用纯OO实现一个系统,然后又能很好的控制事务的? 

Hibernate 也是一样,它也有自己适用的范围和区间。Hibernate 要应用得好,真的是要花很多的时间,我是从JDBC开始写应用的,所以我不喜欢Hibernate,因为它在实现系统时的思维方式与我的不一样~ 我使用 RDBMS 做为 Storage,Hibernate 将 RDBMS 中的 Table 转换为 POJO,在做系统时,我要不停的在 RDBMS Model 和 POJO 之间转换,为的是了解系统底层发生了什么,系统是否能进一步优化,为了能更好的让 Hibernate 发挥效率,我要试很多不同的方式,最终才能确定哪一种在这个情况下可能更合适~ 说句实话,累啊~ 感觉就像是在计算机里不停的切换两个线程~

iBatis简单,最重要的是,我的模型是用 RDBMS 描述的,我能继续用 RDBMS 的方式来处理数据,对于我这种人来说,存贮过程在很多情况下仍然是最好的选择。也许有人会说,你们把业务放在存贮过程中,可扩展性很差。呵~ 所以这就要看你应用的 scope 了,如果性能很重要,使用存贮过程还是很好的选择。而且对我们的应用,除了 Oracle,不可能用别的数据库。

我觉得很多人把精力花在系统的可扩展性和可移植性上了,就我接触过的系统来说,这方面的需求还是很少的。一来有些系统的生命周期非常短,没有必要;再来,系统运行的时间长了,对它进行替换的成本是很高的。

因此我偏向于对一个具体的应用,采取最有效最简单的方式来完成。就像如果需求只是要打印 123,那就 System.out.println("123”)就好了,不要再来个 System.out.println(124-1)

Hibernate 对于熟悉它的人,是一样非常好的工具,Hibernate 的作者也说过,只要是 Hibernate Team 的人,做出来的系统肯定性能不会差~ 但是不熟悉的人就很难说了~ 我建议使用它的人还是读读它的代码,别盲目使用。很难相象一个程序员,对它的工具做了什么都不知道,还能用好它。

Hibernate 还有一样我最不能接受的,就是它的作者。他根本不能接受别人的意见,只想听奉承。对于别人提出的意见示而不见。最有名的就是在 web 系统里 redeploy 时, Hibernate 会因为内存不能得到释放,引起 web 容器down掉(OutofMemoryExcepiton)。很多人都报告过这个问题,但是开发团队从来不承认这是 Hibernate 引起的。一下说是 commons-log.jar的问题,一下又说是 dom4j的问题,一下又说是 tomcat 的问题(已经证实jboss/weblogic/websphere也会出这问题),一下又说是cglib的问题,呵~ 反正理由多得是~ 就是不关 Hibernate 的问题~ 有人在 JIRA 里开了个BUG,被作者以 Session没有 close 为由给close了,他连测都没测一下~ 我经过测试,证明就算是调用了Session.close还是一样会出现这个问题,只要把Hibernate.jar去掉,一切就可以很好的工作。 Hibernate 的论坛上本来有一个贴子就是说这个问题的,很多人都关注过,但是后来不知道为什么这个贴子不在了。这个问题存在很久了,到最新版的Hibernate也没有解决。我很难理解,JBoss为什么要把它引入到 AS 里面去,它就不怕 Hibernate 引起 redeploy 失效吗?这和JBoss AS的 7*24 不相符啊~


最后我想说,在没有ORM的时候,我们一样能做出系统,而且性能也不差,系统一样可以维护,为什么一定要用ORM?有个朋友说,这些技术只是让程序员舒服了,但是软件不见得就强壮多少。我想这句话很有道理

通篇是你的臆想和猜测
另外,如果你"要不停的在 RDBMS Model 和 POJO 之间转换",说明你还不知道如何用hibernate
30 楼 ray_linn 2007-01-01  
downpour 写道

一张表有30个字段,你用ibatis去做一次insert试试?不过在查询方面,iBatis的确有很多优势的地方。


我只能说,典型的活人给尿憋死,人的手是用来创造工具的,不只是用来打键盘的.

相关推荐

    struts2+hibernate+spring+ibatis.rar

    Struts2、Hibernate、Spring 和 iBatis 是四个在Java Web开发中广泛应用的开源框架,它们的整合常常被称为SSH(Struts2、Spring、Hibernate)或者SHiP(Struts2、Hibernate、iBatis、Spring)。这个"struts2+...

    ibatis2+spring

    在现代企业级应用开发中,iBatis2和Spring框架的结合使用已经成为一种常见的技术选型。iBatis作为一个优秀的SQL映射框架,使得数据库操作更为灵活,而Spring作为全方位的应用框架,提供了依赖注入、事务管理等核心...

    SSH学习之Hibernate

    SSH(Spring、Struts、Hibernate)是一种经典的Java Web应用程序开发框架,其中Hibernate是一个强大的持久层框架,专注于简化数据库交互。这篇PPT主要介绍了Hibernate的核心概念、持久层的重要性以及ORM(对象关系...

    struts2_spring_ibatis3.0整合

    Struts2、Spring和iBatis是Java Web开发中常用的三大框架,它们分别负责MVC模式中的...在实际开发中,根据项目的具体需求,可能还需要考虑其他组件的集成,如Hibernate、MyBatis3等,以达到最佳的技术选型和性能优化。

    Java高手真经_应用框架卷_Java_Web核心框架.part1.rar

    书首先分析了java web应用的分层设计方法,并进行应用框架的选型,然后讲解各种java web应用框架、集成技术、实战开发。主要内容包括如下。.  持久层框架hibernate:讲解hibernate入门与核心技术,分别实现mysql、...

    Java高手真经_应用框架卷_Java_Web核心框架.part2.rar

    书首先分析了java web应用的分层设计方法,并进行应用框架的选型,然后讲解各种java web应用框架、集成技术、实战开发。主要内容包括如下。.  持久层框架hibernate:讲解hibernate入门与核心技术,分别实现mysql、...

    Java高手真经_应用框架卷_Java_Web核心框架.part3.rar

    书首先分析了java web应用的分层设计方法,并进行应用框架的选型,然后讲解各种java web应用框架、集成技术、实战开发。主要内容包括如下。.  持久层框架hibernate:讲解hibernate入门与核心技术,分别实现mysql、...

    Java高手真经 应用框架卷 源码

    表现层框架Struts 1:讲解Struts 1的入门配置、核心组件、标签库、国际化、数据校验、Sitemesh集成、数据库开发技术,并分别实现与Hibernate、iBATIS持久层框架的集成开发。..表现层框架Struts 2:讲解Struts 2的...

    软考系统架构设计师2016年真题范文题目3

    - **iBATIS**(MyBatis):与 Hibernate 相比,iBATIS 更侧重于 SQL 映射,开发者需要手动编写 SQL 语句,并通过框架提供的工具将其映射到 Java 对象上。这种方式更灵活,但在复杂查询方面可能需要更多手工工作。 ...

    大数据功能模块概要设计.doc

    J2EE服务端开发涉及的库包括apache-commons提供基础类扩展,json-lib处理JSON数据,junit进行单元测试,struts2/spring mvc作为MVC框架,ibatis/mybatis/hibernate作为ORM层选择。 **选型** 3.1 **中间件**:商业...

    java开发规范.pdf

    此外,对于Hibernate和IBatis的SQL语句以及Spring的Service注入,都要求加上模块名,以防止命名冲突和加载错误。 最后,模块划分的意义在于提升系统的扩展性和可维护性。各模块之间尽量避免直接调用,以降低耦合,...

    大数据功能模块概要设计-V1.1Word版.docx

    《大数据功能模块概要设计》是对大数据系统的架构和组件进行详细描述的一份文档,主要涵盖了系统总体架构、通用组件和基础类库的选择,以及中间件和数据库的选型。以下是根据文档内容提炼的关键知识点: 1. **系统...

    通向架构师的道路(第十八天)

    而对于需要复杂对象关系映射的场景,则Hibernate或iBatis(MyBatis)可能是更好的选择。 #### 结语 《通向架构师的道路》不仅是技术探索的旅程,更是个人成长与家庭责任交织的故事。通过深入理解和运用Spring框架...

    创建灵活易扩展的J2EE企业应用程序框架

    数据持久层则涉及数据的存储和访问,包括JDBC、ORMapping工具(如Hibernate、TopLink)、SQLMapper(如iBatis)、JDO以及EJB实体bean等。ORMapping工具简化了对象与数据库之间的映射,提高了开发效率,而JDBC则更为...

    大数据功能模块概要设计_V1.1.pdf

    - **J2EE基础类库**:如Apache Commons、JSON-Lib用于JSON处理,JUnit进行单元测试,Struts2或Spring MVC作为MVC框架,Spring处理业务逻辑,ORM层可以选择ibatis、mybatis或hibernate。 - **中间件**:商业中间件...

    Java开发与技术挑战——关于技术的技术思考.docx

    - 随后,开发者会接触到诸如dom4j、jdom、log4j、Hibernate、Spring、iBatis、Struts等开源框架。 - 数据交换中,JSON和XML的封装和解析是必备技能,正则表达式也在开发中扮演重要角色。 - 开发环境如Tomcat、...

    IT系统架构概述.pptx

    - 使用Spring和Alibaba Service框架,引入Velocity模板,使用分布式缓存,数据库访问层开始使用Hibernate和iBatis,以iBatis为主。 3. **每个阶段的技术演进** - **史前到石器时代**:从脚本语言到Java的转变,...

    网站架构设计 教你进入架构设计

    例如,Amoeba用于MySQL,PL/Proxy用于PostgreSQL,而Hibernate Shard、Ibatis Shard和Pyshards则是不同编程语言中的Sharding库。 总的来说,网站架构设计是一个复杂而深奥的领域,涉及到技术选型、系统设计、性能...

Global site tag (gtag.js) - Google Analytics