0
votes

Exception ResultSet - avant le démarrage

Trace: java.sql.SQLException: Operation not allowed for a result set of type ResultSet.TYPE_FORWARD_ONLY.
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
    at com.mysql.cj.jdbc.result.ResultSetImpl.beforeFirst(ResultSetImpl.java:426)
    at DaoLayer.daoImplementation.getUser(daoImplementation.java:28)
    at DaoLayer.DaoTest.testGetUser(DaoTest.java:26)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)

2 commentaires

Je ne suis pas sûr qu'il y ait une question, sauf le "pourquoi est-ce que j'obtiens cette erreur".


Pourquoi appelez-vous même beforeFirst () ? Cela n'a aucun sens dans votre code.


3 Réponses :


0
votes

changez pStatement.executeQuery (sql) par pStatement.executeQuery ()

userID est également int code > donc pas besoin d'utiliser le guillemet simple ' dans la requête (mais ce n'est pas la racine de l' Exception)

Je suggère d'utiliser un if instruction sur Rset.next () (qui incrémente le curseur, pas besoin d'utiliser beforeFirst () ) cela peut provoquer des exceptions lors de l'obtention des valeurs si la requête ne renvoie rien.

Utilisez le code comme suit

public static User getUser (User user) throws Exception {
        String sql = "SELECT * FROM login WHERE userID = " + user.getuserID();
        //is FROM Correct?
        PreparedStatement pStatement = conn.prepareStatement(sql);
        ResultSet Rset = pStatement.executeQuery();
        if(Rset.next())
        {
             int userID = Rset.getInt("userID");
             String email = Rset.getString("email");
             User userReturn = new User (userID, email);
             return userReturn;
        }
        return null;

    }


0 commentaires

1
votes

Eh bien, votre JDBC / SQL pourrait utiliser certaines mises à jour.

Mais tout d'abord. Voici ce qui se passe:

public static User getUser (User user) throws Exception {
    String sql = "SELECT * FROM login WHERE userID = ?;
    try(PreparedStatement pStatement = conn.prepareStatement(sql)) {
      pStatement.setInt(1, user.getuserID());
      try(ResultSet Rset = pStatement.executeQuery()) {  
        if(Rset.next()) {
          int userID = Rset.getInt("userID");
          String email = Rset.getString("email");
          User userReturn = new User (userID, email);
          return userReturn;
        }
      }
    } catch(SQLException e) {
      //Deal with the exception
      e.printStackTrace();
    }
    //Error or no user found
    return null;
}

La deuxième ligne lance une exception car le curseur est FORWARD_ONLY. Plus: Vous n'avez pas du tout besoin de cet appel!

Cela devrait résoudre votre problème immédiat:

    ResultSet Rset = pStatement.executeQuery(sql);
    if(Rset.next()) {
      int userID = Rset.getInt("userID");
      String email = Rset.getString("email");
      User userReturn = new User (userID, email);
      return userReturn;
    } else {
      //Deal with no user found
    }

Maintenant, pour le truc général:

  • il est bon que vous prépariez la déclaration. Mais comme Bashir l'a déjà souligné: si vous utilisez executeQuery (sql), qui est membre de la classe Statement, vous jetez l'instruction précompilée.
  • lors de l'utilisation de PreparedStatement - utilisez également les paramètres de liaison. Cela rend votre code moins fréquent pour l'injection SQL et
  • utilisez try-with-resource pour vous assurer de tout fermer correctement. Traquer les fuites de connexion ou les curseurs ouverts est un problème facilement évité.

À la fin, vous vous retrouverez probablement avec quelque chose comme ceci:

    ResultSet Rset = pStatement.executeQuery(sql); //Executes the query
    Rset.beforeFirst(); //Moves the cursor backwards before the first row (!)
    Rset.next(); //Goes to the next row


0 commentaires

1
votes

Lorsque vous créez un ResultSet standard, vous ne pouvez utiliser que la méthode rs.next () pour itérer les lignes résultantes. Donc rs.beforeFirst () n'est pas autorisé. Et ce n'est pas non plus nécessaire dans votre code. Lorsque le ResultSet est créé, le curseur est automatiquement placé avant la première ligne. Donc, utilisez simplement if (rs.next ()) {...} . Lorsque rs.next () renvoie false après le premier appel, cela signifie que le ResultSet est vide.


0 commentaires