`
Sev7en_jun
  • 浏览: 1227584 次
  • 性别: Icon_minigender_1
  • 来自: 广州
博客专栏
84184fc0-d0b6-3f7f-a3f0-4202acb3caf5
Apache CXF使用s...
浏览量:111477
社区版块
存档分类
最新评论

iBATIS框架batch处理优化浅析

 
阅读更多

 

FROM:http://developer.51cto.com/art/200907/138664.htm

 

 

 

 

iBATIS框架batch处理优化的情况。为什么要做batch处理这个问题我就不解释了,因为我想你们肯定能比我解释的更好!如果你真的不知道,那就到雅虎上去搜索一下吧

Oracle回滚段

这个问题偶也不很明白,只是大概有个了解,如果你是这方面的专家,或者对这方面有比较深的理解,别忘了跟偶分享哦?

在JDBC中如何做batch处理

JDBC提供了数据库batch处理的能力,在数据大批量操作(新增、删除等)的情况下可以大幅度提升系统的性能。我以前接触的一个项目,在没有采用batch处理时,删除5万条数据大概要半个小时左右,后来对系统进行改造,采用了batch处理的方式,删除5万条数据基本上不会超过1分钟。看一段JDBC代码:

//关闭自动执行  
con.setAutoCommit(false);  
Statementstmt=con.createStatement();  
 
stmt.addBatch("INSERTINTOemployeesVALUES(1000,'JoeJones')");  
stmt.addBatch("INSERTINTOdepartmentsVALUES(260,'Shoe')");  
stmt.addBatch("INSERTINTOemp_deptVALUES(1000,260)");  
 
//提交一批要执行的更新命令  
int[]updateCounts=stmt.executeBatch(); 
本例中禁用了自动执行模式,从而在调用Statement.executeBatch()时可以防止JDBC执行事务处理。禁用自动执行使得应用程序能够在发生错误及批处理中的某些命令不能执行时决定是否执行事务处理。因此,当进行批处理更新时,通常应该关闭自动执行。

在JDBC2.0中,Statement对象能够记住可以一起提交执行的命令列表。创建语句时,与它关联的命令列表为空。Statement.addBatch()方法为调用语句的命令列表添加一个元素。如果批处理中包含有试图返回结果集的命令,则当调用Statement.executeBatch()时,将抛出SQLException。只有DDL和DML命令(它们只返回简单的更新计数)才能作为批处理的一部分来执行。如果应用程序决定不提交已经为某语句构
造的命令批处理,则可以调用方法Statement.clearBatch()(以上没有显示)来重新设置批处理。

Statement.executeBatch()方法将把命令批处理提交给基本DBMS来执行。命令的执行将依照在批处理中的添加顺序来进行。ExecuteBatch()为执行的命令返回更新计数数组。数组中对应于批处理中的每个命令都包含了一项,而数组中各元素依据命令的执行顺序(这还是和命令的最初添加顺序相同)来排序。调用executeBatch()将关闭发出调用的Statement对象的当前结果集(如果有一个结果集是打开的)。executeBatch()返回后,将重新将语句的内部批处理命令列表设置为空。

如果批处理中的某个命令无法正确执行,则ExecuteBatch()将抛出BatchUpdateException。可以调用BatchUpdateException.getUpdateCounts()方法来为批处理中成功执行的命令返回更新计数的整型数组。因为当有第一个命令返回错误时,Statement.executeBatch()就中止,而且这些命令是依据它们在批处理中的添加顺序而执行的。所以如果BatchUpdateException.getUpdateCounts()所返回的数组包含N个元素,这就意味着在调用executeBatch()时批处理中的前N个命令被成功执行。用PreparedStatement可以象下面这样写代码:

//关闭自动执行  
con.setAutoCommit(false);  
PreparedStatementstmt=con.prepareStatement("INSERTINTOemployeesVALUES(?,?)");  
 
stmt.setInt(1,2000);  
stmt.setString(2,"KellyKaufmann");  
stmt.addBatch();  
??? 
//提交要执行的批处理  
 
int[]updateCounts=stmt.executeBatch(); 
iBATIS框架对batch处理优化的支持

iBATIS框架对batch处理提供了很好的支持,底层的实现方式就是JDBC。下面看一段示例代码:

privatevoidexecute(SqlMapClientclient){  
if(log.isDebugEnabled()){  
log.debug("executestart...");  
}  
 
client.startBatch();  
 
for(inti=0;i<2000;i++){  
 
client.delete("deletefromorderwhereid=?",i);  
 
}  
 
client.executeBatch();  
 
if(log.isDebugEnabled()){  
log.debug("executeend...");  
}  
} 
iBATIS框架做batch处理的问题

在一个batch中只能对一个表进行操作,例如插入或删除。当有多个表需要处理时,只能放在多个batch中进行处理。看下面的一段代码:

代码1:

privatevoidexecute(intfrom,intto,Listlist){  
if(log.isDebugEnabled()){  
log.debug("STRGHousekeepTaskexecutestart...");  
}  
HKSqlMapWrappersqlWrapper=HKSqlMapWrapper.newInstance();  
sqlWrapper.startBatch();  
 
for(inti=from;i<to;i++){  
sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR_BL,list.get(i));  
sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR,list.get(i));  
sqlWrapper.delete(STRGHousekeepConstants.DELETE_CNTR,list.get(i));  
}  
sqlWrapper.execBatch();  
if(log.isDebugEnabled()){  
log.debug("STRGHousekeepTaskexecuteend...");  
}  
} 
这段代码的目的就是要删除数据库中3个表的数据,sqlWrapper是iBATIS的SqlMapClient的一个包装器,主要是封状对事物的控制。当批次(既to-from的值)很小的时候,这样写是没有问题的。尽管这段代码的本意是要享受batch处理带来的好处,但是事实上这段代码并不会真正达到预期的效果,至于原因,我们一会在进行分析?。我们先来看下面一段代码:

privatevoidexecute(intfrom,intto,Listlist){  
if(log.isDebugEnabled()){  
log.debug("STRGHousekeepTaskexecutestart...");  
}  
HKSqlMapWrappersqlWrapper=HKSqlMapWrapper.newInstance();  
sqlWrapper.startBatch();  
 
for(inti=from;i<to;i++){  
sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR_BL,list.get(i));  
}  
for(inti=from;i<to;i++){  
sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR,list.get(i));  
}  
for(inti=from;i<to;i++){  
sqlWrapper.delete(STRGHousekeepConstants.DELETE_CNTR,list.get(i));  
}  
sqlWrapper.execBatch();  
if(log.isDebugEnabled()){  
log.debug("STRGHousekeepTaskexecuteend...");  
}  
} 
代码2

正如你所看到的,和代码1相比它只是做了3次循环,每个循环执行一个表的操作。虽然麻烦,但是却真正的享受到了batch处理的好处!下面是时候解释一下这两段代码幕后的秘密了?。
在前面的章节里已经解释了JDBC如何做batch处理,如果还不清楚的话请查看前面的章节。要解释这两段代码里面的玄机,还得看一段代码?下面的代码是从iBATIS源码中提取的:

publicvoidaddBatch(RequestScoperequest,Connectionconn,Stringsql,Object[]parameters){  
PreparedStatementps=null;  
if(currentSql!=null 
&&sql.hashCode()==currentSql.hashCode()  
&&sql.length()==currentSql.length()){  
intlast=statementList.size()-1;  
ps=(PreparedStatement)statementList.get(last);  
}else{  
ps=conn.prepareStatement(sql);  
currentSql=sql;  
statementList.add(ps);  
}  
request.getParameterMap().setParameters(request,ps,parameters);  
ps.addBatch();  
size++;  
} 
这就是iBATIS中batch处理的做法,在这里不想对这段代码做一一解释,有兴趣的可以自己查看一下iBATIS的源码,我们只关心它如何对一条语句进行处理。参数sql是要进行batch处理的语句,parameters是sql的参数列表,如果sql和实例变量currentSql相等,则从statementList列表里面得到一个PreparedStatement,然后进行batch处理,如果不等就新生成一个PreparedStatement对象,并把它加到statementList列表里面,并把当前sql的值附给currentSql,下次传递来sql的时候就会和这个新的currentSql比较。这就是为什么在一个循环里面只对一个表进行处理的原因了。如果在一个循环里面对多个表进行处理,每次传给addBatch方法的sql都是新的,都会生成一个新的PreparedStatement,所以也就享受不到batch处理带来的好处了!

按照代码1的方式执行程序,当batchsize很小的时候尽管享受不到batch处理带来的好处,但是也不至于会出什么大问题,但是当batchsize值很大的时候(我在程序中试验过1000-5000范围),数据库就会报错了!错误是"toomanycourses",原因是每生成一个PreparedStatement实例,就会相应的生成一个course。假设batchsize是5000,要删除10个表的数据,那么产生的course的数目就是5000*10=50000,这对数据库来说是不能接受
的,所以就会报错。

如果按照代码2的的方式写程序肯定是没有问题的,只会生成10个PreparedStatement实例,相应的也只会生成10个course,这样就真正的享受到了batch处理带来的好处。但是,作为一名“挑剔”的程序员,我们怎么能容忍这样的写法呢?明明一个循环就可以搞定,现在要分成10个循环来做,非但效率上存在问题,大量重复的代码也让我们的程序显得很没“水准”。

既然第一种方式不能享受batch处理带来的好处,并且还会出错,第二种方式代码又非常的丑陋,那么我们就得想个办法来解决这个问题了。请记住:解决问题的过程就是一种享受?。

修改底层代码,支持多表batch处理.

既然出问题的地方找到了,那么解决它就很容易了。什么,你说还不知道问题出在哪?MyGod!Killme,pleale?!

在这里分享一下我的思路,把每次传近来的sql作为key、把生成的PreparedStatement实例作为value放在一个Map里以后每次传来sql时先判断在Map里有没有这个key,如果有就直接拿到它的value作为PreparedStatement实例,如果没有就新生成一个PreparedStatement实例并把它放到Map里。这样有几个sql就有几个PreparedStatement实例,和写多个循环效果是一样的。但写一个循环会更爽!
 

 

分享到:
评论

相关推荐

    iBATIS框架源码剖析

    iBATIS框架源码剖析

    ssh2+ibatis框架

    SSH2+IBATIS框架是Java开发中常用的一套企业级应用开发框架组合,它将Spring、Hibernate、Struts2和iBatis等组件融合在一起,以提高开发效率和实现松耦合。以下是对这些框架及其整合方式的详细说明: **Spring框架*...

    IBATIS框架搭建教程

    本教程聚焦于“IBATIS框架搭建”,它是一个流行的数据持久层框架,用于简化Java应用程序中的数据库操作。IBATIS的核心理念是将SQL语句与Java代码分离,提供灵活的映射机制,使得开发者能更好地控制SQL执行过程。 在...

    ibatis框架简单应用

    **Ibatis 框架简介** Ibatis 是一个优秀的、开源的 Java 数据访问框架,它提供了 SQL 映射功能,可以将 SQL 语句与 Java 代码分离,从而实现更灵活的数据访问。Ibatis 主要解决的问题是简化 JDBC 的繁琐工作,通过 ...

    SpringMvc+ibatis框架

    SpringMvc作为Spring框架的一部分,主要用于处理HTTP请求和视图的渲染,而iBatis则是一个轻量级的数据访问层框架,它将SQL与Java代码分离,提高了数据库操作的灵活性和可维护性。接下来,我们将深入探讨这两个框架的...

    iBATIS框架源码剖析pdf第二部分

    这部分内容对于理解iBATIS的工作流程至关重要,它将帮助你更好地调试和优化基于iBATIS的应用。 最后,你会了解到iBATIS与MyBatis的关系。MyBatis是iBATIS的后续版本,它在iBATIS的基础上进行了许多改进,包括更丰富...

    ibatis框架源码剖析光盘资料

    通过对源码的深入分析,我们可以理解ibatis的核心机制,掌握数据库操作的底层原理,从而更好地利用和优化这个强大的持久层框架。在这个压缩包中,包含的文件是《ibatis框架源码剖析》的全文内容。 ibatis作为一个轻...

    Ibatis 框架基础

    《Ibatis 框架基础详解》 Ibatis,作为一个轻量级的持久层框架,以其灵活、简单的特点在Java开发领域中广受欢迎。本文将深入解析Ibatis的基本概念、核心功能以及使用方法,帮助开发者更好地理解和应用这一框架。 ...

    IBatis框架简单例子

    自己写的ibatis例子,可以用来入门,也可以学习一下配置文件的配置方法,程序中对可以Student表进行增删改查,自己也可以根据需要添加新的方法,里面有源码和数据库脚本。有需要的,可以下过来看看。

    iBatis技术框架介绍

    iBatis技术框架介绍。ibatis2.x教程。

    ibatis框架理论学习

    iBATIS是一个流行的开源框架,主要用于处理关系数据库的交互操作。该框架最初由Clinton Begin创建,并随着时间的发展逐步演进,成为Java开发者中非常受欢迎的一个选项。iBATIS框架的核心特性在于提供了一种简便的...

    ibatis 框架原理实现

    **Ibatis 框架原理实现** Ibatis 是一个优秀的持久层框架,它允许开发者将SQL语句直接写在XML配置文件中,从而避免了Java代码与SQL的耦合,提高了开发效率。在这个自己编写的Ibatis框架实现中,我们可以看到类似的...

    springmvc ibatis框架

    Spring MVC 和 iBatis 是两个在 Java Web 开发中广泛使用的框架。Spring MVC 是 Spring 框架的一部分,主要用于构建 MVC(Model-View-Controller)架构的 Web 应用程序,而 iBatis 是一个轻量级的持久层框架,它提供...

    springmvc+ibatis 框架

    Spring MVC 和 iBatis 是两个在 Java Web 开发中广泛使用的框架,它们组合起来可以构建高效、灵活且可维护的Web应用程序。Spring MVC 作为Spring框架的一部分,是用于构建前端控制器(DispatcherServlet)的MVC设计...

    SpringMvc+Ibatis框架

    SpringMvc作为Spring框架的一部分,主要负责处理HTTP请求,实现Model-View-Controller(MVC)的设计模式,而iBatis则是一个轻量级的数据访问层框架,用于简化SQL操作。 SpringMvc框架的核心组件包括...

    iBATIS教程之快速入门浅析

    iBATIS 是一款轻量级的Java持久层框架,它主要负责对象关系映射(Object-Relational Mapping,简称O/R Mapping),使得开发者可以将关注点集中在业务逻辑上,而无需过多地处理数据库操作的细节。与Hibernate等其他...

    spring、struts、ibatis框架搭建流程

    ### Spring、Struts、iBatis框架搭建流程详解 #### 一、框架下载与准备 在构建基于Spring、Struts和iBatis的项目时,首先需要下载这些框架的最新版本,并进行相应的准备工作。 ##### 1. Struts2框架 Struts2是一...

    struts1+ibatis框架整合

    Struts1和iBatis是两个非常经典的Java Web开发框架,它们在早期的Web应用程序中广泛应用。...通过深入理解和实践这个Demo,开发者可以提升对这两个框架的掌握,同时也可以了解到如何在实际项目中进行框架的集成和优化。

Global site tag (gtag.js) - Google Analytics