Parcourir une Jtable, ResultSet closed

Résolu
zerargui
Messages postés
65
Date d'inscription
vendredi 24 octobre 2008
Statut
Membre
Dernière intervention
25 février 2019
- Modifié par KX le 30/07/2016 à 12:06
zerargui
Messages postés
65
Date d'inscription
vendredi 24 octobre 2008
Statut
Membre
Dernière intervention
25 février 2019
- 1 août 2016 à 20:49
Bonjour,
je veux parcourir une Jtable et ensuite je dois au fur et mesure de la lecture d'une ligne, diminuer la quantité du stock de la table produit( bien-sur en recherchant à chaque fois le code du produit).
Voici la structure de ma table produit: CodePd, NomPd,QtePd, PxAchat, PxVente, DateVente. mais une erreur me parvient toujours et je suis dans l'embrouille:
""Operation not allowed after ResultSet closed.""
et voici mon code :
private void enrFactActionPerformed(java.awt.event.ActionEvent evt) {                                       
        int q1, id_Pd;
        try{
            for (int i=0; i<model2.getRowCount();i++){
                txtCodePd.setText(model2.getValueAt(i, 0).toString());
                txtQteV.setText(model2.getValueAt(i, 1).toString());
                q1=Integer.parseInt(txtQteV.getText());
            try{
                st=conn.obtenirConnexion().createStatement();
                Rs=st.executeQuery("SELECT * FROM produits where CodePd='"+txtCodePd.getText()+"'");
            }catch(SQLException e){System.err.println(e);}
                Rs.next();
                int oldQte=Rs.getInt(3);
//q1 est la quantité à diminuer du stock
                oldQte=oldQte-q1;
                String oq=Integer.toString(oldQte);
                txtQteVTable.setText(oq);
                st.executeUpdate("UPDATE produits SET QtePd ='"+txtQteVTable.getText()+"' WHERE CodePd= "+txtCodePd.getText());
            }           
        }catch(SQLException e){System.err.print(e.getMessage());}
}        

Merci de me répondre...@mar
A voir également:

3 réponses

KX
Messages postés
16568
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
5 juillet 2022
124
30 juil. 2016 à 13:05
Bonjour,

Visiblement il y a des incompréhensions sur les exceptions...

System.err.println(e);
n'est pas suffisant pour obtenir des informations sur l'erreur, il vaudrait mieux utiliser
e.printStackTrace();
ou des Logger.

De plus ce code n'a pas de sens :
try {
    st=conn.obtenirConnexion().createStatement();
    Rs=st.executeQuery("SELECT * FROM ...");
} catch(SQLException e) {
    System.err.println(e);
}
Rs.next();

Si tu obtiens une erreur lors de la connexion, ou l'exécution de la requête alors ça ne sert à rien de faire un Rs.next(), tu ne pourras jamais avoir de résultats à ta requête puisqu'elle a échouée dans le try/catch

De plus, st et Rs devraient être des variables locales, ça n'a pas de sens de les déclarer au niveau de l'objet, ça va entraîner des effets de bords monstrueux, et c'est d'ailleurs le cas dans ton erreur :

"Operation not allowed after ResultSet closed" car tu as du utiliser Rs dans une autre méthode, où tu l'as fermé, sauf que tu le réutilises dans cette méthode où la connexion ou la requête ont du planter mais tu essayes quand même de faire un Rs.next() sur l'ancienne valeur de Rs, celle de l'autre méthodes... un beau bazar.

Remarque : je t'incites à utiliser un try-with-resources pour faire des ouvertures et fermetures propres de tes connexions, ainsi que des PreparedStatement pour éviter des injections SQL

https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html

Et pour simplifier ton code, je t'invites à clairement séparer ton code Swing de ton code de base de données, en appelant des méthodes séparées.

Exemple :

public int getQtePd(String codePd) throws SQLException {
    try (Connection conn = obtenirConnexion()) {
        String sql = "SELECT QtePd FROM produits where CodePd = ?";
        try (PreparedStatement st = conn.prepareStatement(sql)) {
            st.setString(1, codePd);
            try (ResultSet rs = st.executeQuery()) {
                if (!rs.next()) {
                    throw new IllegalStateException("getQtePd has no row for " + codePd);
                }
                int qte = rs.getInt("QtePd");
                if (rs.next()) {
                    throw new IllegalStateException("getQtePd has more than 1 row for " + codePd);
                }
                return qte;
            }
        }
    }
}

public void setQtePd(String codePd, int qtePd) throws SQLException {
    try (Connection conn = obtenirConnexion()) {
        String sql = "UPDATE produits SET QtePd = ? WHERE CodePd = ?";
        try (PreparedStatement st = conn.prepareStatement(sql)) {
            st.setInt(1, qtePd);
            st.setString(2, codePd);
            int counts = st.executeUpdate();
            if (counts != 1) {
                throw new IllegalStateException("setQtePd has changed " + counts + " rows for " + codePd + " (1 was expected)");
            }
        }
    }
}

private void enrFactActionPerformed(ActionEvent evt) {
    for (int i = 0; i < model2.getRowCount(); i++) {
        try {
            String codePd = model2.getValueAt(i, 0).toString();
            txtCodePd.setText(codePd);

            String qteV = model2.getValueAt(i, 1).toString();
            txtQteV.setText(qteV);

            int oldQte = getQtePd(codePd);
            int newQte = oldQte - Integer.parseInt(qteV);
            setQtePd(codePd, newQte);

            txtQteVTable.setText(Integer.toString(newQte));
        } catch (SQLException | RuntimeException e) {
            Logger.getLogger(getClass().toString()).log(Level.SEVERE, "Can't enrFactActionPerformed: " + i, e);
        }
    }
}
0
zerargui
Messages postés
65
Date d'inscription
vendredi 24 octobre 2008
Statut
Membre
Dernière intervention
25 février 2019

31 juil. 2016 à 10:05
Merci beaucoup KX..
0
zerargui
Messages postés
65
Date d'inscription
vendredi 24 octobre 2008
Statut
Membre
Dernière intervention
25 février 2019

31 juil. 2016 à 10:24
Bonjour KX,
J'ai une erreur comme indiquée sur l'image :


cann't find symbol
Symbol : Method obtenirConnection()



Local variable hides a field.
0
KX
Messages postés
16568
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
5 juillet 2022
124
31 juil. 2016 à 13:01
obtenirConnexion()
c'était une méthode dans ton code...

try {
    st=conn.obtenirConnexion().createStatement();
    Rs=st.executeQuery("SELECT * FROM produits where CodePd='"+txtCodePd.getText()+"'");
}
0
zerargui
Messages postés
65
Date d'inscription
vendredi 24 octobre 2008
Statut
Membre
Dernière intervention
25 février 2019
> KX
Messages postés
16568
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
5 juillet 2022

Modifié par zerargui le 31/07/2016 à 22:23
Voici la class Connecter où je fais appel à obtenirConnection
package MyFrames;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Connecter {
//creation de la variable con de type Connection
Connection con;

public Connecter() throws InstantiationException, IllegalAccessException, SQLException {

try{
// chargement de la classe par son nom
Class c = Class.forName("com.mysql.jdbc.Driver") ;
Driver pilote = (Driver)c.newInstance() ;
// enregistrement du pilote auprès du DriverManager
DriverManager.registerDriver(pilote);
System.out.println("Driver jdbc chargée");
}catch(ClassNotFoundException e){System.err.println(e);}

try{
con=DriverManager.getConnection("jdbc:mysql://localhost:3306/gestcom","root","");
System.out.println("Connection établie");
}catch(SQLException e){System.err.println(e);
System.out.println("SQLException: " + e.getMessage());
System.out.println("SQLState: " + e.getSQLState());
System.out.println("VendorError: " + e.getErrorCode());}
}
Connection obtenirConnexion(){return con;}
}
0
KX
Messages postés
16568
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
5 juillet 2022
124 > zerargui
Messages postés
65
Date d'inscription
vendredi 24 octobre 2008
Statut
Membre
Dernière intervention
25 février 2019

Modifié par KX le 1/08/2016 à 00:41
À tester :

public class GestComDatasource {

    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException("Can't load MySQL Driver", e);
        }
    }
    
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/gestcom", "root", "");
    }
}

Puis dans mon code, tu adaptes :

public int getQtePd(String codePd) throws SQLException {
    try (Connection conn = GestComDatasource.getConnection()) {
0
zerargui
Messages postés
65
Date d'inscription
vendredi 24 octobre 2008
Statut
Membre
Dernière intervention
25 février 2019
> KX
Messages postés
16568
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
5 juillet 2022

1 août 2016 à 10:19
Bonjour KX,
le projet est bien compilé mais une erreur à l’exécution :

GRAVE: Can't enrFactActionPerformed: 3
java.lang.IllegalStateException: getQtePd has no row for
at MyFrames.FrameVentes.getQtePd(FrameVentes.java:1518)
at MyFrames.FrameVentes.enrFactActionPerformed(FrameVentes.java:1499)
at MyFrames.FrameVentes.access$2800(FrameVentes.java:24)
at MyFrames.FrameVentes$29.actionPerformed(FrameVentes.java:720)


à la ligne du code suivant dans la méthode getQtePd() :

throw new IllegalStateException("getQtePd has no row for " + codePd);
0
KX
Messages postés
16568
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
5 juillet 2022
124 > zerargui
Messages postés
65
Date d'inscription
vendredi 24 octobre 2008
Statut
Membre
Dernière intervention
25 février 2019

1 août 2016 à 17:49
GRAVE: Can't enrFactActionPerformed: 3 
java.lang.IllegalStateException: getQtePd has no row for 

Cela signifie que dans ta table model2, à la ligne 3 (la 4è ligne vu qu'on commence à 0), tu as codePd="" et que cette valeur n'existe pas en base de données, il ne peut donc pas la traiter correctement.
Il va falloir rajouter un peu de code pour gérer les cas particuliers mais s'il ne plante qu'à la 4è ligne ça veut dire qu'il a réussi les 3 premières apparemment donc on doit pas être trop loin du résultat...
0