Java 使用JDBC和MySQL更新大型结果集
我正在尝试更新一大组行(大约5M)。我第一次遇到堆溢出问题,即在一个resultset中获取了如此多的行。因为我不想在这台机器上提高堆大小,所以我想知道是否有一种有效的方法可以做到这一点 我尝试设置Java 使用JDBC和MySQL更新大型结果集,java,database,jdbc,resultset,Java,Database,Jdbc,Resultset,我正在尝试更新一大组行(大约5M)。我第一次遇到堆溢出问题,即在一个resultset中获取了如此多的行。因为我不想在这台机器上提高堆大小,所以我想知道是否有一种有效的方法可以做到这一点 我尝试设置setFetchSize(Integer.MIN\u值),但当我调用更新函数时,出现以下错误: 流式处理结果集com.mysql.jdbc。RowDataDynamic@2087c268仍处于活动状态。在给定连接上打开并使用任何流结果集时,不得发出任何语句。在尝试更多查询之前,请确保已对任何活动的流式
setFetchSize(Integer.MIN\u值)
,但当我调用更新函数时,出现以下错误:
流式处理结果集com.mysql.jdbc。RowDataDynamic@2087c268
仍处于活动状态。在给定连接上打开并使用任何流结果集时,不得发出任何语句。在尝试更多查询之前,请确保已对任何活动的流式处理结果集调用了.close()
如果我对结果集调用close()
,我当然不能更新它。这是我的密码
public void getRows()
{
Statement stmt = null;
ResultSet rs = null;
int countSpecialChars = 0;
int upper = 0, lower = 0, digits =0;
String pass = null;
int id = 0;
char thisChar;
String query = "select id,pass from datatable";
try {
this.conn.setAutoCommit(false);
stmt = this.conn.createStatement();
stmt.setFetchSize(Integer.MIN_VALUE);
rs = stmt.executeQuery(query);
while (rs.next()) {
pass = rs.getString(2).trim();
id = rs.getInt(1);
for (int i=0; i<=pass.length()-1; i++)
{
thisChar= pass.charAt(i);
if (thisChar >= 65 && thisChar <= 90) {
upper++;
} else if (thisChar >= 97 && thisChar <= 122) {
lower++;
} else if( thisChar >= 48 && thisChar <= 57) {
digits++;
}
else
{countSpecialChars++;}
}
Entropy entropy = new Entropy();
double naiveEntropy = entropy.naiveEntropy(pass);
NumberFormat formatter = new DecimalFormat("#0.00");
this.updateRow(id, pass.length(), digits, upper, lower, countSpecialChars, Double.parseDouble(formatter.format(naiveEntropy)));
countSpecialChars = 0;
upper=digits=0;
lower = 0;
}
rs.close();
}
catch (SQLException e)
...
}
public void updateRow(int id, int length, int numbers, int upper,
int lower, int specialChars, double naiveEntropy )
{
PreparedStatement updatePassEntry = null;
String updateString = "update cwlCompatiblePassUnique " +
"set length = ?, numbers = ?, upper = ?, lower = ?, specialChars = ?, ShannonEntropy = ? where id = ?";
try {
this.conn.setAutoCommit(false);
updatePassEntry = this.conn.prepareStatement(updateString);
updatePassEntry.setInt(1, length);
...
updatePassEntry.setInt(7, id);
updatePassEntry.executeUpdate();
this.conn.commit();
}
catch (SQLException e)
...
}
public void getRows()
{
语句stmt=null;
结果集rs=null;
int countSpecialChars=0;
整数上限=0,下限=0,数字=0;
字符串传递=null;
int id=0;
char thisChar;
String query=“选择id,从数据表传递”;
试一试{
this.conn.setAutoCommit(false);
stmt=this.conn.createStatement();
stmt.setFetchSize(Integer.MIN_值);
rs=stmt.executeQuery(查询);
while(rs.next()){
pass=rs.getString(2.trim();
id=rs.getInt(1);
对于(int i=0;i=65&&thisChar=97&&thisChar=48&&thisChar,在rs.next()循环中调用updateRow()方法;该方法尝试对while(rs.next()中当前正在处理的SQL字段(id)进行SQL更新循环。这将引发您得到的错误。我建议您首先编写一个方法来提取rs并将其存储在java对象向量中。此方法将在退出后关闭rs。然后编写另一个方法来处理和更新缓存向量对象上的数据。
大概是这样的:
private void Vector<DataSet> getDataSet(){
Vector<DataSet> data=new Vector<DataSet>();
String query = "select id,pass from datatable";
try {
this.conn.setAutoCommit(false);
stmt = this.conn.createStatement();
stmt.setFetchSize(Integer.MIN_VALUE);
rs = stmt.executeQuery(query);
while (rs.next()) {
pass = rs.getString(2).trim();
id = rs.getInt(1);
data.addElement(new DataSet(id,pass));
}
}catch(Exception e){
// here close connection and rs
}
}
private void udpateData(Vector<dataSet> data){
//process data and update her
}
static class DataSet{
int id;
String pass;
//constructor here
}
private void Vector getDataSet(){
向量数据=新向量();
String query=“选择id,从数据表传递”;
试一试{
this.conn.setAutoCommit(false);
stmt=this.conn.createStatement();
stmt.setFetchSize(Integer.MIN_值);
rs=stmt.executeQuery(查询);
while(rs.next()){
pass=rs.getString(2.trim();
id=rs.getInt(1);
addElement(新数据集(id,pass));
}
}捕获(例外e){
//这里有密切的联系和联系
}
}
专用数据(矢量数据){
//处理数据并更新她
}
静态类数据集{
int-id;
串通;
//这里是构造器
}
连接对象不应同时保存多个resultset对象。
在创建ResultSet和Statement对象之后,每个对象都必须显式关闭,
resultSet.close()
statement.close()尝试创建一个新连接并使用该连接更新数据库。希望这会有所帮助。这是正确的答案。MySQL wire协议不支持在同一连接上同时执行多个语句。因此,如果确实需要两个命令,则必须完全读取第一个命令的完整结果(这是“非流式传输”模式),或者您可以通过一个连接“流式传输”结果,并通过第二个连接进行更新。