读书人

现在小弟我们在hibernate中还需要使用

发布时间: 2012-11-07 09:56:10 作者: rapoo

现在我们在hibernate中还需要使用多表查询吗?

最近我和一朋友讨论如何在在spring+hibernate框架下设计通用的查询程序。设计通用的查询程序,对于单表查询比较容易,只要把要查询的值对象和查询条件作为条件传递给后台就可以执行查询了。而从结果集中取值也比较容易,因为结果集就是这个值对象的集合。但要是设计一个通用的多表查询程序就比较复杂了,涉及多个值对象、值对象的关联、查询条件的前缀、取值等等问题。我提出一个观点,现在的hibernate可以不需要多表查询,运用单表查询以及值对象的各种关系就可以完全实现所有多表查询的功能。

为什么这么说呢?比如我们需要获得一个部门及其下面的所有员工。过去我们需要将部门和员工这2个表进行关联进行多表查询,但现在我们只需要在设计部门值对象的时候为其增加一个一对多关联,然后通过单表查询部门表,在每个部门值对象的员工属性中就有其所有的员工了。再比如,如果我们需要在查询员工的时候显示各个员工所在部门的部门名称,现在我们也同样不需要多表查询了。只需要在员工值对象中建立员工到部门的多对一关系,在单表查询员工的时候,每个员工值对象中都有部门属性,对应的是部门值对象,包含了其所在部门的全部信息。

以上提供了运用单表查询以及值对象的各种关系替代多表查询最常见的2种情况,而hibernate还提供了一对一、多对多、3种继承关系,我认为可以含盖几乎所有需要使用多表查询的应用。所以我认为,hibernate发展到现在,我们可以几乎不需要使用多表查询。编写一个通用的单表查询程序就可以应付大多数使用hibernate的查询程序,除了复杂查询。hibernate不适用于复杂查询,不论是易用性、效率来看都不适合。

28 楼 fangang 2007-10-12 coolnight 写道需要分页的时候, 这一对多关联如何做??

使用一对多实现分页非常麻烦,如果你需要使用一对多又要实现分页的使用,换个思路,改成多对一就可以所有这些功能。比如:

我需要显示某个部门的信息,同时又要显示该部门下的所有员工。如果采用一对多可以一次查询就实现了,即load该部门,该部门值对象的employees属性就是所有员工的信息。但是如果显示的员工需要分页就不能这样做了。那么就反过来采用多对一,查询employee,条件是employee.department=:department。这样的查询可以轻松实现分页,并且每个employee都有完整的department的信息可以用。

关于分页的实现我的示例http://fangang.iteye.com/blog/120768中的com.htxx.service.dao.BasicDao可以给你一点儿参考。 29 楼 kevin_gzhz 2007-10-15 Hibernate确实是个好东东,但对于复杂查询存在性能上的缺陷;而用jdbc能解决性能问题,但写起来也太过繁琐.我相信很多用过了Hibernate的朋友在大多数情况下都不愿意回到用jdbc的年代.我前一个项目里有一个统计子系统,当牵涉到3张以上的表时,Hibernate就是一头老牛,怎么拉都不走,还常报内存溢出.但有不想在代码里写sql,想到的方法采用视图来进行数据汇总,然后用Hibernate对视图进行操作,速度提搞了,有免了去写sql.但在处理只取某个持久化对象的少量属性时,为了节约内存资源,写类似sql的hql很有必要! 30 楼 fangang 2007-10-15 总结起来,使用hibernate完成复杂查询有性能问题似乎大家都没有异议,而解决办法有二:使用视图和JDBC。使用视图,既可以使用SQL建立视图,解决hibernate不能解决的问题,又可以对视图建值对象,使得JDBC和hibernate这对熊掌和鱼可以兼得,着实不错。如果通过spring的代理使用JDBC,其实编程也是挺简单的,少了很多需要考虑的问题(如获得连接、传值、关闭连接、内存泄漏等问题)。更重要是通过JDBC可以将SQL保存在数据库或配置文件中,增加系统灵活性和可维护性。而有些操作,如blob、clob采用JDBC似乎也更加可靠一些。 31 楼 kaki 2007-10-16 也就是说把复杂的东西交给数据库处理?? 32 楼 guofei_gf 2007-10-17 哪个适用选哪个 33 楼 kyo100900 2007-10-17 你的选择也决定你的代码量,一般来说大家更喜欢偷懒吧。呵呵 34 楼 fangang 2007-10-18 kyo100900 写道你的选择也决定你的代码量,一般来说大家更喜欢偷懒吧。呵呵

我是比较喜欢偷懒的那种懒汉,哈哈。不过我始终相信代码少出错也就少。 35 楼 devil_javaMode 2008-04-17 总的来说。看了这多收获不少。
我对于复杂查询一般都采用jdbc,有时候其实蛮享受那种拼结sql语句的感觉`呵呵。 36 楼 beyondqinghua 2008-04-17 是的,使用spring结合hibernate来操作是不会出现问题,
但是LZ有没有碰到过这种问题,以前我做的一些东西没有使用spring来管理hibernate进行数据库操作,而是使用hibernate直接查询数据库,多表查询的时候如果只是加载单个表,比如部门和员工是一对多的,如果我把部门的信息放在List里面,查询结束后需要session.close()吧,如果我再用list去读取员工的数据,将会出现session is closed错误,数据不能进行lazing!

37 楼 Fly_m 2008-04-18 spring的openSessionInViewFilter是个好东东.
复杂的东西还是由jdbc吧,hibernate管不了那个. 38 楼 rukyo 2008-04-21 搞个报表就够你受了,当然有需要多表的时候。 39 楼 rukyo 2008-04-21 我觉得复杂查询时候还是需要用jdbc,把sql写在配置文件中 40 楼 maming2000 2008-05-05 作view正解,只读表很好用,当成一个只读业务对象就OK了。 41 楼 nbawukun 2008-05-07 hibernate对于连接查询的支持不是很好,实际项目中还是有必要使用连接查询的,如果直接根据hibernate的映射关系来获得对象,有的时候效率很低,它莫名其妙的生成了很多乱七八杂的sql语句 42 楼 lwqenter 2012-05-06 fangang 写道在数据库中建索引当然是有必要(谈到索引罗嗦一下,索引在精而不在多,使用的字段一定要有选择性,也就是当该字段的值确定以后查询出来的结果尽量上那么这个字段的选择性就高),但站在hibernate的角度说,如果不能使用延迟查询,应当尽量不用一对多和多对多关系,也尽量不要采用双向关联。

另外,使用hibernate2也不是完全不能用延迟查询。如果将bus设置为要用事务处理,并且在bus层保证在bus以下各层要使用的属性,bus都已经预装载了,同样可以使用延迟查询来提高运行效率。在我的示例http://fangang.iteye.com/blog/120768中的com.htxx.service.dao.LasyPropertyProxy也许在预装载方面给你一些提示。



使用的字段一定要有选择性,也就是当该字段的值确定以后查询出来的结果尽量上那么这个字段的选择性就高
---这块没看懂,使用的字段是指做索引的字段吗,后面这句是什么意思

不能使用延迟查询---什么情况下不能使用延迟查询?很多时候都是要显示关联的例表的啊,都要显示数据,这时就不能使用延迟查询,是这样吗 43 楼 lwqenter 2012-05-06 uuidfangang 写道seacat 写道Java对象没必要一直存在于内存中
你的意思是hibernate没有必要做缓存吗?如果是这样我倒是有一些不同的看法。现在我们是3层结构,就意味着应用服务器与数据库服务器是2个不同的机器。当客户发出请求时,如果仅仅在应用服务器上进行运算以后向客户反馈,当然比从应用服务器到数据库服务器,再返回结果集到应用服务器,再反馈客户的效率高。因此,我们在编写java代码的时候,应当考虑尽量少的访问数据库。hibernate通过uuid获得主键就是一个很好的例子。从这个角度理解,hibernate采用应用服务器端的数据缓存对于提高效率就显得比较重要了,它可以大大降低应用服务器对数据库的访问。

-----
我们项目用的数据库是mysql,楼主对uuid+innodb(表引擎)性能很低有什么看法和办法?
44 楼 lwqenter 2012-05-06 楼主的hiberante查询篇让人受教了 45 楼 fangang 2012-05-08 lwqenter 写道我们项目用的数据库是mysql,楼主对uuid+innodb(表引擎)性能很低有什么看法和办法?

不要这样使用,效率非常差。如果生成主键时需要从数据库端生成,那么无疑将增大数据库的访问次数,那么就是降低系统运行效率。试想,在一次操作中,应用端生成主键访问一次数据库,执行持久化时访问数据库一次,就是2次;如果生成主键不访问数据库,仅持久化时访问数据库,数据库访问量将减少50%,性能将有多大的提升,特别在那些并发访问压力巨大的系统中。因此我采用的策略就是uuid,uuid虽然从理论上可能出现重复,但概率简直是千年等一回。

但uuid的缺陷是无序,如果用户要求一个有序的编号时,就需要innodb,但建议不要建在主键里,另做一个字段 46 楼 fangang 2012-05-08 lwqenter 写道使用的字段一定要有选择性,也就是当该字段的值确定以后查询出来的结果尽量上那么这个字段的选择性就高
---这块没看懂,使用的字段是指做索引的字段吗,后面这句是什么意思

不能使用延迟查询---什么情况下不能使用延迟查询?很多时候都是要显示关联的例表的啊,都要显示数据,这时就不能使用延迟查询,是这样吗

数据库建索引是非常有讲究的,建得不好反倒会降低查询效率。一般来说,索引字段必须有选择性,什么意思?比如说,采用主键选择性最强,因为输入一个主键值只能获得一条记录;采用一些序号、日期次之,假如一个表单表,一日生成数据数十条,当输入一个日期时产生的结果也就数十条,如果采用一些序号,可能产生数据就几条,我说的序号是指那些一个表对另一个表主键的引用。采用各种代码编号是选择性最差的,一般都不建议采用,比如一个代码有10条记录,另一个100万的表用了一个代码,那么输入一个代码产生的结果将是10万条记录。用这样的索引不如不用。记住,假如输入任意一个值得到的结果越少,那么这个字段的选择性就越高。

延迟加载在BUS层是有效的、在MVC层是有效的,但再往前端呢,到页面端就无效了,所以如果到页面端再去访问某个属性就什么也得不到了,需要预先加载。这问题在使用dwr框架的系统中特别突出。 47 楼 lwqenter 2012-05-09 fangang 写道lwqenter 写道我们项目用的数据库是mysql,楼主对uuid+innodb(表引擎)性能很低有什么看法和办法?

不要这样使用,效率非常差。如果生成主键时需要从数据库端生成,那么无疑将增大数据库的访问次数,那么就是降低系统运行效率。试想,在一次操作中,应用端生成主键访问一次数据库,执行持久化时访问数据库一次,就是2次;如果生成主键不访问数据库,仅持久化时访问数据库,数据库访问量将减少50%,性能将有多大的提升,特别在那些并发访问压力巨大的系统中。因此我采用的策略就是uuid,uuid虽然从理论上可能出现重复,但概率简直是千年等一回。

但uuid的缺陷是无序,如果用户要求一个有序的编号时,就需要innodb,但建议不要建在主键里,另做一个字段
-----
我们的主键用的就是hibernate的UUID,同时我们的需求要处理事务,所以用了innodb,正如你所说uuid是无序的,但innodb是进行有序挺入的,所以效率就很低,还没找到好的解决办法

读书人网 >软件架构设计

热点推荐