绕过Hibernate API ,直接通过 JDBC API
- 格式:doc
- 大小:60.00 KB
- 文档页数:9
1. Hibernate获取数据方式 Hibernate获取数据的方式有不同的几种,其与缓存结合使用的效果也不尽相同,而Hibernate中具体怎么使用缓存其实是我们很关心的一个问题,直接涉及到性能方面。 缓存在Hibernate中主要有三个方面:一级缓存、二级缓存和查询缓存;一级缓存在Hibernate中对应的即为session范围的缓存,也就是当 session关闭时缓存即被清除,一级缓存在Hibernate中是不可配置的部分;二级缓存在Hibernate中对应的即为 SessionFactory范围的缓存,通常来讲SessionFactory的生命周期和应用的生命周期相同,所以可以看成是进程缓存或集群缓存,二级缓存在Hibernate中是可以配置的,可以通过class-cache配置类粒度级别的缓存(class-cache在class中数据发生任何变化的情况下自动更新),同时也可通过collection-cache配置集合粒度级别的缓存(collection-cache仅在 collection中增加了元素或者删除了元素的情况下才自动更新,也就是当collection中元素发生值的变化的
2. Hibernate批处理的实例分析 1:绕过Hibernate API ,直接通过 JDBC API 来做,这个方法性能上是比较好的,也是最快的。(实例为 更新操作)
................. Transaction tx=session.beginTransaction(); //注意用的是hibernate事务处理边界 Connection conn=session.connection(); PreparedStatement stmt=conn.preparedStatement("update CUSTOMER as C set C.sarlary=c.sarlary+1 where c.sarlary>1000"); stmt.excuteUpdate(); tx.commit(); //注意用的是hibernate事务处理边界
这小程序中,采用的是直接调用JDBC 的API 来访问数据库,效率很高。避免了Hibernate 先查询出来加载到内存,再进行操作引发的性能问题。
2:运用存储过程。以上两种方法,可以参考我博客引用的相关文章。(实例为 更新操作) 如果底层数据库(如Oracle)支持存储过程,也可以通过存储过程来执行批量更新。存储过程直接在数据库中运行,速度更加快。在Oracle数据库中可以定义一个名为batchUpdateCustomer()的存储过程,代码如下:
代码内容 create or replace procedure batchUpdateCustomer(p_age in number) as begin update CUSTOMERS set AGE=AGE+1 where AGE>p_age; end;
以上存储过程有一个参数p_age,代表客户的年龄,应用程序可按照以下方式调用存储过程: 代码内容 tx = session.beginTransaction(); Connection con=session.connection(); String procedure = "{call batchUpdateCustomer(?) }"; CallableStatement cstmt = con.prepareCall(procedure); cstmt.setInt(1,0); //把年龄参数设为0 cstmt.executeUpdate(); tx.commit();
从上面程序看出,应用程序也必须绕过Hibernate API,直接通过JDBC API来调用存储过程。 3:还是用Hibernate API 来进行常规的批量处理,可以也有变,变就变在,我们可以在查找出一定的量的时候,及时的将这些数据做完操作就删掉,session.flush();session.evict(XX对象集); 这样也可以挽救一点性能损失。这个“一定的量”要就要根据实际情况做定量参考了。。(实例为 保存操作)
业务逻辑为:我们要想数据库插入10 0000 条数据 tx=session.beginTransaction(); for(int i=0;i<100000;i++) { Customer custom=new Customer(); custom.setName("user"+i); session.save(custom); if(i%50==0) // 以每50个数据作为一个处理单元,也就是我上面说的“一定的量”,这个量是要酌情考虑的 { session.flush(); session.clear(); } } 这样可以把系统维持在一个稳定的范围....
3.Struts+Hibernate+Oracle应该注意的问题 由于项目需要,我用Struts+Hibernate+Oracle来开发一些模块,熟悉Mysql,MSSQL 的我,在以前做一些模块的时候用这两个数据库都可以运行顺畅,今天用Oracle 就遇到了一些问题。
我用Oracle的Sequences 来维护主键ID的生成,在Oracle定义好了一个sequence ,名为"QINGJIA",如果你不在某些地方声明它的话,Hibernate是不会自动识别的,hibernate就使用默认的名为"hibernate_sequence" 的sequence 。最后才发现应该在相应的xx.hbm.xml里配置,如下:
QINGJIA
要在这一项里配置这个sequence。 这样在生成ID 的时候,hibernate就会识别了.....哈哈.... 还有一点要注释的是,ID 生成器选为sequence,是采用数据库提供的sequence机制生成主键,这里Oracle 就用到了。 使用native 是最好的,它具有很好的跨平台性。
4. 详解ehcache.xml文件中cache配置参数
今天开发过程中无意间就接触到了这个文件(ehcache.xml),经了解它是Hibernate 的缓存配置文件,和hibernate.cfg.xml 放在一起的。这对以后大量数据操作提供一个很好优化方案。 现在就给出各项的注释: maxElementsInMemory="10000" //缓存中最大允许创建的对象数 eternal="false" //缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期 timeToIdleSeconds="120" //缓存数据钝化时间(设置对象在它过期之前的空闲时间) timeToLiveSeconds="120" //缓存数据的生存时间(设置对象在它过期之前的生存时间) overflowToDisk="true" //内存不足时,是否启用磁盘缓存 /> 5. Hibernate批量处理--之我见 Hibernate批量处理其实从性能上考虑,它是很不可取的,浪费了很大的内存。从它的机制上讲,Hibernate它是先把符合条件的数据查出来,放到内存当中,然后再进行操作。
我想到的有三种来处理以解决性能问题: 1:绕过Hibernate API ,直接通过 JDBC API 来做,这个方法性能上是比较好的。也是最快的. 2:运用存储过程。以上两种方法,可以参考我博客引用的相关文章。 3:还是用Hibernate API 来进行常规的批量处理,可以也有变,变就变在,我们可以在查找出一定的量的时候,及时的将这些数据做完操作就删掉,session.flush();session.evict(XX对象集); 这样也可以挽救一点性能损失。这个“一定的量”要就要根据实际情况做定量参考了。
稍后些时间,我会为这3种方法整理出 具体的实例,以供大家参考!请关注...... 关于Hibernate的批量处理操作的 评议 批量更新是指在一个事务中更新大批量数据,批量删除是指在一个事务中删除大批量数据。以下程序直接通过Hibernate API批量更新CUSTOMERS表中年龄大于零的所有记录的AGE字段: 代码内容 tx = session.beginTransaction(); Iterator customers=session.find("from Customer c where c.age>0").iterator(); while(customers.hasNext()){ Customer customer=(Customer)customers.next(); customer.setAge(customer.getAge()+1); } tx.commit(); session.close(); 如果CUSTOMERS表中有1万条年龄大于零的记录,那么Session的find()方法会一下子加载1万个Customer对象到内存。当执行tx.commit()方法时,会清理缓存,Hibernate执行1万条更新CUSTOMERS表的update语句: 代码内容 update CUSTOMERS set AGE=? „. where ID=i; update CUSTOMERS set AGE=? „. where ID=j; update CUSTOMERS set AGE=? „. where ID=k; 以上批量更新方式有两个缺点: (1) 占用大量内存,必须把1万个Customer对象先加载到内存,然后一一更新它们。 (2) 执行的update语句的数目太多,每个update语句只能更新一个Customer对象,必