Oracle-ODBC Treiber bockt

  • 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



    Tabelle auslesen - funktioniert



    Neue Datensätze einfügen - funktioniert



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



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



    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!

  • 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!

  • 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!

  • 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

  • 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!

  • 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!

  • 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();
  • 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!

  • 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!

  • 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?

  • 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. ***

  • 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.



    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.

  • 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.


    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. ***

  • 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.


    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!


    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!