您的位置:首页 > 其它

Hibernate的优缺点

2011-04-01 23:32 120 查看
优点: Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序实用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
大 多数开发机构经常采取创建各自独立的数据持久层。一旦底层的数据结构发生改变,那么修改应用的其余部分使之适应这种改变的代价将是十分巨大的。 Hibernate适时的填补了这一空白,它为Java应用提供了一个易用的、高效率的对象关系映射框架。hibernate是个轻量级的持久性框架,功 能却非常丰富。hibernate它是一个开放源码的关系对象型框架,它对jdbc进行了非常轻量级的封装。使得程序员可以随心所欲的使用对象编程思维来操作数据库。 hibernate它可以应用在任何使用jdbc的场合,即可以在java客户端程序使用,也可以在servlet/jsp的web应用中使用。更具革命意义的是,可以代替在j2ee应用中的cmp,完成数据持久的重任。
大多数开发机构经常采取创建各自的数据持久层,一旦底层数据结构发生改变时,那么修改其余部分适应这种改变将花费的代价十分巨大。而hibernate适时的填补了这一空白,它为java提供了一个易用的,高效率的关系对象映射。它是一个轻量级的持久层框架,功能十分丰富。 hibernate使用java反射机制,而不是字节码增强程序来实现透明性。它性能非常好,因为它是轻量级框架,映射的灵活非常出色。它支持各种关系的数据库,从一对一到多对多的各种复杂关系。 缺 点:它限制您所使用的对象模型。( 优化: 有很多人认为Hibernate天生效率比较低,确实,在普遍情况下,需要将执行转换为SQL语句的
Hibernate的效率低于直接JDBC存取,然而,在经过比较好的性能优化之后,Hibernate的性能还是让人相当满意的,特别是应用二级缓存之 后,甚至可以获得比较不使用缓存的JDBC更好的性能,下面介绍一些通常的Hibernate的优化策略: 1.抓取优化 抓取是指Hibernate如何在关联关系之间进行导航的时候,Hibernate如何获取关联对象的策略,其主要定义了两个方面:如何抓取和何时抓取 1)如何抓取。 Hibernate3主要有两种种抓取方式,分别应用于对象关联实例(many-to-one、one-to-one)和对象关联集合(set、map等),总共是四种变种
JOIN抓取: 通过在SELECT语句中使用OUTER JOIN来获得对象的关联实例或者关联集合) SELECT抓取: 另外发送一条SELECT语句来抓取当前对象的关联实体和集合 在我的开发经历中,此处对性能的优化是比较有限的,并不值得过多关注 例: A.应用于对象关联实例(默认是false) B.应用于对象关联集合(默认是auto) .... 2)何时抓取 主要分为延迟加载和立即抓取,默认的情况下Hibernate3对对象关联实采用延迟加载,普通属性采用立即抓取,通过延迟加载和采用适当的抓取粒度,与不采用优化相比往往可以将性能提升数倍
立即抓取:当抓取宿主对象时,同时抓取其关联对象和关联集以及属性 延迟加载:当抓取宿主对象时,并不抓取其关联对象,而是当对其对象进行调用时才加载 例: A.应用于对象关联实例(默认是延迟加载) B.应用于对象关联集合(默认是延迟加载) .... 对于延迟加载,需要注意的时,对延迟对象的使用必须在Session关闭之前进行,Hibernate的 LazyInitalizationException往往就是由于在Session的生命期外使用了延迟加载的对象。当我们进行Web开发时,可以使用 OpenSessionInView模式,当请求开始时打开session,当请求响应结束时才关闭session,不过,在使用
OpenSessionInView模式时,需要注意如果响应时间比较长(业务比较复杂或者客户端是低速网络),将Session资源(也就是数据库的连 接)占用太久的话可以会导致资源耗尽 3)抓取粒度 抓取粒度指的是对象在关联关系之间被导航时一次预先加载的数量,Hibernate程序的性能比较差往往就在于没有对抓取粒度仔细考虑,当加载一个列表并在列表中的每个对象中对其关联进行导航时,往往导致N+1条SQL语句查询。 例: A.应用于对象关联实例(默认为1),注意,对对象关联实例的设置是在被关联的对象之上的,譬如
class User { Group g; } 那么抓取粒度应该在Group的配置文件之上,见下 ... 对该值并没有一个约定俗成的值,根据情况而定,如果被关联表数据比较少,则可以设置地小一些,3-20,如果比较大则可以设到30-50,注意的时候,并不是越多越好,当其值超过50之后,对性能并没有多大改善但却无谓地消耗内存 假设有如下例子: List users = query.list(); 如果有20个User,并对这20个User及其Group进行遍历,如果不设置batch-size(即batch-size="1"),则在最糟糕的情况
下,需要1 + 20条SQL语句,如果设置batch-size="10",则最好的情况下只需要1 + 2条SQL语句 B.应用于对象关联集合(默认为1) .... 2.二级缓存 Hibernate 对数据的缓存包括两个级:一级缓存,在Session的级别上进行,主要是对象缓存,以其id为键保存对象,在Session的生命期间存在;二级缓存, 在SessionFactory的级别上进行,有对象缓存和查询缓存,查询缓存以查询条件为键保存查询结果,在SessionFactory的生命期间存 在。默认地,Hibernate只启用一级缓存,通过正确地使用二级缓存,往往可以获得意想不到的性能。
1)对象缓存: 当抓取一个对象之后,Hiberate将其以id为键缓存起来,当下次碰到抓取id相同的对象时,可以使用如下配置 方法1:在缓存对象上配置 useage 表示使用什么类型的缓存,譬如只读缓存、读写缓存等等(具体参见Hibernate参考指南),值得注意的时,有部分缓存在Hibernate的实现中不 支持读写缓存,譬如JBossCache在Hibernate的实现中只是一种只读缓存,具体缓存实现对缓存类型的支持情况,可以参见 org.hibernate.cache包 regions表示缓存分块,大部分的缓存实现往往对缓存进行分块,该部分是可选的,详细参见各缓存实现
方法2:在hibernate.cfg.xml中配置 我认为第二种更好,可以统一管理 2)查询缓存 查询时候将查询结果以查询条件为键保存起来,需要配置如下 A.在hibernate.cfg.xml中配置(启用查询缓存) true (前面的属性名可参见常量 org.hibernate.cfg.Enviroment.USE_QUERY_CACHE) B.程序 query.setCacheable(true); query.setCacheRegions(...); 需要注意的是,查询缓存与对象缓存要结合更有效,因为查询缓存仅缓存查询结果列表的主键数据
一般情况下在开发中,对一些比较稳定而又被频繁引用的数据,譬如数据字典之类的,将其进行二级缓存,对一些查询条件和查询数据变化不频繁而又常常被使用的 查询,将其进行二级缓存。由于二级缓存是放在内存中,而且Hibernate的缓存不是弱引用缓存(WeekReference),所以注意不要将大块的 数据放入其中,否则可能会被内存造成比较大的压力。 3.批量数据操作 当进行大批量数据操作(几万甚至几十几百万)时,需要注意两点,一,批量提交,二,及时清除不需要的一级缓存数据 1) 所谓的批量提交,就是不要频繁使用session的flush,每一次进行flush,Hibernate将PO数据于数据库进行同步,对于海量级数据操
作来说是性能灾难(同时提交几千条数据和提交一条数据flush一次性能差别可能会是几十倍的差异)。一般将数据操作放在事务中,当事务提交时 Hibernate自动帮你进行flush操作。 2)及时清除不需要的一级缓存数据:由于Hibernate默认采用一级缓存,而在 session的生命期间,所有数据抓取之后会放入一级缓存中,而当数据规模比较庞大时,抓取到内存中的数据会让内存压力非常大,一般分批操作数据,被一 次操作之后将一级缓存清除,譬如 session.clear(User.class) 4.杂项 dynamic-insert,dynamic-update,动态插入和动态更新,指的是让Hibernate插入数据时仅插入非空数据,当修改数据时只修改变化的数据,譬如对于
class User { id username password } 如果u.id=1, u.username="ayufox",u.password=null,那么如果不设置动态插入,则其sql语句是 insert into users(id, username, password) values (1, 'ayufox', '),如果设置则其 sql语句是insert into users(username) valeus('ayufox') 在如上的情况下,如果修改 u.password='11',那么如果不设置动态更新,则sql语句为update
users set username='ayufox', password='11' where id = 1,如果设置则为update user set password='11' where d = 1 设置是在class的映射文件中,如下   该设置对性能的提升比较有限
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: