web-dev-qa-db-fra.com

JDBC renvoie un jeu de résultats vide

J'utilise JDBC pour une connectivité de base de données très simple.

J'ai créé ma connexion/instruction et exécuté une requête . Je vérifie l'objet de requête de l'instruction dans le débogueur pour confirmer l'envoi d'une requête appropriée . J'ai ensuite revérifié la requête (copiée directement à partir du débogueur ) sur la base de données pour s’assurer qu’elle renvoie les données . Le jeu de résultats renvoyé donne cependant la valeur false pour .next ()

Y a-t-il des pièges courants ici qui me manquent?

public List<InterestGroup> getGroups() {
    myDB.sendQuery("select distinct group_name From group_members where
            username='" + this.username + "'");
    ResultSet results = myDB.getResults();
    List<InterestGroup> returnList = new ArrayList<InterestGroup>();
    try {
        while (results.next()) {
            returnList.add(new InterestGroup(results.getString("group_name"), myDB));
        } 
        return returnList;
    } catch (SQLException e) {
        e.printStackTrace();
        return null;
    }

}

Et la classe myDB (un simple wrapper qui me permet de déposer le code de connexion/instruction dans n’importe quel projet)

public void sendQuery(String query){
    this.query = query;
    try {
        if(statement == null){
            statement = connection.createStatement();
        }
        results = statement.executeQuery(query);
    } catch (SQLException e) {
        System.out.println(query);
        currentError = e;
        results = null;
        printError(e, "querying");
    }

}

public ResultSet getResults(){
    return results;
}

EDIT: Sur la base de suggestions, j'ai surtout réorganisé mon code mais j'ai toujours le même problème. Vous trouverez ci-dessous une partie simplifiée du code qui pose le même problème.

private boolean attemptLogin(String uName, String pWord) {

    ResultSet results;
    try{
        try {
            Class.forName("Oracle.jdbc.driver.OracleDriver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        connection =DriverManager.getConnection(connectionString,user,password);
        PreparedStatement statement = connection.prepareStatement("select username from users where username='testuser'");
        results = statement.executeQuery();
        if(results != null && results.next()){
            System.out.println("found a result");
            statement.close();
            return true;
        }
        System.out.println("did not find a result");
        statement.close();
        return false;
    }catch(SQLException e){
        e.printStackTrace();
        return false;
    }

}

J'ai également codé en dur la requête en place pour l'instant pour éliminer cette source d'erreur. Même problème que précédemment (cela se produit avec toutes les requêtes). Le débogueur montre que tous les objets sont instanciés et qu'aucune trace de pile n'est imprimée. De plus, je peux utiliser le même code (et le code plus complexe répertorié précédemment) dans un projet différent.

16
dpsthree

Je l'ai compris ... stupide Oracle n'aimait pas le nombre de connexions simultanées que j'avais (toutes les deux, une pour la console, une pour Java). Malheureusement, le serveur n'est pas sous mon contrôle, je vais donc devoir m'en occuper. Vous penseriez que Oracle fournirait une meilleure réponse. Au lieu de cela, il a simplement renvoyé des ensembles de résultats vides.

Merci pour les réponses

edit Depuis que cela a été demandé/répondu, un certain nombre de personnes ont fait remarquer que la cause sous-jacente était plus probablement liée aux paramètres de validation/transaction utilisés. Assurez-vous de voir les autres réponses pour des astuces supplémentaires et des solutions possibles.

21
dpsthree

Je vois quelques pièges dans votre code, il y a quelques endroits où les choses peuvent mal se passer:

Tout d'abord, utilisez des déclarations régulières. Utilisez instructions préparées pour ne pas avoir de problèmes avec injection SQL .

Au lieu de

statement = connection.createStatement();

utilisation

statement = connection.prepareStatement(String sql);

Avec cela, votre requête devient

"select distinct group_name From group_members where username= ?"

et vous définissez le nom d'utilisateur avec

 statement.setString(1, username);

Ensuite, je n'aime pas utiliser votre classe myDB. Et si les résultats sont null? Vous ne faites pas d'erreur en vérifiant cela dans votre méthode public List<InterestGroup> getGroups()

public void sendQuery(String query) me semble que cela ne devrait pas être void, mais il devrait retourner un ResultSet. En outre, recherchez sur le net les moyens appropriés de gérer les exceptions JDBC.

Aussi, cette ligne:

new InterestGroup(results.getString("group_name"), myDB)

Pourquoi avez-vous myDB comme paramètre?

Je suggérerais d'ajouter plus d'instructions System.out.println dans votre code afin que vous puissiez voir où les choses peuvent mal se passer.

9
darioo

Dans Java.sql.connection, vous devez appeler cette méthode après avoir créé votre connexion:

conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

il existe peut-être une méthode similaire dans Oracle.

5
user805125

La même chose m'est arrivée. J'utilisais SQL Developer pour insérer des données de test dans ma base de données et le lire à l'aide de JDBC. Mais tout ce que j'ai obtenu est un jeu de résultats vide. Je pouvais obtenir les noms des colonnes et tout, mais j'avais un problème avec la lecture des données. Comme souligné par dp trois semaines auparavant, je me suis déconnecté de SQL Developer IDE, puis il m'a demandé de m'engager à la sortie.

Voila! Le problème était que les modifications apportées aux bases de données à l'aide de la commande insert n'étaient pas validées. 

Pour SQL Developer, cela se trouve dans Préférences> Base de données> Avancé> Autocommit

Cela a résolu mon problème.

4
anuvab1911

Le plus commun est d'avoir plusieurs déclarations dans la requête:

desc table;
select * from sometable where etc.;

Pour les instructions qui ne renvoient pas de résultats, vous devez utiliser une construction différente. Même cela causera l'étranglement du client:

select * from sometable where whatever;
select * from sometable where something else;

Les deux ensembles de résultats de même forme seront utiles au client.

3
wallyk

Dans le passé, j'avais des problèmes similaires dans le code tel que celui-ci:

querystr = "your sql select query string"

resultset = statement.executeQuery(querystr)

while (resultset.next())
{
//do something with the data. 
//if you do something fairly involved in this block (sequentially, in the same thread)
//such as calling a function that acts on the data returned from the resultset etc.
//it causes the resultset fetch to wait long enough for resultset.next() to 
//unexpectedly return null in the middle of everything
}

Ce que j'ai fait dans cette situation a été de charger toutes les données dans une structure de données en mémoire locale avec un minimum d'attente sur resultset.next (). Ensuite, j'ai fait tout ce que je devais faire sur les données de la structure de données locale après la fermeture harmonieuse de resultset. Ce comportement était dû à Oracle 10 sur un client backend/JDK 1.6.0_22 sous Unix sous Windows XP.

J'espère que cela t'aides.

2
Chirantan

J'ai ensuite vérifié la requête (copiée directement à partir du débogueur) sur la base de données pour m'assurer qu'elle renvoie des données. 

Des ingénieurs avec ce problème ont démontré cette vérification devant moi. Il s'avère qu'ils ont été connectés avec un compte de base de données dans le programme et avec un compte de base de données différent dans le shell interactif SQL. [C'était Oracle 8.]

2
Bert F

Oui, j'ai eu le même problème que l'OP. Cela se produit lorsque vous avez au moins deux connexions ouvertes avec la base de données sur le même utilisateur. Par exemple, une connexion dans SQL Developer et une connexion en Java. Le résultat est toujours un résultat vide.

EDIT: De plus, j'ai remarqué que cela se produit lorsque vous exécutez une procédure ou que vous insérez dans la base de données et que vous ne commettez pas vos transactions.

1
westman379

Je m'étais connecté au serveur à l'aide du client Plsql et, alors que j'essayais de me connecter à partir de mon code, je me connectais correctement mais il n'y avait aucun enregistrement dans le jeu de résultats. Ce n'est qu'après la déconnexion du serveur que le jeu de résultats a été rempli. Je suis d'accord avec @dpsthree, Oracle doit fournir le message d'erreur/avertissement approprié.

1
Yash

Veuillez vérifier si la connexion et l'instruction Object sont actives jusqu'à ce que vous parcouriez le jeu de résultats. Nous risquons parfois de fermer sans le savoir.

1
gmhk

dans mon cas, la requête qui fonctionnait dans SQL Developer ne fonctionnait pas en Java.

*select * from table where process_date like '2014-08-06%'* (worked in sql developer)

la mise en forme de process_date en char a aidé à le faire fonctionner en Java 

*select * from table where to_char(process_date) = '06-AUG-14'*
0
user3916827

Pour moi, le problème était que lors de la création de la colonne de clé primaire, j'avais NOT NULL ENABLE. Un péché ...

CREATE TABLE SYSTEM_SETTINGS  ( 
  SYSTEM_SETTING_ID NUMBER(9,0) NOT NULL ENABLE, 
    "KEY" VARCHAR2(50 BYTE), 
    "VALUE" VARCHAR2(128 BYTE),
     CONSTRAINT "PK_SYSTEM_SETTINGS" PRIMARY KEY (SYSTEM_SETTING_ID)) 
TABLESPACE USERS;

Quand j'ai recréé la table sans que comme dans

CREATE TABLE SYSTEM_SETTINGS  ( 
  SYSTEM_SETTING_ID NUMBER(9,0), 
    "KEY" VARCHAR2(50 BYTE), 
    "VALUE" VARCHAR2(128 BYTE),
     CONSTRAINT "PK_SYSTEM_SETTINGS" PRIMARY KEY (SYSTEM_SETTING_ID)) 
TABLESPACE USERS;

Cela a commencé à fonctionner via JDBC. J'utilise ojdbc6.jar pour le pilote jdbc.

0
Martin Benns

Il se peut que votre table ne soit pas commit . Essayez d'insérer de nouveaux enregistrements, puis validez dans votre fenêtre de commande d'exécution SQL et exécutez votre code.

0
Shara Rizvi

ResultSet renvoie false même si vous devez obtenir les valeurs de ligne pour la requête et que rs.next () renvoie false car il est possible que vous n'ayez pas écrit commit; sur votre terminal SQL pour la requête. Après cela, vous obtiendrez la valeur True de rs.next ().

0
Sushmita Mitkar