【问题标题】:Java/SQL - executeUpdate() hangs and causes OutOfMemoryExceptionJava/SQL - executeUpdate() 挂起并导致 OutOfMemoryException
【发布时间】:2015-01-29 13:18:30
【问题描述】:

我正在尝试对我的表执行一个相对简单的插入操作,但是 executeUpdate() 方法一直挂起,直到程序因 OutOfMemoryException 而崩溃。我已经成功地在 SQL Server Management Studio 上执行了插入,并且我已经将数据库设置为脱机并重新联机,所以我认为没有任何方法可以锁定表。我也在打印我的令牌,它们都不是空的。

我的代码中有什么可疑之处吗?

if(commandCode.equals("RV")){
    StringTokenizer tokens = new StringTokenizer(fullLine,"^");

    String itemCallNumber=null;
    String itemCurrentLocation=null;
    String itemFormat=null;
    String itemHomeLocation=null;
    String itemLibrary=null;
    String itemType=null;
    String itemCat1=null;
    String itemCat2=null;
    String itemCat3=null;
    Integer itemPubYear=null;
    String stationLibrary=null;
    String userProfileName=null;
    String userCat1=null;
    String userCat2=null;       
    String userZipCode=null;
    String userLibrary=null;
    java.sql.Date userBirthdate=null;
    String clientType = null;


    while(tokens.hasMoreTokens()){
        String token = tokens.nextToken();
        System.out.println(token);
        if(token.startsWith("UZ")){
            String dateString = token.substring(2);
            SimpleDateFormat format = new SimpleDateFormat("M/d/yyyy");
            Date date = format.parse(dateString);

            userBirthdate=new java.sql.Date(date.getTime());;
        }
        if(token.startsWith("PG")){
            userCat1=token.substring(2);
        }
        if(token.startsWith("PH")){
            userCat2=token.substring(2);
        }

        if(token.startsWith("PE")){
            userProfileName=token.substring(2);
        }

        if(token.startsWith("UM")){
            userLibrary=token.substring(2);
        }
        if(token.startsWith("UB")){
            userZipCode=token.substring(2);
        }

        if(token.startsWith("IQ")){
            itemCallNumber=token.substring(2);
        }
        if(token.startsWith("IL")){
            itemCurrentLocation=token.substring(2);
        }
        if(token.startsWith("IK")){
            itemFormat=token.substring(2);
        }
        if(token.startsWith("IN")){
            itemHomeLocation=token.substring(2);
        }
        if(token.startsWith("NS")){
            itemLibrary=token.substring(2);
        }
        if(token.startsWith("IG")){
            itemType=token.substring(2);
        }
        if(token.startsWith("NX")){
            itemCat1=token.substring(2);
        }
        if(token.startsWith("NY")){
            itemCat2=token.substring(2);
        }
        if(token.startsWith("0A")){
            itemCat3=token.substring(2);
        }
        if(token.startsWith("IF")){
            itemPubYear=Integer.parseInt(token.substring(2));
        }
        if(token.startsWith("FE")){
            stationLibrary=token.substring(2);
        }

        if(token.startsWith("dC")){
            clientType=token.substring(2);
        }

    }


    String insert = "INSERT INTO dbo.RenewItem Values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
    PreparedStatement insertPS = connection.prepareStatement(insert);

    //These come from earlier in the code and are verified to be correct
    insertPS.setInt(1, id);
    insertPS.setTimestamp(2, ts);

    insertPS.setString(3, itemCallNumber);
    insertPS.setString(4, itemCurrentLocation);
    insertPS.setString(5, itemFormat);
    insertPS.setString(6, itemHomeLocation);
    insertPS.setString(7, itemLibrary);
    insertPS.setString(8, itemType);
    insertPS.setString(9, itemCat1);
    insertPS.setString(10, itemCat2);
    insertPS.setString(11, itemCat3);
    insertPS.setInt(12, itemPubYear);
    insertPS.setString(13, stationLibrary);
    insertPS.setString(14, userProfileName);
    insertPS.setString(15,userCat1);
    insertPS.setString(16, userCat2);
    insertPS.setString(17, userZipCode);
    insertPS.setString(18, userLibrary);
    insertPS.setDate(19, userBirthdate);
    insertPS.setString(20,clientType);

    insertPS.executeUpdate();

编辑:我已经能够极大地隔离问题。它与大桌子上的周围 SELECT * 有关。在下面的代码中,达到了 selectPS.close() 但该方法永远不会返回。

        final Connection connection = DriverManager.getConnection(url);

        String select = "SELECT * FROM dbo.SirsiStat";
        PreparedStatement selectPS = connection.prepareStatement(select);
        ResultSet rs = selectPS.executeQuery();
        System.out.println("here");
        selectPS.close();

【问题讨论】:

  • 我不确定,但我认为您需要指定列,例如dbo.RenewItem('col1','col2'.....,'col20')
  • @Titus:那将是无效的 SQL。 'col1' 是字符文字,而不是列名(col1 是列名)。但我同意明确列出 insert 语句的列名是一种很好的编码风格。

标签: java sql sql-server jdbc


【解决方案1】:

首先您必须必须处理 JDBC 资源,其次尝试了解 PreparedStatement 的正确用途或用途。

使用 try-with-resource 语法。这种语法确保即使在发生异常后也能调用close() 方法。

try(Connection cn=DriverManager.getConnection(url,user,pass)) {
  //statements

   String sql = "insert into tableName (columnOne, columnTwo) values (?,?)";
   try(PreparedStatement ps = cn.prepareStatement(sql)) {

      while(tokens.hasMoreTokens()) {
         //statements
        ps.setInt(1,valueForColumn1);
        ps.setString(2,valueForColumn2);
      }
   }
}

参考线程 - How to properly dispose of Connection, ResultSet, and Statement objects in a while loop?

【讨论】:

  • 这不能解决我的问题。
  • 我想我看错了你的答案。我道歉。当我有能力时,我会删除我的反对票。请看看我的编辑。
  • @JamesHarpe 我猜这个问题与驱动 API 有关。
猜你喜欢
  • 2014-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多