it-swarm.com.de

JDBC gibt leere Ergebnismenge zurück

Ich verwende JDBC für eine sehr einfache Datenbankverbindung.

Ich habe meine Verbindung/Anweisung erstellt und eine Abfrage ausgeführt. Ich überprüfe das Abfrageobjekt der Anweisung im Debugger, um zu bestätigen, dass eine korrekte Abfrage gesendet wird. Ich überprüfte dann die Abfrage (direkt aus dem Debugger kopiert) ) in der Datenbank, um sicherzustellen, dass sie Daten zurückgibt. Das zurückgegebene Resultset gibt jedoch false auf .next () zurück.

Gibt es hier übliche Fallstricke, die ich vermisse?

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

}

Und die myDB-Klasse (einfacher Wrapper, mit dem ich den Verbindungs-/Anweisungscode in einem beliebigen Projekt ablegen kann)

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

BEARBEITEN: Aufgrund von Vorschlägen habe ich meinen Code meistens überarbeitet, habe aber immer noch das gleiche Problem. Nachfolgend finden Sie einen vereinfachten Teil des Codes, der das gleiche Problem aufweist.

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

}

Ich habe die Abfrage jetzt vor Ort hartcodiert, um diese Fehlerquelle zu beseitigen. Gleiches Problem wie zuvor (dies tritt bei allen Abfragen auf). Der Debugger zeigt an, dass alle Objekte instanziiert werden und keine Stapelverfolgungen gedruckt werden. Darüber hinaus kann ich in einem anderen Projekt denselben Code (und den zuvor aufgeführten komplizierteren Code) verwenden.

16
dpsthree

Ich habe es herausgefunden ... dummes Oracle mochte nicht die Anzahl der gleichzeitigen Verbindungen, die ich hatte (alle zwei, eine für Konsole, eine für Java). Leider ist der Server nicht unter meiner Kontrolle, so dass ich mich nur darum kümmern muss. Sie würden denken, dass Oracle eine bessere Antwort liefern würde. Stattdessen wurden leere Ergebnissätze zurückgegeben.

Danke für die Antworten

edit Da dies gefragt/beantwortet wurde, wurde eine Reihe von Leuten darauf hingewiesen, dass die zugrunde liegende Ursache eher mit den verwendeten Commit-/Transaktionseinstellungen zusammenhängt. Bitte sehen Sie andere Antworten für zusätzliche Hinweise und mögliche Lösungen.

21
dpsthree

Ich sehe ein paar Fallstricke in Ihrem Code, es gibt ein paar Stellen, an denen Dinge schief gehen können:

Verwenden Sie zunächst reguläre Anweisungen. Verwenden Sie vorbereitete Anweisungen , damit Sie keine Probleme mit SQL-Injection haben.

Anstatt

statement = connection.createStatement();

benutzen

statement = connection.prepareStatement(String sql);

Damit wird Ihre Abfrage

"select distinct group_name From group_members where username= ?"

und Sie setzen einen Benutzernamen mit

 statement.setString(1, username);

Als nächstes mag ich Ihre myDB-Klasse nicht. Was ist, wenn Ergebnisse null sind? In Ihrer public List<InterestGroup> getGroups()-Methode führen Sie keine Fehlerprüfung durch. 

public void sendQuery(String query) scheint mir nicht void zu sein, sollte aber eine ResultSet zurückgeben. Suchen Sie auch im Internet nach geeigneten Methoden für die JDBC-Ausnahmebehandlung.

Auch diese Zeile:

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

Warum haben Sie myDB als Parameter?

Ich würde vorschlagen, weitere System.out.println-Anweisungen in Ihren Code aufzunehmen, damit Sie sehen können, wo etwas schief gehen kann.

9
darioo

In Java.sql.connection sollten Sie diese Methode aufrufen, nachdem Sie Ihre Verbindung erstellt haben:

conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

vielleicht gibt es in Oracle eine ähnliche Methode.

5
user805125

Dasselbe ist mir passiert. Ich habe SQL Developer verwendet, um Testdaten in meine Datenbank einzufügen und diese mit JDBC zu lesen. Aber alles was ich bekam war ein leeres Ergebnis. Ich konnte die Spaltennamen und alle bekommen, hatte aber ein Problem mit dem Lesen von Daten. Wie zuvor von dpsthree beschrieben, habe ich die Verbindung zum SQL-Entwickler IDE getrennt, und ich wurde dann beim Commit zum Commit aufgefordert.

Voila! Das Problem war, dass die Änderungen an den Datenbanken mit dem Befehl Einfügen nicht festgeschrieben wurden. 

Für SQL Developer befindet sich dies unter Preferences> Database> Advanced> Autocommit.

Das hat mein Problem gelöst.

4
anuvab1911

Am häufigsten werden mehrere Anweisungen in der Abfrage angezeigt:

desc table;
select * from sometable where etc.;

Für Anweisungen, die keine Ergebnisse zurückgeben, müssen Sie ein anderes Konstrukt verwenden. Selbst dann wird der Client verschluckt:

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

Die beiden gleich geformten Ergebnismengen werden den Client verbessern.

3
wallyk

In der Vergangenheit hatte ich ähnliche Probleme mit dem Code:

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
}

Was ich in dieser Situation getan habe, war das Laden aller Daten in eine lokale Speicherdatenstruktur mit minimaler Wartezeit auf resultset.next (). Dann habe ich alles getan, was ich an den Daten aus der lokalen Datenstruktur tun musste, nachdem ich das Ergebnisset ordnungsgemäß geschlossen hatte. Dieses Verhalten wurde bei Oracle 10 unter Unix Backend/JDK 1.6.0_22 unter Windows XP ausgeführt.

Hoffe das hilft.

2
Chirantan

Ich habe dann die Abfrage (direkt aus dem Debugger kopiert) in der Datenbank überprüft, um sicherzustellen, dass sie Daten zurückgibt. 

Ich hatte Ingenieure mit diesem Problem vor mir diese Verifizierung gezeigt. Es stellte sich heraus, dass sie mit einem Datenbankkonto im Programm und mit einem anderen Datenbankkonto in der interaktiven SQL Shell angemeldet waren. [Dies war Oracle 8.]

2
Bert F

Ja, ich hatte das gleiche Problem wie das OP. Dies geschieht, wenn Sie zwei oder mehr Verbindungen mit der Datenbank unter demselben Benutzer haben. Zum Beispiel eine Verbindung in SQL Developer und eine Verbindung in Java. Das Ergebnis ist immer eine leere Ergebnismenge.

BEARBEITEN: Ich habe auch bemerkt, dass es passiert, wenn Sie eine Prozedur ausführen oder in die Datenbank einfügen und Ihre Transaktionen nicht festschreiben.

1
westman379

Ich hatte mich beim Server mit dem plsql-Client angemeldet, und während ich versuchte, eine Verbindung mit meinem Code herzustellen, konnte ich eine Verbindung herstellen, aber es waren keine Datensätze im Ergebnissatz. Erst nach dem Abmelden vom Server wurde die Ergebnismenge aufgefüllt. Ich stimme mit @dpsthree überein, Oracle sollte eine entsprechende Fehler-/Warnmeldung bereitstellen.

1
Yash

Prüfen Sie, ob die Verbindung und die Anweisung Object lebendig sind, bis Sie die Ergebnismenge durchlaufen. Manchmal werden wir möglicherweise unwissentlich geschlossen.

1
gmhk

in meinem Fall funktionierte die Abfrage, die im SQL-Entwickler funktionierte, nicht in Java.

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

das Formatieren von process_date zu char hat dazu beigetragen, dass es in Java funktioniert 

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

Für mich bestand das Problem darin, dass ich bei der Erstellung der Primärschlüsselspalte NOT NULL ENABLE hatte. Wie in ...

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;

Als ich den Tisch ohne das wie in neu erstellt habe

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;

Es begann über JDBC zu arbeiten. Ich verwende ojdbc6.jar für den jdbc-Treiber.

0
Martin Benns

Es kann eine Bedingung sein, dass Ihre Tabelle nicht commit .. __ ist. Versuchen Sie, neue Datensätze einzufügen, und nehmen Sie in Ihrem SQL-Ausführungsbefehlsfenster einen Commit vor, und führen Sie den Code aus.

0
Shara Rizvi

Das resultSet gibt false zurück, obwohl Sie Zeilenwerte für die Abfrage erhalten sollten. Rs.next () gibt false zurück, da Sie möglicherweise nicht commit geschrieben haben. in Ihrem SQL-Terminal für die Abfrage. Danach erhalten Sie rs.next () als True.

0
Sushmita Mitkar