2017-07-25 18 views
0

我有一个相当讨厌的问题。在下面的代码段中,我试图在数据库的“RevisionDispersion”表中插入一个新行。但是,无论何时我调用stmt.executeUpdate(),程序都会冻结,最终导致数据库无事务发生。不管我等多久,数据库不会被更新。以下是感兴趣的代码:Java SQL Server应用程序停滞在statement.executeUpdate()

private static final String INSERT_DISPERSION = "insert into RevisionDispersion(" 
               + Assignments.ID + ", " 
               + Persons.EMAIL + ", " 
               + Handins.ID + ")" 
               + " values(?, ?, ?)"; 

public static void disperse(DataSource source, Assignment assignment) throws Exception 
{ 
    List<String> handins = assignment.getHandins(); 

    //used to decide who checks which assignment 
    int maxRNG = Math.max(1, handins.size()/assignment.getPeerCount()); 
    int rng = new Random().nextInt(maxRNG); 

    PreparedStatement stmt = null; 
    Connection con = null; 

    try{ 
     //Get the connection, set it to TRANSACTION_SERIALIZABLE and set autocommit to false 
     con = source.getConnection(); 
     configureConnection(con); 

     //Prepare the statement to insert the new dispersion 
     stmt = con.prepareStatement(INSERT_DISPERSION); 
     stmt.setString(1, assignment.getID()); 

     //Iterate over all hand-ins and decide from which peer a peer receives feedback 
     for(int i = 0; i < handins.size(); i++) 
     { 
      HandIn handin = new HandIn(source.getConnection(), handins.get(i)); 
      String student = handin.getEmail(); 

      stmt.setString(2, student); 

      for(int j = 1; j <= assignment.getPeerCount(); j++) 
      { 
       HandIn otherHandin = new HandIn(source.getConnection(), handins.get(j * rng)); 
       stmt.setString(3, otherHandin.getId()); 
       stmt.executeUpdate(); 
      } 
     } 

     con.commit(); 
    }catch(Exception e){ 
     throw e; 
    }finally{ 
     closeQuietly(con, stmt); 
    } 
} 

//This method is originally in the DBAO class, but I put it here for you folks. 
protected static void configureConnection(Connection connection) throws SQLException 
{ 
    connection.setAutoCommit(false); 
    connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); 
} 

在应用程序中没有其他地方发生此问题。每当我在SQL Server Management Studio中运行SQL语句时,使用相同的参数,它不会卡住,它会插入新行。删除行并在应用程序中尝试相同之后,它会卡住。

任何人都可以指出我出错的正确方向吗?我一直在尝试3小时直现在......

的东西,我已经尝试过

次使用stmt.addBatch(),而不是的executeUpdate()(不有所作为,它会被卡住在executeBatch())

- 检查是否所有连接都正确关闭;他们是。

- 检查是否有其他语句/结果集仍然打开使用RevisionDispersion表(有没有开放的。即使有,不应该有所作为,我认为?)

- 完全删除数据库并设置它备份

+0

任何机会'handins.size()'可能在执行期间增加?我将这个值保存在循环外部的变量中。 – Horaciux

+0

@Horaciux Nope,在执行期间不会增加。除此之外:程序在它称为“stmt.executeUpdate()”的地方冻结)。换句话说:它甚至不会完成一次迭代:p感谢您的回应:) – ImJustACowLol

+0

@ImJustACowLol - 请分享您在SQL Server Management Studio中执行的查询。我相信直接在SSMS和代码中使用的Insert插入查询是不同的。 –

回答

0

我解决了问题...

在不同的代码,我有以下几点:

private static final String GET_NOT_DISPERSED = "select * from Assignments where " 
              + Assignments.CLOSE_DATE + "<=? and " 
              + Assignments.PEER_START_DATE + ">=? and " 
              + Assignments.ID + " not in(select " + Assignments.ID + " from RevisionDispersion)"; 
private void makeMailDispersion() throws Exception 
{ 
    DateTime currentDate = DateTime.getCurrentDateTime(); 

    PreparedStatement assignmentsStmt = null; 
    ResultSet assignments = null; 
    Connection con = null; 

    try{ 
     con = source.getConnection(); 
     configureConnection(con); 
     assignmentsStmt = con.prepareStatement(GET_NOT_DISPERSED); 
     assignmentsStmt.setString(1, currentDate.toString()); 
     assignmentsStmt.setString(2, currentDate.toString()); 

     assignments = assignmentsStmt.executeQuery(); 

     ArrayList<Assignment> requiresDispersion = new ArrayList<>(); 

     assignments.close(); 
     assignmentsStmt.close(); 
     while(assignments.next()) 
     { 
      Assignment assignment = new Assignment(source.getConnection(), assignments.getString(Assignments.ID)); 
      AssignmentDisperser.disperse(source, assignment); 
     } 
    }catch(Exception e){ 
     throw e; 
    }finally{ 
     closeQuietly(con, assignmentsStmt, assignments); 
    } 
} 

我在这段代码中,我关闭了变量的'赋值'和'assignmentsStmt'。我认为这已足够在使用GET_NOT_DISPERSED查询后解锁表。显然它不是:桌子仍然锁着。

为了解决这个问题我需要做些什么:除了调用assignments.close()和assignmentsStmt.close()之外,我还必须调用con.close()。这完全解锁了表并允许代码正常运行。