Java 使用JDBC和MySQL更新大型结果集

Java 使用JDBC和MySQL更新大型结果集,java,database,jdbc,resultset,Java,Database,Jdbc,Resultset,我正在尝试更新一大组行(大约5M)。我第一次遇到堆溢出问题,即在一个resultset中获取了如此多的行。因为我不想在这台机器上提高堆大小,所以我想知道是否有一种有效的方法可以做到这一点 我尝试设置setFetchSize(Integer.MIN\u值),但当我调用更新函数时,出现以下错误: 流式处理结果集com.mysql.jdbc。RowDataDynamic@2087c268仍处于活动状态。在给定连接上打开并使用任何流结果集时,不得发出任何语句。在尝试更多查询之前,请确保已对任何活动的流式

我正在尝试更新一大组行(大约5M)。我第一次遇到堆溢出问题,即在一个resultset中获取了如此多的行。因为我不想在这台机器上提高堆大小,所以我想知道是否有一种有效的方法可以做到这一点

我尝试设置
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协议不支持在同一连接上同时执行多个语句。因此,如果确实需要两个命令,则必须完全读取第一个命令的完整结果(这是“非流式传输”模式),或者您可以通过一个连接“流式传输”结果,并通过第二个连接进行更新。