Ⅰ java中的通过JDBC事务批量提交的问题,我的代码如下,问题是不回滚.大神帮我看看什么原因
getPreparedStatement(conn,sql,item);
方法是干啥的,贴出来
其实问题很简单
MyLog.e(">>>提交之前<<<");
//在try块内添加事务的提交操作,表示操作无异常,提交事务。
conn.commit();//此处都没有执行到
MyLog.e(">>>全部提交了<<<");
}catch(SQLExceptione){
isInsertOk=false;
MyLog.e(">>>出错,准备rollback<<<");
try{
上面的那个SQLException e
换成 Exception e 应该就可以了,
Ⅱ java,jdbc,大量数据update更新效率很慢,哪位大神可怜可怜我吧
mysql使用jdbc的批量插入需要在连接Mysql的地方加上rewriteBatchedStatements=true
,也就是spring.datasource.url = jdbc:mysql://192.168.15.44:3306/ml_test?useSSL=false&useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true
,如果不加这个的话,和自己循环插入差不多
Ⅲ java的jdbc批量更新使用了PreparedStatement的addBatch方法,添加了事务不回滚..
事务是不是没有开启啊?感觉你写的事务不对,conn是个连接吧
Ⅳ 关于JDBC批量操作中异常BatchUpdateException的getUpdateCounts()方法
此类问题的出现主要来自三个方面。
1、 SQL语句中存在语法错误或是传入的数据有误;
2、 数据库的配置不合法,或者说是配置有误。较容易出现的有数据表的映射文件(,hbm.xml文件)配置有误;Hibernate.cfg.xml文件配置有误;
3、 当前的数据库用户权限不足,不能操作数据库。以是以Oracle 数据库为例,这种情况下在错误提示中会显示java.sql.BatchUpdateException: ORA-01031: insufficient privileges这样的信息。
Ⅳ jdbc一次批量处理多少条数据
作为一个替代方案,可以试试使用Statement 的批量处理特性看看能否同时执行所有的SQL以提高速度。 存储过程的最简单的形式就是包含一系列SQL语句的过程,将这些语句放在一起便于在同一个地方管理也可以提高速度。Statement 类可以包含一系列SQL语句,因此允许在同一个数据库事务执行所有的那些语句而不是执行对数据库的一系列调用。 使用批量处理功能涉及下面的两个方法: · addBatch(String) 方法 · executeBatch方法 如果你正在使用Statement 那么addBatch 方法可以接受一个通常的SQL语句,或者如果你在使用PreparedStatement ,那么也可以什么都不向它增加。executeBatch 方法执行那些SQL语句并返回一个int值的数组,这个数组包含每个语句影响的数据的行数。如果将一个SELECT语句或者其他返回一个ResultSet的SQL语句放入批量处理中就会导致一个SQLException异常。 关于java.sql.Statement 的简单范例可以是: Statement stmt = conn.createStatement(); stmt.insert(DELETE FROM Users); stmt.insert(INSERT INTO Users VALUES(rod, 37, circle)); stmt.insert(INSERT INTO Users VALUES(jane, 33, triangle)); stmt.insert(INSERT INTO Users VALUES(freddy, 29, square)); int[] counts = stmt.executeBatch(); PreparedStatement 有些不同,它只能处理一部分SQL语法,但是可以有很多参数,因此重写上面的范例的一部分就可以得到下面的结果: // 注意这里没有DELETE语句 PreparedStatement stmt = conn.prepareStatement(INSERT INTO Users VALUES(?,?,?));
Ⅵ java JDBC 批量插入的时候报数组下标越界,求大神
擦
已经解决:原因是
我insert_st.setString(1,
ZH_S(user.getId()));,传递的参数过多,Oracle的批处理个数限制为:
count=传参个数
*
查入的数据条数
上边设置的1000条数据,进行一次批处理,越界了~
将
final
int
batchSize
=
500;
的值设小一点就屁事没有
Ⅶ Java中怎样实现批量删除操作
本文是记录Java中实现批量删除操纵(Java对数据库进行事务处置),在开始之前先来看上面这样的一个页面图:
上面这张图片表现的是从数据库中查询出的出租信息,信息中进行了分页处置,然后每行的后面提供了一个复选按钮和对应的一个删除操纵,可以选中多个进行操纵,这里主要是进行删除操纵。在执行删除操纵之前先要选中对应的行信息,点击删除选中按钮进行删除。当进行多条信息删除的时候,需要使用java的事务处置机制对数据库进行删除,也就是说删除的时候如果选中的要删除的说有信息其中一条没有成功删除的话,那么就都不删除。
现在是在java中对数据库实现这一操纵,我们可看上面的代码,它实现了对数据库的批量删除操纵,代码如下:
public Connection con=null;
public PreparedStatement pstmt=null;
/**
* 失掉连接对象
*/
public void getConnection(){
String driver="com.mysql.jdbc.Driver";
String url="jdbc:mysql://localhost:3306/zufang?user=root&password=root&useUnicode=true&characterEncoding=GB2312";
try {
Class.forName(driver);
con=DriverManager.getConnection(url,"root","root");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
/** * 批量删除信息表中的信息 * @param sql * @param param * @return */ public boolean updateBatchDel(String sql,String[] param){ boolean flag = false; getConnection(); try { con.setAutoCommit(false); pstmt = con.prepareStatement(sql); for(int i =0 ;i<param.length;i++){ pstmt.setString(1,param[i].trim()); pstmt.addBatch(); } pstmt.executeBatch(); //批量执行 con.commit();//提交事务 flag = true; } catch (SQLException e) { try { con.rollback(); //进行事务回滚 } catch (SQLException ex) { ex.printStackTrace(); } }finally { closeAll(null,pstmt,con); } return flag; }
当然上面是进行批量删除,如果我们只删除一条信息的话也可以使用独自的删除方法,即是:点击删除,当然上面的方法也是可以完成的,还是再看一下吧:
/**
* 删除某条求租表中的信息
* @param id 删除信息的id
* @return 如果删除成功,返回true;否则返回false
*/
public boolean delQiuZu(String id){
boolean flag=false;
String sql="delete from qiuzhu where id=?";
String[] param={id};
flag=bd.updateDate(sql, param);
return flag;
}
控制器servlet中的处置操纵代码如下:
package com.sxt.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sxt.biz.ChuZuBiz;
import com.sxt.biz.PageBiz;
import com.sxt.biz.QiuZuBiz;
public class OutDateQiuzuServlet extends HttpServlet {
QiuZuBiz qzb=new QiuZuBiz();
PageBiz pb=new PageBiz();
int pagesize=10;
boolean flag=true;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("gb2312");
response.setContentType("text/html;charset=gb2312");
int countpage=pb.getOutDatePageCountQiuzu(pagesize);
request.setAttribute("countpage", countpage);
String nowpage=request.getParameter("nowpage");
String id=request.getParameter("id");
PrintWriter out = response.getWriter();
String command = request.getParameter("command");
if ("del".equals(command)) {
String[] qiuzuIds = request.getParameterValues("selectFlag");
boolean flag = qzb.delQiuzuMany(qiuzuIds);
if(flag){
out.print("<script>alert('删除成功!');</script>");
}else{
out.print("<script>alert('删除失败!');</script>");
}
}
if(nowpage==null){
nowpage="1";
}
if(Integer.valueOf(nowpage)<=0){
nowpage="1";
}
if(Integer.valueOf(nowpage)>countpage){
nowpage=countpage+"";
}
if(id!=null){
flag=qzb.delQiuZu(id);
}
request.setAttribute("currentpage", nowpage);
List list=qzb.getOutDateQiuZuInfo(Integer.valueOf(nowpage), pagesize);
request.setAttribute("list1", list);
if(flag){
request.getRequestDispatcher("admin/OutDateQiuzu.jsp").forward(request, response);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
上面是对数据库的操纵代码,上面看一下页面中怎样实现的,代码如下:
每日一道理
灯,带有一种明亮的光,每当深夜来临,是它陪伴着你,如此默默无闻。它是平凡的,外表华丽与否,那都是一样的,珍珠点缀,水晶加饰的灯它只能用以装饰,来满足人们的虚荣心,比起这,普普通通的日光灯是幸运的,因为它照明的本性没有改变,如同生活中的一部分人平平凡凡却实实在在。
<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@ taglib uri="#" prefix="c" %>
<html>
<head>
<title>house</title>
<script type="text/javascript">
//删除用户控制
function deleteSelect() {
var select = document.getElementsByName("selectFlag");
var flag = false;
for (var i=0; i<select.length; i++) {
if (select[i].checked) {
flag = true;
break;
}
}
if (!flag) {
alert("请选择需要删除的过期求租信息!");
return;
}
if (window.confirm("确认要删除过期的求租信息吗?")) {
with (document.getElementById("userform")) {
action="OutDateQiuzuServlet?command=del";
method="post";
submit();
}
}
}
//全选/反选操纵
function checkAll(ifAll) {
var select = document.getElementsByName("selectFlag");
for(var i = 0;i<select.length;i++){
select[i].checked = ifAll.checked;
}
}
</script>
</head>
<link rel="stylesheet" href="./skin/css/lianjie.css" type="text/css" />
<body>
<form name="userform" action="ChuzuServlet" method="get">
<table width="1000" height="80" cellpadding="0" cellspacing="1" bgcolor="#CCCCCC">
<tr>
<td height="40" align="center" bgcolor="#F1F1F1"><font color="#FF0000"><b>已过期的求租信息</b></font></td>
</tr>
<tr>
<td align="left">
<input name="btnDelete" class="button1" type="button"
id="btnDelete" value="删除选中" onClick="deleteSelect()">
</td>
</tr>
</table>
<table width="1000" cellpadding="0" cellspacing="1" bgcolor="#CCCCCC" style="word-break:break-all;">
<tr align="center">
<td width="15%" height="25" bgcolor="#F1F1F1"><font size="3"><input type="checkbox" name="ifAll" title="全选/反选" onClick="checkAll(this)" checked="checked"/></font></td>
<td width="10%" bgcolor="#F1F1F1"><font size="3">期望区域</font></td>
<td width="15%" bgcolor="#F1F1F1"><font size="3">装修水平</font></td>
<td width="10%" bgcolor="#F1F1F1"><font size="3">房型</font></td>
<td width="10%" bgcolor="#F1F1F1"><font size="3">面积(平米)</font></td>
<td width="10%" bgcolor="#F1F1F1"><font size="3">价格(元)</font></td>
<td width="10%" bgcolor="#F1F1F1"><font size="3">添加日期</font></td>
<td width="10%" bgcolor="#F1F1F1"><font size="3">有效天数</font></td>
<td width="10%" bgcolor="#F1F1F1"><font size="3">残余天数</font></td>
</tr>
<c:choose>
<c:when test="${empty list1}">
<tr><td colspan="8" align="center"><font color="red">还没有过期的求租信息!</font></td></tr>
</c:when>
<c:otherwise>
<c:forEach var="qiuzu" items="${list1}" >
<tr>
<td height="25" align="center" bgcolor="#FFFFFF"><input type="checkbox" name="selectFlag" value="${qiuzu.id}" checked="checked"/></font>
<a href="javascript:if(confirm('确定要删除这条过期的求租信息吗?')){location.href='OutDateQiuzuServlet?id=${qiuzu.id}'}" style="COLOR: #0000ff;font-size:14px; TEXT-DECORATION:none;"><font size="2">删除</font></a></td>
<td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.qwqy}</font></td>
<td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.zxcd}</font></td>
<td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.hx}</font></td>
<td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.jzmj}</font></td>
<td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.zj}</font></td>
<td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.addDate}</font></td>
<td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.yxts}</font></td>
<td align="center" bgcolor="#FFFFFF"><font size="2" color="red">${qiuzu.syts}</font></td>
</tr>
</c:forEach>
</c:otherwise>
</c:choose>
</table>
</p>
<table width="300" align="center" >
<tr>
<td align="center"><font size="2">共${countpage}页</font></td>
<td align="center"><font size="2">${currentpage}/${countpage}页</font></td>
<td align="center"><a href="OutDateQiuzuServlet?nowpage=${1}"><font size="2">首页</font></a></td>
<td align="center"><a href="OutDateQiuzuServlet?nowpage=${currentpage-1}"><font size="2">上一页</font></a></td>
<td align="center"><a href="OutDateQiuzuServlet?nowpage=${currentpage+1}"><font size="2">下一页</font></a></td>
<td align="center"><a href="OutDateQiuzuServlet?nowpage=${countpage}"><font size="2">尾页</font></a></td>
</tr>
</table>
</form>
</body>
</html>
Ⅷ JAVA JDBC批处理插入,每一千行提交一次,如果中途失败。怎么办
1、如果这一批次中的记录毫无相关性,可以将失败的记录回滚,成功的记录依然提交,并将失败记录保存下来,或者打印日志什么的,这样可以知道哪里错了,改正后手动插入;
2、当然如果这一批次作为一个原子型事务的话,就全部回滚;
Ⅸ java Spring 的JDBCTemplet批量入库数据时如果有一条数据入库不成功,其他的数据还会入库吗
在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。我们以往在spring和hibernate框架中总是配置一个数据源,因而sessionFactory的dataSource属性总是指向这个数据源并且恒定不变,所有DAO在使用sessionFactory的时候都是通过这个数据源访问数据库。但是现在,由于项目的需要,我们的DAO在访问sessionFactory的时候都不得不在多个数据源中不断切换,问题就出现了:如何让sessionFactory在执行数据持久化的时候,根据客户的需求能够动态切换不同的数据源?我们能不能在spring的框架下通过少量修改得到解决?是否有什么设计模式可以利用呢?问题的分析我首先想到在spring的applicationContext中配置所有的dataSource。这些dataSource可能是各种不同类型的,比如不同的数据库:Oracle、SQLServer、MySQL等,也可能是不同的数据源:比如apache提供的org.apache.commons.dbcp.BasicDataSource、spring提供的org.springframework.jndi.JndiObjectFactoryBean等。然后sessionFactory根据客户的每次请求,将dataSource属性设置成不同的数据源,以到达切换数据源的目的。但是,我很快发现一个问题:当多用户同时并发访问数据库的时候会出现资源争用的问题。这都是“单例模式”惹的祸。众所周知,我们在使用spring框架的时候,在beanFactory中注册的bean基本上都是采用单例模式,即spring在启动的时候,这些bean就装载到内存中,并且每个bean在整个项目中只存在一个对象。正因为只存在一个对象,对象的所有属性,更准确说是实例变量,表现得就如同是个静态变量(实际上“静态”与“单例”往往是非常相似的两个东西,我们常常用“静态”来实现“单例”)。拿我们的问题来说,sessionFactory在整个项目中只有一个对象,它的实例变量dataSource也就只有一个,就如同一个静态变量一般。如果不同的用户都不断地去修改dataSource的值,必然会出现多用户争用一个变量的问题,对系统产生隐患。通过以上的分析,解决多数据源访问问题的关键,就集中在sessionFactory在执行数据持久化的时候,能够通过某段代码去根据客户的需要动态切换数据源,并解决资源争用的问题。问题的解决(一)采用Decorator设计模式要解决这个问题,我的思路锁定在了这个dataSource上了。如果sessionFactory指向的dataSource可以根据客户的需求去连接客户所需要的真正的数据源,即提供动态切换数据源的功能,那么问题就解决了。那么我们怎么做呢?去修改那些我们要使用的dataSource源码吗?这显然不是一个好的方案,我们希望我们的修改与原dataSource代码是分离的。根据以上的分析,使用GoF设计模式中的Decorator模式(装饰者模式)应当是我们可以选择的最佳方案。什么是“Decorator模式”?简单点儿说就是当我们需要修改原有的功能,但我们又不愿直接去修改原有的代码时,设计一个Decorator套在原有代码外面。当我们使用Decorator的时候与原类完全一样,当Decorator的某些功能却已经修改为了我们需要修改的功能。Decorator模式的结构如图。我们本来需要修改图中所有具体的Component类的一些功能,但却并不是去直接修改它们的代码,而是在它们的外面增加一个Decorator。Decorator与具体的Component类都是继承的AbstractComponent,因此它长得和具体的Component类一样,也就是说我们在使用Decorator的时候就如同在使用ConcreteComponentA或者ConcreteComponentB一样,甚至那些使用ConcreteComponentA或者ConcreteComponentB的客户程序都不知道它们用的类已经改为了Decorator,但是Decorator已经对具体的Component类的部分方法进行了修改,执行这些方法的结果已经不同了。(二)设计MultiDataSource类现在回到我们的问题,我们需要对dataSource的功能进行变更,但又不希望修改dataSource中的任何代码。我这里指的dataSource是所有实现javax.sql.DataSource接口的类,我们常用的包括apache提供的org.apache.commons.dbcp.BasicDataSource、spring提供的org.springframework.jndi.JndiObjectFactoryBean等,这些类我们不可能修改它们本身,更不可能对它们一个个地修改以实现动态分配数据源的功能,同时,我们又希望使用dataSource的sessionFactory根本就感觉不到这样的变化。Decorator模式就正是解决这个问题的设计模式。首先写一个Decorator类,我取名叫MultiDataSource,通过它来动态切换数据源。同时在配置文件中将sessionFactory的dataSource属性由原来的某个具体的dataSource改为MultiDataSource。如图:对比原Decorator模式,AbstractComponent是一个抽象类,但在这里我们可以将这个抽象类用接口来代替,即DataSource接口,而ConcreteComponent就是那些DataSource的实现类,如BasicDataSource、JndiObjectFactoryBean等。MultiDataSource封装了具体的dataSource,并实现了数据源动态切换:java代码{privateDataSourcedataSource=null;publicMultiDataSource(DataSourcedataSource){this.dataSource=dataSource;}publicConnectiongetConnection()throwsSQLException{returngetDataSource().getConnection();}//其它DataSource接口应当实现的方法publicDataSourcegetDataSource(){returnthis.dataSource;}}publicvoidsetDataSource(DataSourcedataSource){this.dataSource=dataSource;}}客户在发出请求的时候,将dataSourceName放到request中,然后把request中的数据源名通过调用newMultiDataSource(dataSource)时可以告诉MultiDataSource客户需要的数据源,就可以实现动态切换数据源了。但细心的朋友会发现这在单例的情况下就是问题的,因为MultiDataSource在系统中只有一个对象,它的实例变量dataSource也只有一个,就如同一个静态变量一般。正因为如此,单例模式让许多设计模式都不得不需要更改,这将在我的《“单例”更改了我们的设计模式》中详细讨论。那么,我们在单例模式下如何设计呢?(三)单例模式下的MultiDataSource在单例模式下,由于我们在每次调用MultiDataSource的方法的时候,dataSource都可能是不同的,所以我们不能将dataSource放在实例变量dataSource中,最简单的方式就是在方法getDataSource()中增加参数,告诉MultiDataSource我到底调用的是哪个dataSource:java代码publicDataSourcegetDataSource(StringdataSourceName){log.debug("dataSourceName:"+dataSourceName);try{if(dataSourceName==null||dataSourceName.equals("")){returnthis.dataSource;}return(DataSource)this.applicationContext.getBean(dataSourceName);}catch(){thrownewDaoException("ThereisnotthedataSource}}值得一提的是,我需要的数据源已经都在spring的配置文件中注册,dataSourceName就是其对应的id。xml代码oracle.jdbc.driver.OracleDrivervalue>property>bean>oracle.jdbc.driver.OracleDrivervalue>property>bean>为了得到spring的ApplicationContext,MultiDataSource类必须实现接口org.springframework.context.ApplicationContextAware,并且实现方法:java代码=null;()throwsBeansException{this.applicationContext=applicationContext;}如此这样,我就可以通过this.applicationContext.getBean(dataSourceName)得到dataSource了。(四)通过线程传递dataSourceName查看以上设计,MultiDataSource依然无法运行,因为用户在发出请求时,他需要连接什么数据库,其数据源名是放在request中的,要将request中的数据源名传给MultiDataSource,需要经过BUS和DAO,也就是说为了把数据源名传给MultiDataSource,BUS和DAO的所有方法都要增加dataSourceName的参数,这是我们不愿看到的。写一个类,通过线程的方式跳过BUS和DAO直接传递给MultiDataSource是一个不错的设计:java代码publicclassSpObserver{privatestaticThreadLocallocal=newThreadLocal();publicstaticvoidputSp(Stringsp){local.set(sp);}publicstaticStringgetSp(){return(String)local.get();}}做一个filter,每次客户发出请求的时候就调用SpObserver.petSp(dataSourceName),将request中的dataSourceName传递给SpObserver对象。最后修改MultiDataSource的方法getDataSource():java代码publicDataSourcegetDataSource(){Stringsp=SpObserver.getSp();returngetDataSource(sp);}完整的MultiDataSource代码在附件中。(五)动态添加数据源通过以上方案,我们解决了动态分配数据源的问题,但你可能提出疑问:方案中的数据源都是配置在spring的ApplicationContext中,如果我在程序运行过程中动态添加数据源怎么?这确实是一个问题,而且在我们的项目中也确实遇到。spring的ApplicationContext是在项目启动的时候加载的。加载以后,我们如何动态地加载新的bean到ApplicationContext中呢?我想到如果用spring自己的方法解决这个问题就好了。所幸的是,在查看spring的源代码后,我找到了这样的代码,编写了DynamicLoadBean类,只要调用loadBean()方法,就可以将某个或某几个配置文件中的bean加载到ApplicationContext中(见附件)。不通过配置文件直接加载对象,在spring的源码中也有,感兴趣的朋友可以自己研究。(六)在spring中配置在完成了所有这些设计以后,我最后再唠叨一句。我们应当在spring中做如下配置:xml代码bean>property>bean>property>bean>其中dataSource属性实际上更准确地说应当是defaultDataSource,即spring启动时以及在客户没有指定数据源时应当指定的默认数据源。该方案的优势以上方案与其它方案相比,它有哪些优势呢?首先,这个方案完全是在spring的框架下解决的,数据源依然配置在spring的配置文件中,sessionFactory依然去配置它的dataSource属性,它甚至都不知道dataSource的改变。唯一不同的是在真正的dataSource与sessionFactory之间增加了一个MultiDataSource。其次,实现简单,易于维护。这个方案虽然我说了这么多东西,其实都是分析,真正需要我们写的代码就只有MultiDataSource、SpObserver两个类。MultiDataSource类真正要写的只有getDataSource()和getDataSource(sp)两个方法,而SpObserver类更简单了。实现越简单,出错的可能就越小,维护性就越高。最后,这个方案可以使单数据源与多数据源兼容。这个方案完全不影响BUS和DAO的编写。如果我们的项目在开始之初是单数据源的情况下开发,随着项目的进行,需要变更为多数据源,则只需要修改spring配置,并少量修改MVC层以便在请求中写入需要的数据源名,变更就完成了。如果我们的项目希望改回单数据源,则只需要简单修改配置文件。这样,为我们的项目将增加的弹性。特别说明:实例中的DynamicLoadBean在web环境下运行会出错,需要将类中AbstractApplicationContext改为org.springframework.context.。
Ⅹ java jdbc 执行sql语句批量操作问题
sql优化:
1.name字段创建索引
2.“table_c.*” 不要用”*“号,可以换成table_c.id,table_c.name,table_c.sex,table_c.email
如果可以的话,你和以在insert into table_a 中间加 append ,这样写 insert /*+ append */ into
希望能帮到你!