由于hibernate是对jdbc的一个封装,而且在session的缓存中存在着相互关联的对象。对于一个类的访问将导致对另外一个关联类的访问,这样将导致大量的sql语句产生,所以为了提升hibernate性能减少频繁访问数据库,就需要对hibernate进行优化。
我们知道在hibernate的默认情况下,比如:在一对多的情况下,当我们访问Customer类后,又同时访问它相关联的Order类,但是如果我们不需要order的信息呢?这将导致hibernate的性能下降。
怎么解决呢?下面我们看一下hibernate加载一个对象的方式有哪些?
1.立即加载
所谓立即加载,就是指当加载完实体对象后,立即加载其关联的对象数据,在Customer.hbm.xml里的内容为:
<set name="order" table="ord" cascade="all" lazy="false" inverse="true">
<key column="c_id"/>
<one-to-many class="com.lovo.Order"></one-to-many>
</set>
-------------------
从运行的结果中我们可以看出hibernate连续调用了两次sql,分别完成了对Customer和order对象的加载,这就是立即加载的基本原理,上面配置里面cascade="all"表示当我增删改这个实体时是不是要对相关联的实体进行增删改操作,在一般情况下用delete-update,lazy="false"表示立即加载这个对象,inverse="true"表示在一对多的情况下,把对象的加载交给多的一方进行维护。就好比zf和我们,zf不可能可照顾所有的人吧,得让我们自己照顾自己。呵呵,这个举例只是好理解而已。
2.延迟加载
当hibernate加载Customer对象时同时加载了关联的order对象,如果只需要读取Customer对象的信息而不需要读取order类的信息的话将会导致性能损耗,hibernate引入了延迟加载的方式避免了这一问题,
<set name="order" table="ord" cascade="all" lazy="true" inverse="true"><!--hibernate默认情况也是true-->
<key column="c_id"/>
<one-to-many class="com.lovo.Order"></one-to-many>
</set>
与立即加载不同之处在于,hibernate没有在加载Customer对象时就加载order对象并读取对象的信息,而是在调用customer.order.size()才会读取order的信息,这就是延迟加载的机制,当真正需要访问关联对象才执行sql语句进行数据读取。
3.预加载
所谓预加载就是指通过外连接(out-join)来获得对象的关联实例;
比如:Query query = session.createQuery("from Customer c left join c.order");
运行上面代码,hibernate会生成一条sql语句,相对于立即加载情况下的读取多条sql语句,预加载方式在性能上带来了更多的提升,减少了对数据库的访问次数,但是,我们发现预加载的情况下,关联对象的实例也会被创建。所以,这也是一种不推荐的加载方式,应当尽量使用延迟加载方式。
4.批量加载
hibernate中的批量加载就是批量提交多个限定条件,一次完成多个数据的读取,例如:
from Customer where c_id=1;
from Customer where c_id=2;
我们可以将其整合为一条语句:
from Customer where c_id in(1,2);
在hibernate的关联关系中,我们可以在立即加载和延迟加载里设定批量加载的数目,从而减少查询语句的数目,提高延迟加载和立即加载的性能。在映射文件中<set>元素的batch-size属性用于设置批量加载的数量,Customer类的映射文件有如下:
<set name="order" table="ord" cascade="all" lazy="true" inverse="true" batch-size="10"><!--一般小于10-->
<key column="c_id"/>
<one-to-many class="com.lovo.Order"></one-to-many>
</set>
可以发现在使用批量加载的情况下,select语句使用了in关键字来限定范围,从而减少了select语句的使用,而in所限定的范围大小与"batch-size"属性的值有关,值越小范围就越小,反之越大,一般来说batch-size属性设置为一个小于10的数值,由此可见,批量加载的方式可以成为延迟加载或立即加载的一种优化解决方案,采用这种方式抓取对象又被称为批量抓取(Batch fetching);
hibernate查询优化:
我们已经理解了hibernate中对象加载方式后,可以看出在hibernate中主要有如下几个方面来优化查询性能:
1.降低数据库的访问的次数和频率,减少select语句的数量,对延迟加载和立即加载设置批量抓取策略。
2.使用延迟加载,避免不需要的多余数据,
3.使用投影查询,避免查询数据占用缓存。
4.减少访问字段,降低访问数据库的数据量,利用query()对象的iterate()方法
query的list()和iterator方法都可以执行HQL查询语句,但是list()方法会直接操作sql访问数库,而iterator方法会根据主键字段到一、二级缓存里查找,如果有就加入到查询结果中,没有就执行额外的查询语句。
Query q1=session.createQuery("from Customer");
List it1=q1.list();
Query q2=session.createQuery("from Customer");
List it2=q2.iterate();
list()方法查询所有字段信息,而iterate()方法查询的却不是所有字段而是c_id,也就是说减少了访问字段,同时iterator()方法根据c_id再向缓存里进行查找对象,如果缓存里没有数据最后再进行数据库的访问。
hibernate缓存:
hibernate为什么要有缓存呢??和其它关系型数据库一样,
我们不可能每次相同的查询都去与数据库进行交互吧,也就是说hibernate的缓存就是一块内在空间,充当数据库在内存中的一个临时容器,当我们每次执行session.load(),save().update()时,或者query.list(),iterate()方法时,如果在Sesssion中不存在相应对象,hibernate就把该对象加入到缓存中。比如:我们查询ID为了的用户,由于第一次在缓存中没有,就与数据库进行交互,并且加入到一级缓存中,第二次呢?由于一级缓存中已经存在了,所以直接从一级缓存中获取数据,提高了查询性能。
缓存分为以下几种:
1。一级缓存:必须的,缓存中每个持久对象都对应一个OID,用clear()清除对象.
2.二级缓存:是一个处理分布式的缓存。不是必须的。在查询时首行是从一级缓存中查找,如果没有就去二级缓存中查找,二级缓存最大的好处在于提高了查询性能,但是,hibernate并没有提供二级缓存的实现,而是为第三方的缓存组件提供了接口,所以还需要配置。
3.查询缓存:使用查询缓存,如果查询结果集中包含实体,二级缓存中只会存放实体OID,如果查询部分属性,则二级缓存会存放所有属性值。hibernate默认是不进行查询缓存的。如果要进行缓存,需要调用Query.setCacheable(true)方法。
Session管理:
首先,什么是线程安全,什么是线程不安全??
线程安全:就是说可以有多个线程同时访问,
线程不安全:不能有多个线程访问。否则,会造成混乱。
在Session管理中SessionFacory是线程安全,它可以被多个线程同时访问,而Session是不安全的,以前我们是在每个方法里都会使用一个session,这样造成的结果是Session的频繁创建和销毁,内在消耗也相应增大了。在Session管理中,可以使用ThreadLocal模式,它为多线程的情况下并发访问问题提供了一种隔离机制,例如:
public static Session getSession(){
Session session=(Session)threadLocal.get();//获得session对象
if(session==null){
session = SessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
ThreadLocal的使用将使得我们在线程级进行Session重用,从而充分利用一缓存中的已有的数据,避免数据库访问开销的浪费和大量临时对象的反复创建。
hibernate的批量处理:加入10000条数据
PrepareStatement pst = conn.preparedStatement(...);
for(int i=0;i<10000;i++){
pst.addBatch();
}
int[] count=pre.executeBatch();
由于会产生大量的对象存放在内存中,所以性能不好
分享到:
相关推荐
《Hibernate性能优化》 在Java应用开发中,Hibernate作为一个强大的对象关系映射(ORM)框架,极大地简化了数据库操作。然而,如果不进行适当的优化,它可能会成为系统性能的瓶颈。以下是一些关于Hibernate性能优化...
### Hibernate性能优化研究 #### 一、引言 随着企业级应用的发展,高效的数据持久化技术成为了提升系统性能的关键因素之一。Hibernate作为一种流行的面向Java环境的对象关系映射(Object-Relational Mapping,简称...
### Hibernate性能优化方案详解 #### 一、引言 Hibernate作为Java领域中广泛使用的对象关系映射(ORM)框架,其高效性和灵活性受到众多开发者的青睐。然而,不当的设计和配置往往会导致性能瓶颈,严重影响应用程序...
"Hibernate性能优化共9页.pdf.zip" 这个文件标题表明了内容专注于Hibernate框架的性能优化,暗示我们将探讨如何提升使用Hibernate进行数据库操作时的效率。通常,性能优化涉及减少延迟、提高吞吐量、降低资源消耗等...
Hibernate 性能优化 在 Hibernate 中,性能优化是非常重要的,因为它直接影响着应用程序的效率和可扩展性。在本文中,我们将讨论两个常见的性能优化问题:批量处理和 1+n 问题,并提供相应的解决方法。 问题 1:...
本文将深入探讨Hibernate性能优化中的一个重要概念——一级缓存,并结合给出的压缩包文件“hibernate_cache_level1”,来详细解析一级缓存的工作原理及其优化策略。 一级缓存是Hibernate内置的一种缓存机制,它存在...
以下是对《hibernate性能优化[参考].pdf》内容的详细解读: 1. **数据库优化**: - **物理硬件优化**:关注磁盘的IO性能,因为数据库读写频繁,磁盘的寻道能力直接影响数据访问速度。 - **MySQL配置优化**:通过...
### Hibernate 性能优化 #### 一、引言 Hibernate 是一款非常强大的对象关系映射(ORM)框架,它能够简化 Java 应用程序与数据库之间的交互过程。然而,对于初次接触 Hibernate 的开发者来说,可能会遇到性能方面...
二级缓存是Hibernate性能优化的重要手段,通过合理配置和使用,可以显著减少数据库访问,提高系统响应速度。但同时,需要注意缓存的副作用,如数据一致性、并发控制等问题。在实际应用中,需要结合业务场景和性能...
在进行大型项目开发时,性能优化是至关重要的,特别是对于基于SSH(Struts、Spring、Hibernate)这样的企业级框架的应用。SSH性能优化主要是针对Struts的MVC处理、Spring的依赖注入以及Hibernate的对象关系映射进行...
### Hibernate性能调优知识...综上所述,Hibernate性能优化涉及多个层面,包括但不限于关联管理、集合类型选择、继承关系配置以及缓存策略等。合理配置这些选项能够显著提高应用程序的性能,并且减少不必要的资源消耗。
【标签】:hibernate, 性能优化 【正文】: 1. **数据库设计调整**: - **降低关联的复杂性**:减少多对多关联,避免过度嵌套的对象关系。 - **避免联合主键**:联合主键可能导致额外的性能损失,尝试使用单独的...