1. Dashboard
  2. Forum
    1. Unerledigte Themen
  3. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team-Mitglieder
    4. Trophäen
    5. Mitgliedersuche
  4. Tutorial Bereich
  • Anmelden
  • Registrieren
  • Suche
Dieses Thema
  • Alles
  • Dieses Thema
  • Dieses Forum
  • Seiten
  • Forum
  • Lexikon
  • Erweiterte Suche
  1. Informatik Forum
  2. Webmaster & Internet
  3. Entwicklung

Oracle-ODBC Treiber bockt

  • java-girl
  • 16. Januar 2008 um 10:44
  • Unerledigt
  • java-girl
    14
    java-girl
    Mitglied
    Reaktionen
    7
    Punkte
    2.037
    Beiträge
    357
    • 16. Januar 2008 um 10:44
    • #1

    Hallo!
    Ich habe zwei kleine Klassen geschrieben, die eine beliebige Tabelle (egal, welches DBMS dahintersteckt) in einer JTable anzeigt. Außerdem kann man neue Datensätze einfügen, löschen und Datensätze verändern.
    Ich habe bisjetzt nur auf MySQL gearbeitet und natürlich sollte es keinen Unterschied machen, ob ich jetzt auf MySQL oder Oracle arbeite, immerhin sind ja die Queries identisch.
    Allerdigs geht bei Oracle nur das auslesen - will ich ein Update, Delete oder Insert machen dann hängt sich das Programm auf.
    Die wesentlichen Stellen:

    Verbindungsaufbau - funktioniert

    Code
    [B][size=10][COLOR=#7f0055][align=left]private void createConnection(String driver, String user, String password){
      try{
       //Parameter
       String url="jdbc:odbc:" + driver;
       //Verbindungsaufbau
       connection=DriverManager.getConnection(url, user, password);
       //Statement Object erzeugen
       statement = connection.createStatement();
    
      }
      catch(SQLException e){
       e.printStackTrace();
       System.out.println(e.getErrorCode());
       add(new JTextField(e.toString()));
      }
     }[/B][/COLOR][/SIZE][size=10][/align]
    [/SIZE]
    Alles anzeigen



    Tabelle auslesen - funktioniert

    Code
    private void refreshTable(){
      String[] columnNames;
      String[][] data;
      try{
       ResultSet rs = statement.executeQuery("SELECT count(*) FROM " + table);
       rs.next();
       int num = rs.getInt(1);
       rs = statement.executeQuery("SELECT * FROM " + table);
       ResultSetMetaData md = rs.getMetaData();
       columnNames = new String[md.getColumnCount()];
       for(int i = 1; i <= md.getColumnCount(); i ++) {
        columnNames[i-1] = md.getColumnName(i);
       }
       data = new String[num][columnNames.length];
       int j = 0;
       while(rs.next()){
        for(int i=1; i <= md.getColumnCount(); i++){
         data[j][i-1] = rs.getString(i);
        }
        j++;
       }
       DataModel m = new DataModel(columnNames, data);
       m.addTableModelListener(new TableListener());
       jTable.setModel(m);
      }
      catch(SQLException e){
       e.printStackTrace();
       add(new JTextField(e.toString()));
      }
     }
    Alles anzeigen



    Neue Datensätze einfügen - funktioniert

    Code
    private class AddButtonListener implements ActionListener{
      @Override
      public void actionPerformed(ActionEvent arg0) {
       StringBuilder build = new StringBuilder("INSERT INTO " + table + " VALUES(");
       for(JTextField t : fields){
        build.append("'" + t.getText() + "', ");
       }
       build.deleteCharAt(build.length()-1);
       build.deleteCharAt(build.length()-1);
       build.append(")");
       try{
        statement.execute(build.toString());
        refreshTable();
       }
       catch(Exception e){
        e.printStackTrace();
       }
       for(JTextField t : fields){
        t.setText("");
       }
     
      }
    
     }
    Alles anzeigen



    Update - funktioniert nicht, hängt sich bei statement.executeUpdate(query.toString()); auf.

    Code
    private class TableListener implements TableModelListener{
      @Override
      public void tableChanged(TableModelEvent evt) {
       DataModelEvent m = (DataModelEvent)evt;
       int row = evt.getFirstRow();
       StringBuilder query = new StringBuilder("UPDATE " + table + " SET");
       int cols = jTable.getModel().getColumnCount()-1;
       for(int i = 0; i < cols; i++){
        query.append(" " + jTable.getModel().getColumnName(i) + "='");
        query.append((String)jTable.getModel().getValueAt(row, i));
        query.append("',");
       }
       query.deleteCharAt(query.length()-1);
       query.append(" WHERE " + jTable.getModel().getColumnName(0) + "='" + m.getVal() + "'");
       try{
        statement.executeUpdate(query.toString());
        System.out.println(query.toString());
       }
       catch(SQLException e){
        e.printStackTrace();
        refreshTable();
       }
      }
    
     }
    Alles anzeigen



    Datensatz löschen - funktioniert nicht, hängt sich ebenfalls an der selben Stelle auf.

    Code
    [B][size=10][COLOR=#7f0055][align=left]private class DeleteButtonListener implements ActionListener{
      @Override
      public void actionPerformed(ActionEvent arg0) {
       DataModel m = (DataModel)jTable.getModel();
       int rows = m.getRowCount();
       for(int i = 0; i < rows; i++){
        if(m.isRowSelected(i)){
         String query = "DELETE FROM " + table + " WHERE " + m.getColumnName(0) + "='" + m.getValueAt(i, 0) + "'";
         try{
          statement.executeUpdate(query);
         }
         catch(SQLException e){
          e.printStackTrace();
          refreshTable();
         }
        }
       }
       refreshTable();
      }
    
     }[/B][/COLOR][/SIZE][size=10][/align]
    [/SIZE]
    Alles anzeigen



    Also scheinbar liegt es an dem executeUpdate - aber wieso? Es müsste doch theoretisch auf jeder Datenbank funtionieren! Hat jemand eine Ahnung, was da genau der Fehler ist bzw. wie man dem ausweichen kann?

    Lg.

    There's no better place than 127.0.0.1!

  • Trux
    12
    Trux
    Mitglied
    Reaktionen
    26
    Punkte
    1.396
    Beiträge
    274
    • 16. Januar 2008 um 10:52
    • #2

    probier mal die spalten namen beim selecten explizit anzugeben.
    also:
    select columnA, columnB, columnC from table;
    anstatt
    select * from table

  • Ringding
    11
    Ringding
    Mitglied
    Reaktionen
    12
    Punkte
    1.237
    Beiträge
    244
    • 16. Januar 2008 um 13:04
    • #3

    Sind das lauter String-Spalten?

  • java-girl
    14
    java-girl
    Mitglied
    Reaktionen
    7
    Punkte
    2.037
    Beiträge
    357
    • 16. Januar 2008 um 15:55
    • #4
    Zitat von Trux

    probier mal die spalten namen beim selecten explizit anzugeben.
    also:
    select columnA, columnB, columnC from table;
    anstatt
    select * from table



    Wieso?
    Immerhin fuktioniert dieses Query ja. Nur bei UPDATE und DELETE gehts nicht.

    Zitat


    Sind das lauter String-Spalten?



    Nein, aber DBMS führen implizite Typecasts durch. Probiers aus. Auf diese Weise spare ich mir die mühsame Unterscheidung der Datentypen, welche wahnsinnig viele sind. Dadurch wird das Query zwar etwas langsamer, aber das wirkt sich nicht wirklich aus.

    There's no better place than 127.0.0.1!

  • Trux
    12
    Trux
    Mitglied
    Reaktionen
    26
    Punkte
    1.396
    Beiträge
    274
    • 16. Januar 2008 um 16:57
    • #5
    Zitat von java-girl

    Wieso?


    freut mich, dass du meinen tipp ausprobiert hast.

  • java-girl
    14
    java-girl
    Mitglied
    Reaktionen
    7
    Punkte
    2.037
    Beiträge
    357
    • 16. Januar 2008 um 17:12
    • #6
    Zitat von Trux

    freut mich, dass du meinen tipp ausprobiert hast.

    Dann erklär' mir mal bitte, was der Unterschied sein soll - immerhin geht ja UPDATE und DELETE nicht und nicht SELECT.

    Im Übrigen...nachdem das Ganze dynamisch ist geht das gar nicht, denn ich weiß im Vorhinein nicht, wie die Spalten heißen.

    There's no better place than 127.0.0.1!

  • Trux
    12
    Trux
    Mitglied
    Reaktionen
    26
    Punkte
    1.396
    Beiträge
    274
    • 16. Januar 2008 um 17:17
    • #7
    Zitat von java-girl

    Dann erklär' mir mal bitte, was der Unterschied sein soll - immerhin geht ja UPDATE und DELETE nicht und nicht SELECT.


    eine zeile im code, die erst wo anders ein problem macht?
    na, das kanns ja wirklich nicht geben. wär ja echt was ganz neues. ich seh schon, du hast mich durchschaut. ich hab natürlich keine ahnung im gegensatz zu dir.

    wenn dir fad is, dann können wir gerne noch ein bisschen 'wieso-weils halt so is' spielen. aber alternativ könntest du natürlich auch was ganz verrücktes machen und einfach ausprobieren was ich dir vor 6h geraten habe.

    ps: der geneigten leserin empfiehlt der trux:
    http://www.dbai.tuwien.ac.at/education/dbs/folien/JDBC.pdf Seite 35

  • java-girl
    14
    java-girl
    Mitglied
    Reaktionen
    7
    Punkte
    2.037
    Beiträge
    357
    • 16. Januar 2008 um 17:24
    • #8
    Zitat von Trux

    eine zeile im code, die erst wo anders ein problem macht?
    na, das kanns ja wirklich nicht geben. wär ja echt was ganz neues. ich seh schon, du hast mich durchschaut. ich hab natürlich keine ahnung im gegensatz zu dir.

    wenn dir fad is, dann können wir gerne noch ein bisschen 'wieso-weils halt so is' spielen. aber alternativ könntest du natürlich auch was ganz verrücktes machen und einfach ausprobieren was ich dir vor 6h geraten habe.

    ps: der geneigten leserin empfiehlt der trux:
    http://www.dbai.tuwien.ac.at/education/dbs/folien/JDBC.pdf Seite 35

    Das war jetzt wenigstens einmal eine Begründung.
    Aber wie gesagt ich glaube nicht dass das mein Fehler ist, denn immerhin mache ich UPDATE und DELETE nicht aus dem ResultSet heraus sondern setze mit executeUpdate() bzw. execute() hab' ich auch schon ausprobiert - ein eigenes, syntaktisch richtiges Query ab. Das Beispiel auf der Folie ist ein anderes.
    Außerdem kann ich es jetzt gerade nicht ausprobieren, habe es nicht da.

    There's no better place than 127.0.0.1!

  • Trux
    12
    Trux
    Mitglied
    Reaktionen
    26
    Punkte
    1.396
    Beiträge
    274
    • 16. Januar 2008 um 17:40
    • #9

    welche fehlermeldung bekommst du denn?

  • java-girl
    14
    java-girl
    Mitglied
    Reaktionen
    7
    Punkte
    2.037
    Beiträge
    357
    • 16. Januar 2008 um 17:43
    • #10

    Eben gar keine, das gesamte Programm hängt sich auf. Er kommt bis vor die Anweisung statement.executeUpdate() und dort bleibt er dann hängen. Und wie gesagt, execute() liefert selbiges Ergebnis.
    Hab' auch schon 2 verschiedene Oracle-Treiber probiert (die beiden die bei Windows angeboten werden), ist bei beiden gleich.

    There's no better place than 127.0.0.1!

  • Trux
    12
    Trux
    Mitglied
    Reaktionen
    26
    Punkte
    1.396
    Beiträge
    274
    • 16. Januar 2008 um 18:23
    • #11

    probier in jeder methode ein statement zu erzeugen, dann execute aufzurufen, und dann das statement zu schließen. vielleicht lockst du versehentlich mit alten statements die tabelle.

    also so in etwa:

    PHP
    statement = connection.createStatement();
          statement.executeUpdate(query);
          statement.close();
  • java-girl
    14
    java-girl
    Mitglied
    Reaktionen
    7
    Punkte
    2.037
    Beiträge
    357
    • 16. Januar 2008 um 18:30
    • #12

    Kann ich mal probieren, allerdings bezweifle ich das auch, da ja das INSERT funktioniert, welches ebenfalls mit einem stinknormalen execute() abgesetzt wird.

    There's no better place than 127.0.0.1!

  • DePadA
    2
    DePadA
    Mitglied
    Punkte
    40
    Beiträge
    7
    • 16. Januar 2008 um 19:21
    • #13

    Kenn deine Zugriffsreihenfolge nicht aber eventuell fehlt nur ein commit?

    Edit: lieg wohl falsch, autocommit ist ja per default aktiviert ...

  • java-girl
    14
    java-girl
    Mitglied
    Reaktionen
    7
    Punkte
    2.037
    Beiträge
    357
    • 16. Januar 2008 um 19:31
    • #14
    Zitat von DePadA

    Kenn deine Zugriffsreihenfolge nicht aber eventuell fehlt nur ein commit?

    Die Reihenfolge ist unerheblich, habe es schon mehrmals ausprobiert.
    Wo meinst du dass das commit fehlen könnte?
    Denn nachdem es sich beim execute() bzw. executeUpdate() aufhängt ist ein commit danach nutzlos.

    There's no better place than 127.0.0.1!

  • a9bejo
    21
    a9bejo
    Mitglied
    Reaktionen
    42
    Punkte
    4.697
    Beiträge
    913
    • 16. Januar 2008 um 21:01
    • #15

    Vieleicht eine naive Frage, aber hast Du dich schon mit den selben accountdaten ueber einen anderen client (commandline, Toad oder so) eingeloggt und versucht ein update zu machen? Eventuell blockt das Statement ja auch da. Oder vielleicht hat der Account nicht die notwendigen Rechte, und der Treiber versaut das Errorhandling. Read und Insert Rechte vergeben, aber keine updates oder deletes zu erlauben, macht ja manchmal durchaus Sinn.


    Versuch vielleicht mal ein explizites commit vor dem execute(). Z.b. ein select statement wird erst committed, wenn das ResultSet geschlossen wurde. Vielleicht leaked das ja irgendwo. Prüf deshalb auch ob alle ResultSets ordentlich geschlossen werden.

    Oder ist es vielleicht möglich, dass Teile der Daten, die du verändern möchtest, von anderer Stelle (einem anderen Benutzer / einer anderen App) aus gelockt sind?

    lg, Benjamin Ferrari, bookworm.at

  • maciek
    16
    maciek
    Mitglied
    Punkte
    2.805
    Beiträge
    434
    • 16. Januar 2008 um 23:29
    • #16
    Zitat von a9bejo

    Vieleicht eine naive Frage, aber hast Du dich schon mit den selben accountdaten ueber einen anderen client (commandline, Toad oder so) eingeloggt und versucht ein update zu machen? Eventuell blockt das Statement ja auch da. Oder vielleicht hat der Account nicht die notwendigen Rechte, und der Treiber versaut das Errorhandling. Read und Insert Rechte vergeben, aber keine updates oder deletes zu erlauben, macht ja manchmal durchaus Sinn.

    Versuch vielleicht mal ein explizites commit [b]vor[.b] dem execute(). Z.b. ein select statement wird erst committed, wenn das ResultSet geschlossen wurde. Vielleicht leaked das ja irgendwo. Prüf deshalb auch ob alle ResultSets ordentlich geschlossen werden.


    das Erstere würde ich auch empfehlen. Lass Dir mal nur die sql command ausgeben ohne sie auszuführen. Nimm die command und lass sie über tora, toad, oder was auch immer laufen. Geht das?

    Was das commit (!) einer select command betrifft, so bin ich ein bissi sprachlos. Soweit meine bescheidenen Oracle-DB-Kenntnisse reichen: Es gibt entweder ein select, dann auch ein ResultSet, aber nix zu committen. Oder aber es ist eine modifying command (insert/update/delete), dann kann man zwar was committen (es sei denn es ist autocommit eingestellt), aber es wird kein ResultSet zurückgeliefert.

    Im übrigen werden alle ResultSets geschlossen, wenn die Connection geschlossen wird.

    *** Make it idiot proof, and someone will build a better idiot. ***

  • a9bejo
    21
    a9bejo
    Mitglied
    Reaktionen
    42
    Punkte
    4.697
    Beiträge
    913
    • 16. Januar 2008 um 23:49
    • #17
    Zitat von maciek

    Was das commit (!) einer select command betrifft, so bin ich ein bissi sprachlos. Soweit meine bescheidenen Oracle-DB-Kenntnisse reichen: Es gibt entweder ein select, dann auch ein ResultSet, aber nix zu committen. Oder aber es ist eine modifying command (insert/update/delete), dann kann man zwar was committen (es sei denn es ist autocommit eingestellt), aber es wird kein ResultSet zurückgeliefert.

    Aus java.sql.Connection#setAutoCommit(boolean):
    "The commit occurs when the statement completes. ...For Select statements, the statement is complete when the associated result set is closed."

    Stell dir mal vor Du machst ein select auf eine Tabelle, dann machst Du ein Update auf die Tabelle, und dann ließt Du aus dem ResultSet. Es kann meines Wissens nach nicht garantiert werden, das die Daten hinter dem ResultSet zwischengespeichert werden. D.h. Es kann einen Konflikt mit dem Update geben, solange das Select nicht vollstaendig abgeschlossen ist.


    Zitat von maciek


    Im übrigen werden alle ResultSets geschlossen, wenn die Connection geschlossen wird.

    Stimmt, aber die Connections werden ja in der Regel wiederverwendet. Wenn Java Girl hinter ihrem Driver Manager einen Connectionpool hat, dann wird während der ganzen Prozedur vielleicht nur eine einzige Connection aufgebaut. In jedem Fall darf man sich aber nicht darauf verlassen, das ein ResultSet durch die Connection geschlossen wird. Manche Pools benutzen z.b. eine Wrapper-Klasse ueber der eigentlichen Connection und wenn Du close() aufrufst, wir die Connection tatsaechlich nur für den nächsten Zugriff freigegeben.

    lg, Benjamin Ferrari, bookworm.at

  • maciek
    16
    maciek
    Mitglied
    Punkte
    2.805
    Beiträge
    434
    • 17. Januar 2008 um 11:26
    • #18
    Zitat von a9bejo

    Aus java.sql.Connection#setAutoCommit(boolean):
    "The commit occurs when the statement completes. ...For Select statements, the statement is complete when the associated result set is closed."

    Stell dir mal vor Du machst ein select auf eine Tabelle, dann machst Du ein Update auf die Tabelle, und dann ließt Du aus dem ResultSet. Es kann meines Wissens nach nicht garantiert werden, das die Daten hinter dem ResultSet zwischengespeichert werden. D.h. Es kann einen Konflikt mit dem Update geben, solange das Select nicht vollstaendig abgeschlossen ist.


    also was in der generischen Connection Klasse steht, mag eine Sache sein. Bei Oracle kann aber ein read Zugriff in der Regel nicht von einem modifying Zugriff "geblockt" werden. Ich habe jetzt leider nicht die Zeit, einen passenden Link zu diesem Thema zu finden. Kann aber zu diesem Thema allen das Buch "Expert Oracle Datbase Architecture" von Thomas Kyte (das ist der von "ask Tom" bei oracle) sehr empfehlen.

    Zitat von a9bejo


    Stimmt, aber die Connections werden ja in der Regel wiederverwendet. Wenn Java Girl hinter ihrem Driver Manager einen Connectionpool hat, dann wird während der ganzen Prozedur vielleicht nur eine einzige Connection aufgebaut. In jedem Fall darf man sich aber nicht darauf verlassen, das ein ResultSet durch die Connection geschlossen wird. Manche Pools benutzen z.b. eine Wrapper-Klasse ueber der eigentlichen Connection und wenn Du close() aufrufst, wir die Connection tatsaechlich nur für den nächsten Zugriff freigegeben.


    Also erstens habe ich gestern in der Eile etwas zu schnell getippt: Eigentlich wollte ich sagen, dass beim Schließen jedes Statements die dazugehörigen ResultSets ebenfalls geschlossen werden.

    Zweitens gebe ich Dir recht, dass Statements und ResultSets immer explizit geschlossen werden sollten und nicht der Java garbage collection überlassen werden sollten, weil man sonst schnell in cursor overflow Probleme geraten kann. Und das mit dem nicht schließen der connection in einem Pool stimmt natürlich auch.

    Drittens halte ich es für unwahrscheinlich, dass sich statements - auch wenn sie modifying sind - einer connection gegenseitig locken können. Außer die connection wird aus irgendeinem Grund an zwei Threads übergeben, die wirklich gleichzeitig versuchen modifying statements auszuführen. Dann muss eine Ausführung warten, bis die andere ausgeführt worden ist, aber nicht bis die erste Änderung commited worden ist.

    Nimm Dir einfach mal tora oder toad her und exekutiere zwei modifying statements hintereinander auf der gleichen Tabelle. Da musst Du auch nicht das erste committen bevor Du das zweite ausführst. Wenn Du aber zwei connections aufmachst, dann wirst Du sehen, dass Du das erste (auf der ersten connection) committen musst, bevor Du das zweite modyfing statement ausführen kannst. Bei einem read Zugriff über die zweite connection wirst Du nie Probleme haben.

    *** Make it idiot proof, and someone will build a better idiot. ***

  • Ringding
    11
    Ringding
    Mitglied
    Reaktionen
    12
    Punkte
    1.237
    Beiträge
    244
    • 17. Januar 2008 um 12:08
    • #19

    Also zumindest bei MySQL/InnoDB kann man die Effekte, die a9bejo meint, ziemlich gut beobachten. Aber es kann schon sein, dass sich Oracle anders/"besser" verhält.

  • java-girl
    14
    java-girl
    Mitglied
    Reaktionen
    7
    Punkte
    2.037
    Beiträge
    357
    • 17. Januar 2008 um 12:20
    • #20
    Zitat von a9bejo

    Vieleicht eine naive Frage, aber hast Du dich schon mit den selben accountdaten ueber einen anderen client (commandline, Toad oder so) eingeloggt und versucht ein update zu machen? Eventuell blockt das Statement ja auch da. Oder vielleicht hat der Account nicht die notwendigen Rechte, und der Treiber versaut das Errorhandling. Read und Insert Rechte vergeben, aber keine updates oder deletes zu erlauben, macht ja manchmal durchaus Sinn.

    Ja habe ich. Mein Benutzer hat alle Rechte und die von mir produzierten Queries waren OK, ich habe sie vorher ausprobiert.

    Zitat von a9bejo


    Versuch vielleicht mal ein explizites commit [b]vor[.b] dem execute(). Z.b. ein select statement wird erst committed, wenn das ResultSet geschlossen wurde. Vielleicht leaked das ja irgendwo. Prüf deshalb auch ob alle ResultSets ordentlich geschlossen werden.

    Das ResultSet (gibt eh nur eines, das in der Methode mit dem SELECT) habe ich nicht geschlossen...vielleicht liegt es wirklich an dem!

    Zitat von a9bejo


    Oder ist es vielleicht möglich, dass Teile der Daten, die du verändern möchtest, von anderer Stelle (einem anderen Benutzer / einer anderen App) aus gelockt sind?

    Das wäre ebenfalls möglich, ich hatte nämlich zu diesem Zeitpunkt eine SQL Kommandozeile offen.

    Danke, ich werde das einmal ausprobieren, geht aber erst frühestens am Montag, dann werde ich mich melden.

    There's no better place than 127.0.0.1!

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!

Benutzerkonto erstellen Anmelden

Benutzer online in diesem Thema

  • 1 Besucher

Rechtliches

Impressum

Datenschutzerklärung