2017-07-25 8 views
0

J'ai un problème plutôt ennuyeux. Dans le morceau de code ci-dessous, j'essaie d'insérer une nouvelle ligne dans la table "RevisionDispersion" dans ma base de données. Cependant, chaque fois que j'appelle stmt.executeUpdate() le programme se bloque et il n'y a plus de transaction dans la base de données. Peu importe combien de temps j'attends; la base de données ne sera tout simplement pas mise à jour. Voici le code d'intérêt:Application Java SQL Server bloquée sur 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); 
} 

Ce problème ne se produit pas ailleurs dans l'application. Chaque fois que j'exécute l'instruction SQL dans SQL Server Management Studio, avec des paramètres identiques, elle ne reste pas bloquée et insère les nouvelles lignes correctement. Après avoir supprimé les lignes et essayé la même chose dans l'application, il est bloqué.

Quelqu'un peut-il me diriger dans la bonne direction de ce qui ne va pas? J'ai essayé pendant 3 heures d'affilée maintenant ...

Stuff J'ai déjà essayé

-Utiliser stmt.addBatch() plutôt que executeUpdate() (n'a pas fait une différence. Il se coincent à executeBatch())

-Vérifiez si toutes les connexions sont correctement fermées; elles sont.

-Vérifier si d'autres déclarations/resultsets sont encore ouvertes que l'utilisation de la table RevisionDispersion (il n'y en a pas encore ouvert. Même s'il y avait, ne devrait pas faire une différence que je pense?)

supprimer -Complètement la base de données et définir back up

+0

Une chance'handins.size() 'pourrait augmenter pendant l'exécution? Je vais enregistrer cette valeur dans une variable en dehors de la boucle. – Horaciux

+0

@Horaciux Non, n'augmente pas pendant l'exécution. En dehors de cela: le programme se bloque au point qu'il appelle "stmt.executeUpdate()"). En d'autres termes: il n'effectue même pas une seule itération: p Merci pour la réponse :) – ImJustACowLol

+0

@ImJustACowLol - Veuillez partager la requête que vous exécutez dans SQL Server Management Studio. Je crois que la requête 'Insert' utilisée directement dans le SSMS et dans le code est différente. –

Répondre

0

Je résolu la question ...

Dans un autre morceau de code j'ai eu les éléments suivants:

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); 
    } 
} 

I Dans ce morceau de code, j'ai fermé les variables 'assignations' et 'assignmentsStmt'. Je pensais que ce serait suffisant pour déverrouiller la table après avoir utilisé la requête GET_NOT_DISPERSED. Apparemment ce n'était pas le cas: la table était toujours fermée à clé. Ce que je devais faire pour le réparer: mis à part l'appel à assignments.close() et à assignmentsStmt.close(), j'ai aussi dû appeler con.close(). Cela a complètement déverrouillé la table et permis au code de fonctionner correctement.