论坛首页 Java企业应用论坛

谈谈Hibernate令人不爽的地方

浏览 95637 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-09-14  
庄表伟 写道
记得以前robbin还说过,Hibernate生成的SQL,非常的优化,效率极高,非JDBC顶级高手,勿须尝试写出比Hibernate更加好的SQL。

怎么现在就成了:“现在极其厌恶Hibernate生成的SQL,又臭又长,极难阅读。”?


正所谓“此一时,彼一时”嘛, ,说来说去,还是个场景问题,性能 vs 移植性...
0 请登录后投票
   发表时间:2006-09-15  
Readonly 写道
偶严重反对robbin对于HSQL的看法,如果没有HSQL的话,让偶回到过去那种写一个产品,要在N种数据库上调试不同的SQL兼容性,简直是噩梦啊。
COC就更没有啥话好说了,你完全可以给Hibernate加个COC plugin,只支持native PK,只支持1:N,只支持字段和数据库栏位同名。批评Hibernate不够自动化,就象批评手自一体的BMW比自动挡的KIA难用一样好笑...

Hibernate生成的SQL倒是没有啥感觉,因为基本上hibernate.show_sql都是false,只有很特殊的调试情况下,才需要打开这个参数去看生成的sql是怎么样的吧?

用jrc sql,价格便宜量又足。
0 请登录后投票
   发表时间:2006-09-15  
庄表伟 写道
记得以前robbin还说过,Hibernate生成的SQL,非常的优化,效率极高,非JDBC顶级高手,勿须尝试写出比Hibernate更加好的SQL。

怎么现在就成了:“现在极其厌恶Hibernate生成的SQL,又臭又长,极难阅读。”?


Hibernate生成的SQL确实不错,这方面我承认,但Hibernate把表名,字段名都自作主张加上了别名,看起来太难看了,阅读起来非常不友好。
0 请登录后投票
   发表时间:2006-09-15  
hibernate.format_sql = true

如果想要仔细看Hibernate生成的SQL语句,将format_sql设为true可以很大程度地减轻痛苦……


再加上这个的话:
hibernate.use_sql_comments = true

个人认为 [可读性 + 可定位性] 会更好。

当然,这两个一起来的话也会造成SQL在console中显示的篇幅很大。例如:

/**
 * 以下是Hibernate在控制台中自动生成的log
 */

Hibernate:
    /* criteria query */ select
        this_.id as id88_0_,
        this_.flag as flag88_0_,
        this_.description as descript3_88_0_,
        this_.mobilizationDate as mobiliza4_88_0_,
        this_.recordId as recordId88_0_,
        this_.deptFromId as deptFromId88_0_,
        this_.deptToId as deptToId88_0_
    from
        Mobilization this_
    where
        this_.flag=?
    order by
        this_.id asc

Hibernate:
    /* load net.example.model.PersonnelRecord */ select
        personnelr0_.id as id91_0_,
        personnelr0_.flag as flag91_0_,
        personnelr0_.birthDate as birthDate91_0_,
        personnelr0_.deptId as deptId91_0_,
        personnelr0_.eduQualificationId as eduQuali5_91_0_,
        personnelr0_.firstWorkDate as firstWor6_91_0_,
        personnelr0_.gender as gender91_0_,
        personnelr0_.idNumber as idNumber91_0_,
        personnelr0_.nationalityId as national9_91_0_,
        personnelr0_.originDate as originDate91_0_,
        personnelr0_.politicalConditionId as politic11_91_0_,
        personnelr0_.socialRelation as socialR12_91_0_,
        personnelr0_.description as descrip13_91_0_,
        personnelr0_.jobPositionId as jobPosi14_91_0_,
        personnelr0_.jobTitleId as jobTitleId91_0_,
        personnelr0_.jobTypeId as jobTypeId91_0_,
        personnelr0_.personName as personName91_0_,
        personnelr0_.iconUrl as iconUrl91_0_,
        personnelr0_.officialFlagId as officia19_91_0_,
        personnelr0_.marriageFlagId as marriag20_91_0_,
        personnelr0_.personnelNumber as personn21_91_0_,
        personnelr0_.quitWorkDate as quitWor22_91_0_,
        personnelr0_.address as address91_0_,
        personnelr0_.cellPhoneNumber as cellPho24_91_0_,
        personnelr0_.email as email91_0_,
        personnelr0_.phoneNumber as phoneNu26_91_0_,
        personnelr0_.nativeLocation as nativeL27_91_0_
    from
        PersonnelRecord personnelr0_
    where
        personnelr0_.id=?

Hibernate:
    /* load net.example.model.Department */ select
        department0_.id as id81_0_,
        department0_.flag as flag81_0_,
        department0_.deptName as deptName81_0_,
        department0_.deptTypeId as deptTypeId81_0_,
        department0_.description as descript5_81_0_,
        department0_.deptNumber as deptNumber81_0_
    from
        Department department0_
    where
        department0_.id=?

Hibernate:
    /* load net.example.model.Department */ select
        department0_.id as id81_0_,
        department0_.flag as flag81_0_,
        department0_.deptName as deptName81_0_,
        department0_.deptTypeId as deptTypeId81_0_,
        department0_.description as descript5_81_0_,
        department0_.deptNumber as deptNumber81_0_
    from
        Department department0_
    where
        department0_.id=?
0 请登录后投票
   发表时间:2006-09-15  
liuwangxia 写道
robbin 写道
2、现在极其厌恶Hibernate生成的SQL,又臭又长,极难阅读。
深有同感!
原因是要为表生成别名,还要为字段生成别名,而且当 SQL 只涉及到一张表的时候还要为表生成一个别名 this_,为每个字段生成别名 *_0_,浪费!
对了,那位热心人能将这个问题提交给 Hibernate 开发组试试看!




机器自动生成,而且还得考虑不能触犯到保留字(java sql 数据库自身),这样多的要求,还得易看!其实hibernate做得很好了,只是我们不知道他们所考虑的。
0 请登录后投票
   发表时间:2006-09-15  
ylt 写道

我同意Readonly的观点。如果不用hql,想实现数据库兼容就太难了。
举个例子,在很多手工录入的表格中都要记录录入时间/操作人/备注,我在java中使用date/person/comment来表示,可是java的关键字和sql的是不一样的,不同数据库也有各自的扩展关键字,上面那几个字段很可能就是某种数据库的关键字。用hql,我所有的查询语句就可以保持统一,切换数据库只需要修改mapping。实际上我写了一个自动根据数据库关键字修改mapping的类,这样连mapping文件也只需要一个。


实现数据库兼容并不象你想象的那么难。:)
我做的平台软件在多种数据库上测试过,包括:Oracle9(10),SqlServer2000,MySql4(5),PostgreSQL8,
HyperSonic。
操作包括CRUD,查询也有比较复杂的。
兼容数据库的步骤如下:
1)数据库DDL是要自行处理的。当然可以借助PowerDesigner的自动转换数据库功能,虽然也有bug,其实主要无非就是一些数据类型的转换,手写也可。
2)CRUD之字段类型。JDBC的PreparedStatement已经帮你将所有的字段类型都封装了,不需要为了插入日期型等数据调用数据库本地的函数,ps.setDate()即可。
3)CRUD之SQL语法。ANSI SQL标准虽然贯彻得不够彻底,但常用的语法的确得到了一致认可。比如,表的左外连接在Oracle8里只有a.field1=b.feild2(+)这种方式,但在Oracle9以后,都支持标准的left outer join on语法了。这种语法在上述5种数据库都得到支持。其他的别名的语法也支持良好。
我碰到的一个比较搞的问题就是SQLserver2000种删除语句不能给表设置别名,即不能delete from TABLE a where a.id=?,去除别名无问题。
4)结果分页。这个的确是我碰到的最需额外处理等问题。我就是参考了hibernate的方法解决的。
5)ID生成问题。不同数据库有各自优化的方式,也可以使用通用的方式。也参考hibernate。
6)其他问题。比如Oracle里的hierachical query(connect by语句)在其他的数据库可能没有对等的实现方式,此时无法对此特性跨平台了。

0 请登录后投票
   发表时间:2006-09-15  
AreYouOK? 写道
我现在觉得还是jdbc来的最直接,有什么问题无非就是调试一下sql语句。虽然有时候象是在干体力活,但是多花一分钟的时间写sql语句总比花一个小时去研究hibernate产生的奇奇怪怪的现象要划算。

我把potian举过的例子修改下,假设你对性能感兴趣:
那么通常下hibernate会批量更新,但是A情况下就不会,A情况下如果满足B条件,它又能批量更新,不过你不能用C功能,否则它又不行,你是不是很崩溃?最后你可能要花好几个小时终于弄清楚了这个小问题,那边用jdbc做事的早就做完了。

jdbc大家都会,所以相对于整个团队而言,jdbc程序的可读性很好。而hibernate这种东西太复杂,每个人的掌握程度都不一样。这样,当我阅读或者修改别人的hibernate代码的时候,如果他用到了我不熟悉的功能,那么我总是要先花时间了解一下这个功能,否则当我操作对象的时候,不知道hibernate在后面做了些什么奇奇怪怪的事情,心里太没底。或许你是高手,可是当团队里别人要修改你的程序的时候,他怎么办呢?

用最简单的方式解决问题,是很有道理的。


这个问题有意思。我有同感。
没出现ORM之前就会有人觉得直接写SQL丑陋;现在又会有人觉得用ORM麻烦。
这真是事务发展的规律啊。
JAVA不也面临类似的疑问么?

得到一些也要失去一些。什么也替代不了你自己独立的、因地制宜的、具体问题具体分析的判断。
0 请登录后投票
   发表时间:2006-09-15  
Allen的方法时新版本的吧,
那个版本开始的?
0 请登录后投票
   发表时间:2006-09-15  
ylt 写道
Readonly 写道

我同意Readonly的观点。如果不用hql,想实现数据库兼容就太难了。
举个例子,在很多手工录入的表格中都要记录录入时间/操作人/备注,我在java中使用date/person/comment来表示,可是java的关键字和sql的是不一样的,不同数据库也有各自的扩展关键字,上面那几个字段很可能就是某种数据库的关键字。用hql,我所有的查询语句就可以保持统一,切换数据库只需要修改mapping。实际上我写了一个自动根据数据库关键字修改mapping的类,这样连mapping文件也只需要一个。

实现数据库兼容并不象你想象的那么难。:)
我做的平台软件在多种数据库上测试过,包括:Oracle9(10),SqlServer2000,MySql4(5),PostgreSQL8,
HyperSonic。
操作包括CRUD,查询也有比较复杂的。
兼容数据库的步骤如下:
1)数据库DDL是要自行处理的。当然可以借助PowerDesigner的自动转换数据库功能,虽然也有bug,其实主要无非就是一些数据类型的转换,手写也可。
2)CRUD之字段类型。JDBC的PreparedStatement已经帮你将所有的字段类型都封装了,不需要为了插入日期型等数据调用数据库本地的函数,ps.setDate()即可。
3)CRUD之SQL语法。ANSI SQL标准虽然贯彻得不够彻底,但常用的语法的确得到了一致认可。比如,表的左外连接在Oracle8里只有a.field1=b.feild2(+)这种方式,但在Oracle9以后,都支持标准的left outer join on语法了。这种语法在上述5种数据库都得到支持。其他的别名的语法也支持良好。
我碰到的一个比较搞的问题就是SQLserver2000种删除语句不能给表设置别名,即不能delete from TABLE a where a.id=?,去除别名无问题。
4)结果分页。这个的确是我碰到的最需额外处理等问题。我就是参考了hibernate的方法解决的。
5)ID生成问题。不同数据库有各自优化的方式,也可以使用通用的方式。也参考hibernate。
6)其他问题。比如Oracle里的hierachical query(connect by语句)在其他的数据库可能没有对等的实现方式,此时无法对此特性跨平台了。



sql 2000删除时可以设置别名的delete a from table a where a.id = ?
安全起见的话还是需要加一个SQL处理的,毕竟函数 CASE这些也算基本查询了 但不同还是很大的
CRUD问题不大
0 请登录后投票
   发表时间:2006-09-16  
最不爽的是这个。
http://www.iteye.com/topic/244
没想到hibernate性能这个差。
莫非hibernate3.1用了ejb?为什么速度这么慢?
如果这么慢的话,那对于压力比较大的业务,hibernate其实是不能用的。
0 请登录后投票
论坛首页 Java企业应用版

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