hibernate处理批量更新和批量删除

来源:互联网 发布:标准英语发音软件 编辑:程序博客网 时间:2024/04/28 14:41
9.4 批量处理数据通常,在一个Session对象的缓存中只存放数量有限的持久化对象,等到Session对象处理事务完毕,还要关闭Session对象,从而及时释放Session的缓存占用的内存。批量处理数据是指在一个事务中处理大量数据。以下程序在一个事务中批量更新CUSTOMERS表中年龄大于零的所有记录的AGE字段:Transaction tx = session.beginTransaction();Iterator customers=session.createQuery("from Customer c where c.age>0").list().iterator();while(customers.hasNext()){Customer customer=(Customer)customers.next();customer.setAge(customer.getAge()+1);}tx.commit();session.close();如果CUSTOMERS表中有1万条年龄大于零的记录,那么Hibernate会一下子加载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万个Customer对象先加载到内存,然后一一更新它们。执行的update语句的数目太多,每个update语句只能更新一个Customer对象,必须通过1万条update语句才能更新1万个Customer对象,频繁地访问数据库,会大大降低应用的性能。一般说来,应该尽可能避免在应用层进行批量操作,而应该在数据库层直接进行批量操作,例如直接在数据库中执行用于批量更新或删除的SQL语句,如果批量操作的逻辑比较复杂,则可以通过直接在数据库中运行的存储过程来完成批量操作。并不是所有的数据库系统都支持存储过程。例如目前的MySQL就不支持存储过程,因此不能通过存储过程来进行批量更新或批量删除。当然,在应用层也可以进行批量操作,主要有以下方式:(1)通过Session来进行批量操作。(2)通过StatelessSession来进行批量操作。(3)通过HQL来进行批量操作。(4)直接通过JDBC API来进行批量操作。9.4.1 通过Session来进行批量操作Session的save()以及update()方法都会把处理的对象存放在自己的缓存中。如果通过一个Session对象来处理大量持久化对象,应该及时从缓存中清空已经处理完毕并且不会再访问的对象。具体的做法是在处理完一个对象或小批量对象后,立刻调用flush()方法清理缓存,然后再调用clear()方法清空缓存。通过Session来进行批量操作会受到以下约束:(1)需要在Hibernate的配置文件中设置JDBC单次批量处理的数目,合理的取值通常为10到50之间,例如:hibernate.jdbc.batch_size=20在按照本节介绍的方法进行批量操作时,应该保证每次向数据库发送的批量SQL语句数目与这个batch_size属性一致。(2)如果对象采用"identity"标识符生成器,则Hibernate无法在JDBC层进行批量插入操作。(3)进行批量操作时,建议关闭Hibernate的第二级缓存。本书的姊妹篇《精通Hibernate:高级篇》对第二级缓存做了详细介绍。Session的缓存为Hibernate的第一级缓存,通常它是事务范围内的缓存,也就是说,每个事务都有单独的第一级缓存。SessionFactory的外置缓存为Hibernate的第二级缓存,它是应用范围内的缓存,也就是说,所有事务都共享同一个第二级缓存。在任何情况下,Hibernate的第一级缓存总是可用的。而默认情况下,Hibernate的第二级缓存是关闭的,此外也可以在Hibernate的配置文件中通过如下方式显式关闭第二级缓存:hibernate.cache.use_second_level_cache=false1.批量插入数据以下代码一共向数据库中插入十万条CUSTOMERS记录,单次批量插入20条CUSTOMERS记录:Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();for ( int i=0; i<100000 i="" customer="" customer="new" customer="" session="" save="" customer="" if="" i="" 20="=" 0="" 20="" session="" flush="" 20="" sql="" insert="" session="" clear="" customer="" tx="" commit="" session="" close="" session="" flush="" 20="" session="" clear="" 20="" customer="" hibernate="" hibernate="" jdbc="" batch_size="" 20="" session="" customer="" customer="" identity="" 2="" session="" org="" hibernate="" scrollableresults="" query="" scroll="" scrollableresults="" customer="" scrollableresults="" customer="" session="" session="sessionFactory.openSession();" transaction="" tx="session.beginTransaction();" scrollableresults="" customers="session.createQuery('from" customer="" scroll="" scrollmode="" forward_only="" int="" count="0;" while="" customers="" next="" customer="" customer="(Customer)" customers="" get="" 0="" customer="" setage="" customer="" getage="" 1="" customer="" age="" if="" count="" 20="=" 0="" 20="" session="" flush="" 20="" sql="" update="" session="" clear="" customer="" tx="" commit="" session="" close="" query="" scroll="" scrollableresults="" customer="" customers="" scrollableresults="" customer="" hibernate="" hibernate="" jdbc="" batch_size="" 20="" scrollableresults="" customers="session.createQuery('from" customer="" setcachemode="" cachemode="" ignore="" scroll="" scrollmode="" forward_only="" 9="" 4="" 2="" statelesssession="" session="" session="" session="" statelesssession="" statelesssession="" statelesssession="" session="sessionFactory.openStatelessSession();" transaction="" tx="session.beginTransaction();" scrollableresults="" customers="session.getNamedQuery('GetCustomers')" scroll="" scrollmode="" forward_only="" while="" customers="" next="" customer="" customer="(Customer)" customers="" get="" 0="" customer="" setage="" customer="" getage="" 1="" customer="" age="" session="" update="" customer="" update="" customers="" tx="" commit="" session="" close="" statelesssession="" session="" statelesssession="" session="" 1="" statelesssession="" statelesssession="" 2="" statelesssession="" hibernate="" 3="" statelesssession="" save="" update="" delete="" sql="" sql="" 4="" statelesssession="" customer="" statelesssession="" update="" 5="" statelesssession="" statelesssession="" customer="" order="" 6="" statelesssession="" interceptor="" hibernate="" 7="" statelesssession="" oid="" 1="" customer="" customer="" statelesssession="" session="sessionFactory.openStatelessSession();" customer="" c1="(Customer)session.get(Customer.class,new" long="" 1="" customer="" c2="(Customer)session.get(Customer.class,new" long="" 1="" system="" out="" println="" c1="=c2);" false="" 9="" 4="" 3="" hql="" hibernate3="" hql="" hibernate="" query="" language="" hibernate="" session="" query="" executeupdate="" jdbc="" api="" preparedstatement="" executeupdate="" hql="" sql="" 1="" hql="" customer="" session="" session="sessionFactory.openSession();" transaction="" tx="session.beginTransaction();" string="" hqlupdate="update Customer c set c.name = :newName where c.name = :oldName" int="" updatedentities="session.createQuery(" hqlupdate="" setstring="" newname="" mike="" setstring="" oldname="" tom="" executeupdate="" tx="" commit="" session="" close="" sql="" update="" customers="" set="" name="Mike" where="" name="Tom" 2="" session="" delete="" hql="" customer="" session="" session="sessionFactory.openSession();" transaction="" tx="session.beginTransaction();" string="" hqldelete="delete Customer c where c.name = :oldName" int="" deletedentities="session.createQuery(" hqldelete="" setstring="" oldname="" tom="" executeupdate="" tx="" commit="" session="" close="" sql="" delete="" from="" customers="" where="" name="Tom" 3="" hql="" insert="" into="" entityname="" properties_list="" select_statement="" entityname="" properties_list="" select_statement="" hql="" insert="" into="" select="" insert="" into="" values="" hql="" delinquentaccount="" customer="" id="" name="" delinquent_accounts="" customers="" delinquentaccount="" hbm="" xml="" customer="" hbm="" xml="" customers="" delinquent_accounts="" session="" session="sessionFactory.openSession();" transaction="" tx="session.beginTransaction();" string="" hqlinsert="insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where c.id>1" int="" createdentities="s.createQuery(" hqlinsert="" executeupdate="" tx="" commit="" session="" close="" sql="" insert="" into="" delinquent_accounts="" id="" name="" select="" id="" name="" from="" customers="" where="" id="">19.4.4 直接通过JDBC API来进行批量操作当通过JDBC API来执行SQL insert、update和delete语句时,SQL语句中涉及到的数据不会被加载到内存中,因此不会占用内存空间。以下程序直接通过JDBC API来执行用于批量更新的SQL语句:Transaction tx = session.beginTransaction();//获得该Session使用的数据库连接java.sql.Connection con=session.connection();//通过JDBC API执行用于批量更新的SQL语句PreparedStatement stmt=con.prepareStatement("update CUSTOMERS set AGE=AGE+1 "+"where AGE>0 ");stmt.executeUpdate();tx.commit();以上程序通过Session的connection()方法获得该Session使用的数据库连接,然后通过它创建PreparedStatement对象并执行SQL语句。值得注意的是,应用程序仍然通过Hibernate的Transaction接口来声明事务边界。值得注意的是,在Hibernate3中,尽管Session的connection()方法还存在,但是已经被废弃,不提倡使用了,不过Hibernate3提供了替代方案:org.hibernate.jdbc.Work接口表示直接通过JDBC API来访问数据库的操作,Work接口的execute()方法用于执行直接通过JDBC API来访问数据库的操作:public interface Work {//直接通过JDBC API来访问数据库的操作public void execute(Connection connection) throws SQLException;}Session的doWork(Work work)方法用于执行Work对象指定的操作,即调用Work对象的execute()方法。Session会把当前使用的数据库连接传给execute()方法。以下程序演示了通过Work接口以及Session的doWork()方法来执行批量操作的过程:Transaction tx=session.beginTransaction();//定义一个匿名类,实现了Work接口Work work=new Work(){public void execute(Connection connection)throws SQLException{//通过JDBC API执行用于批量更新的SQL语句PreparedStatement stmt=connection.prepareStatement("update CUSTOMERS set AGE=AGE+1 "+"where AGE>0 ");stmt.executeUpdate();}};//执行worksession.doWork(work);tx.commit();当通过JDBC API中的PreparedStatement接口来执行SQL语句时,SQL语句中涉及到的数据不会被加载到Session的缓存中,因此不会占用内存空间。
0 0