2009-01-21 12 views
0

Je le code suivant:Bizarre JDBC executeQuery exception

public Object RunQuery(String query) throws Exception{ 
    System.out.println("Trying to run query"); 
    Statement stmt = null; 
    ResultSet rs = null; 
    try { 
     stmt = conn.createStatement(); 
     System.out.println("Got Statement"); 
     rs = stmt.executeQuery(query); 
     System.out.println("Query executed"); 
     ... 


    } catch (SQLException ex) { 
     // handle any errors 
     System.out.println("SQLException: " + ex.getMessage()); 
     System.out.println("SQLState: " + ex.getSQLState()); 
     System.out.println("VendorError: " + ex.getErrorCode()); 
    } 
    catch (Exception ex) { 
     System.out.println("Exception: " + ex.getMessage()); 
    } 
    finally { 
     if (rs != null) { 
      try { 
       rs.close(); 
      } catch (SQLException sqlEx) { 
      } // ignore 
      rs = null; 
     } 
     if (stmt != null) { 
      try { 
       stmt.close(); 
      } catch (SQLException sqlEx) { 
      } // ignore 
      stmt = null; 
     } 
     return ret; 
    } 
} 

Ce qui fonctionne parfaitement bien lors de l'exécution

query = "SELECT * FROM smalltable" 

Mais échoue sur

query = "SELECT * FROM bigtable" 

qui a environ 200K dossiers. Le débogueur ignore élégamment les blocs catch et va directement dans le bloc finally; NetBeans m'a donné ce cadre de pile quand j'ai ajouté stmt.executeQuery (requête) à la liste de surveillance:

>Exception occurred in target VM: Communications link failure Last packet sent to the server was 0 ms ago. 
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure Last packet sent to the server was 0 ms ago. 

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 

at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) 

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) 

at java.lang.reflect.Constructor.newInstance(Constructor.java:513) 

at com.mysql.jdbc.Util.handleNewInstance(Util.java:406) 

at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1074) 

at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3009) 

at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2895) 

at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3438) 

at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1951) 

at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2101) 

at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2548) 

at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2477) 

at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1422) 

at RunQuery 
Caused by: java.net.SocketException: Software caused connection abort: recv failed 

at java.net.SocketInputStream.socketRead0(Native Method) 

at java.net.SocketInputStream.read(SocketInputStream.java:129) 

at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:157) 

at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:188) 

at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2452) 

at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2962) 

... 9 more 




Comment puis-je faire de grandes questions dans ce cadre?



EDIT: J'utilise le connecteur J et le serveur mysql 5.1; la chaîne de connexion est

jdbc:mysql://localhost?user=root&password=password 

Oui, je sais que select * est une mauvaise pratique, mais comme vous pouvez le voir, je viens de commencer, ce qui est plus ou moins le deuxième essai que je fais

+0

Quel pilote jdbc utilisez-vous? En outre, vous devriez généralement éviter les requêtes select *. – kgiannakakis

+0

Que se passe-t-il si vous sélectionnez "1 from bigtable"? –

+0

Est-ce que cela se produit immédiatement lorsque vous exécutez le programme ou bien plus tard? – Uri

Répondre

1

La seule Ce que je peux penser de cette différence serait un certain délai d'attente au niveau du réseau, et la sortie de Netbeans pointerait certainement dans cette direction. Quelle est la chaîne de connexion JDBC que vous utilisez? peut-être y a-t-il un paramètre de délai qui peut être dépassé?

Il peut également être utile de brancher un renifleur de paquets réseau si le problème persiste et de voir à quoi ressemblent les communications à ce niveau. Jouez à "repérer la différence" avec les requêtes courtes et longues et vous pourriez avoir une bonne idée de ce qui fait qu'un échec échoue là où l'autre réussit. En général, select * est une mauvaise idée simplement en raison de toutes les données supplémentaires qu'il ramène inutilement.Dans ce cas, la sélection de toutes les colonnes de toutes les lignes de la grande table est évidemment donner le problème de connexion par rapport à la sélection de Je sais que dans ce cas, votre question est toujours valide, car il se peut que vous ayez besoin de faire cela, et en plus de sélectionner un sous-ensemble d'un tableau encore plus grand, vous feriez probablement la même chose, mais je le signale une directive générale dans le cas où vous utilisiez ceci dans la production comme un raccourci.)

1

Ma pensée immédiate est qu'il pourrait y avoir un problème de mémoire avec l'extraction de toutes ces données. Je ne sais pas comment MySQL est configuré à cet effet, mais vous pouvez essayer de définir la taille d'extraction dans le ResultSet ou de limiter la taille du ResultSet en sélectionnant moins de colonnes. Il est possible que le pilote JDBC tente d'extraire la totalité de la table en une seule opération.

En note, s'il vous plaît s'il vous plaît s'il vous plaît ne jamais faire stmt.executeQuery (requête). Utilisez toujours un PreparedStatement et liez vos paramètres de requête. Dans votre exemple, il n'y a pas de paramètres, mais c'est une pratique qui est essentielle à des fins de sécurité. N'utilisez jamais SQL avec des paramètres qui sont des 'littéraux' (sauf lorsque vos littéraux sont des chaînes de confiance telles que des constantes de votre code ou des types non-chaînes tels que les nombres que vous avez déjà analysés).

0

Si elle saute directement à la fin, l'exception est-elle lancée dans l'autre code en fait un descendant de Error? Cela éviterait complètement votre prise.

Vous avez peut-être obtenu une erreur OutOfMemoryError, puis vous avez obtenu l'exception de réseau car l'OOME a fermé certaines tâches?