Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
ich zerbreche mir gerade darüber etwas den Kopf:
Man benötigt an vielen verschiedenen Stellen im Programm eine Verbindung zu einer bestimmten Datenbank. Um nicht ständig eine neue Verbindung herstellen zu müssen, instanziiert man am Anfang eine Klasse, die die Verbindung aufbaut und das Statement als Klassenvariable speichert, auf die dann immer über eine Klassenmethode zugegriffen wird, sodass die SQL-Anfrage gleich gestartet werden kann.
Connection irgendwo zu speichern ist kein Unding,
dafür gibts verschiedene Varianten, statt zentral kann es auch durch Hintergrundprozesse recht unauffällig überall hingeschoben werden (Injection),
pauschal nicht zu sagen, solange es geht ist es schon nicht schlecht
das Statement musst du nicht unbedingt speichern, neues Statement auf Connection ist nahezu gleichwertig,
wenn du über Methode getStatement() gehts ist sogar austauschbar, ob intern ein gespeichertes Statement zurückgegeben
oder die Connection um ein neues Statement gebeten wird,
close() im letzteren Fall nicht vergessen
wie alles kann man das natürlich vereinfachen,
wenn es x Objekte gibt die die Connection brauchen, dann gibt es <= x Stellen wo diese erzeugt werden,
an diesen Stellen könnten sie im Konstruktor oder noch unauffälliger in Hintergrund-init-Methoden die benötigten Standard-Daten übergeben bekommen -> schon sind sie da, nix weltbewegendes
für eine einfache Applikation ohne Threads reicht eine Connection, das denke ich auch
Ich finde, auch in einer 2-Schicht-Anwendung ist ein Connection-Pool sehr hilfreich. Er kümmert sich um ein Reconnect bei Timeouts oder sonstigen Verbindungsabbrüchen, Connections werden automatisch geschlossen, wenn man sie nicht mehr braucht - das spart Ressourcen, usw.
Das möchte man nicht selber programmieren, wenn man nicht muss.
Dieser Treiber beinhaltet anscheinend auch eine 'Connection Pool Data Source class' und eine 'singletonConnection'. Beides ist komplettes Neuland für mich und es wäre sehr nett, wenn jemand auf meine beiden Fragen eingehen könnte:
1.) Was ist der Unterschied zwischen einem 'Connection Pool', einer 'Singleton Connection' und einer 'Dependency injection'?
2.) Wenn man den "singletonConnection"-Modus aktiviert hat, spielt es doch keine Rolle (mal abgesehen davon, dass es ganz schlechter Stil ist), wenn man an jeder Stelle im Programm, an der man eine Verbindung zur ein und derselben Datenbank benötigt, ständig ein
schreibt, da der Treiber mit aktivierter 'singletonConnection' ohnehin nur eine einzige Verbindung zu dieser Datenbank zulässt; oder sehe ich das falsch?
> Reconnect bei Timeouts oder sonstigen Verbindungsabbrüchen,
noch nie irgendwo je gesehen, aber wenn es sein muss
> Connections werden automatisch geschlossen, wenn man sie nicht mehr braucht - das spart Ressourcen
wenn ewig gebraucht und die ganze Zeit eine Connection offen, dann ist die Sache einfach
hallo, habe die gleiche Frage, die Anworten sind mir noch zu unkonkret.
also: Eine Desktop-Anwendung verwendet die DB (Derby) im embedded Modus. Um nicht jedesmal eine Verbindung aufbauen zu müßen besitzt die Anwendung eine Klasse Datenbank, die ua während der Laufzeit der Anwendung eine ständig Verbindung zur Datenbank hält ( Variable con ). Die Klasse soll auch als "Anlaufpunkt" für andere Objekte/Methoden dienen und die Zugriffe auf die DB "kapseln" -> spricht fungiert als "Utility-Objekt" (weniger Schreibaufwand etc)
Die Anwendung ermöglicht es eine Tabelle x gleichzeitigzu beschreiben und zu lesen .
Bsp: Tabelle x enthält Analyse-Daten -> ( pro Analyse ca 300.000 Datensätze). Damit der Anwender während die Analyse-Daten Erzeugung läuft (schreiben der Werte in die DB) weiter arbeiten kann.(auswerten der Daten etc).
Die Anwendung muß natürlich sicherstellen, das der Anwender lediglich die "fertigen" Daten auswerten kann .... so weit so gut.
Die Verbindung (Variable con) wird doch lediglich benötigt damit man überhaupt man der Datenbank etwas machen kann (insert / update) ????. Wohl der "Kommunikations-Kanal" zwischen Datenbank und Programm. Über diese Kanal teilt man der Datenbank mit was zu erledigen ist:
a) ein simples Statement
b) eine Transaktion (kapselt diverse Statements / Stichwort CRUD)
ich gehe mal davon aus, das wenn man eine Statement/Transaktion an die DB abschickt, das dann der Kommunikationsweg blockiert ist, sprich die Anwendung muß warten bis die Transaktion beendet ist. Das hätte dann zur Folge das man die SandUhr sieht, solange die DB am werkeln ist. bzw wenn mehre Threads die gleiche Verbindung verwenden, wäre dann wohl auch die Sanduhr sichtbar oder vielleicht sogar exceptions, da die Verbindung nicht doppelt genutz werden kann.
Das Ziel ist wohl, keine Exceptions / Sanduhr zu erzeugen, deswegen sollte man sich wohl mit Connections-Pools auch bei Desktop-Anwendungen auseinandersetzen ??? -> dh die obige Klasse hätte dann wohl ein Connection-Pool Objekt .
@all bitte kein Hinweis auf ORM`s etc .... dafür kann man einen anderen thread aufmachen... die Vereinfachen sicherlich vieles, aber Hintergrundwissen ist sicherlich nicht von Nachteil
was ist denn die Frage, wieder ob das so ok ist?
bisher hast du nur eine Klasse mit Connection als Attribut, das ist so ok, meiner Meinung nach,
wenig überraschend nach den vorherigen Postings
hauptsächlich Nachfrage ob nicht noch eine andere Frage besteht/ es um ein genaueres Detail geht
> ich gehe mal davon aus, das wenn man eine Statement/Transaktion an die DB abschickt, das dann der Kommunikationsweg blockiert ist
Das Ziel ist wohl, keine Exceptions / Sanduhr zu erzeugen, deswegen sollte man sich wohl mit Connections-Pools auch bei Desktop-Anwendungen auseinandersetzen ???
-> da aus meiner Sicht, bei Verwendung von threads mit DB-zugriff, diese sich durch die eine Connection sperren, bzw eine Exception ausgelößt wird .... stimmt da meine Vermutung ?
'stimmt / mag sein' sagt doch beides das gleiche aus, von der Nuance abgesehen, dass ich es nicht mit Sicherheit sagen kann?
wobei ich noch konkretiersen kann, dass es sicherlich keine programmatische Blockierung ist, beliebige Threads können mit der Connection arbeiten, da wird nichts gesperrt, es gibt keine Exception,
fachlich sollte aber die Connection exklusiv sein, es ist deine Aufgabe bzw. die für einen ConnectionPool usw., dafür zu sorgen
Nein auf keinen Fall. Die Verbindung zur Datenbank aufbauen ist etwas sehr teures. Das kann schon sein, dass das bis zu einer Sekunde dauert, ich würde Verbindungen auf jeden Fall in einem Pool cachen....
und in einer einfachen Anwendung ohne konkurrierende Threads mit mehreren Verbindungen reicht doch wohl
eine Connection in einer statischen Variable als 'Cache'?
mhnn... du itererierst übers ResultSet und möchtest für jeden Datensatz nochwas nachladen/updaten/löschen... ok man könnte es auch über ein komplexeres query machen, aber wenn nicht hast du schon das problem, dass du eine zweite verbindung brauchst...
Ein Connection-Pool kann ein Reconnect auslösen, falls sich die DB-Verbindung wegen Timeout o.ä. geschlossen hat. Auch kann der Pool die Connection bei längerer Nichtbenutzung automatisch schließen und so Ressourcen sparen. Das möchte man nicht von Hand programmieren.
> schon das problem, dass du eine zweite verbindung brauchst...
eine Connection kann mehrere Statements haben, das funktioniert, nur mit nebenläufigen Transaktionen, eben Threads, wird es eine Stufe höher
das Sparen bei Schließen habe ich ja schon früher angesprochen,
in einem einfachen Programm kommt es nie zu Timeouts, nie sind Ressourcen etwas worüber man nachdenkt,
eine Connection auf und fertig, das ist die einfachste Variante die normalerweise für alles (einfache) funktioniert,
was passiert bei einem Timeout mit offenen Transaktionen?
wie werden mehrstufige Verarbeitungschritte mit Exception korrekt abgebrochen und neu gestartet?
nur auf ConnectionPool zu verweisen löst überhaupt keine Probleme
einen so schwerwiegender Fehler wie ein Problem mit der Datenbank kann in einem einfachen Programm nicht sinnvoll behandelt werden,
jedenfalls (in der Regel) nicht von jemanden der überlegt ob eine Connection in einer statischen Variable abgelegt wird,
aus und neu an
75% aller einfachen Programme laufen sowieso nicht mehr als paar sec, und vom Rest sind 24% Dummy-GUI-Programme, die auch nicht viel mehr leisten,
die ganze Diskussion ist für mich surreal,
wenn man die entsprechenden Anforderungen hat, Probleme mit mehreren Threads sieht usw., landet man ganz automatisch bei den richtigen Strukturen,
Es muss nicht nebenläufig sein um mehrere Verbindungen zu benötigen.
Gesetzt den Fall, dass man zwei Tabellen hat. Die erste enthält Referenzen auf die zweite. Aus der ersten holt man sich die Referenzen, die eine bestimmte Bedingung erfüllen. Um das Beispiel realistischer zu machen, stehen in der ersten Tabelle noch viele andere Daten und die Ergebnismenge ist sehr sehr groß. Danach möchte man die Daten aus der zweiten Tabelle holen, die zu den gerade verarbeiteten gehören. Ich setzte mal voraus, dass ein simpler JOIN nicht funktioniert, weil das Kreuzprodukt zu groß wäre und die Laufzeit daher in den Keller ginge.
Um mit dem verfügbaren Speicher jetzt hinzukommen, verarbeitet man dann die Daten aus der ersten Tabelle sequentiell und holt sie erst von der Datenbank, wenn man sie benötigt. Zwischendurch benötigt man die zweite Verbindung, um die weiteren Daten zu verarbeiten.
Das ist kein so konstruiertes Beispiel wie es erscheinen mag - in der Praxis sind mir derartige Fälle schon untergekommen.
@SlaterB
für Einsteiger / Umsteiger ist das sicherlich nicht surreal ! (Wobei einsteiger sicherlich erstmalig die Finger von Threads lassen *g).
Als Umsteiger wäre es ganz gut wenn man bei grundlegenen Dingen aufs richtige Pferd gesetzt wird, was durch diverse Foren manchmal echt schwer wird, bzw man selbst nicht abschätzen kann welchen TIP man folgt. (Komplexität,Halbwissen etc).
zurück zum Topic:
Nach stöbern in der DB-Derby Doku bin ich auf das folgende gestossen (Das scheint sich auf die JDBC allgemein zu beziehen
Pitfalls of sharing a connection among threads
Here is a review of the potential pitfalls of sharing a single Connection among multiple threads.
Committing or rolling back a transaction closes all open ResultSet objects and currently executing Statements, unless you are using held cursors.
If one thread commits, it closes the Statements and ResultSets of all other threads using the same connection.
Executing a Statement automatically closes any existing open ResultSet generated by an earlier execution of that Statement.
If threads share Statements, one thread could close another's ResultSet.
daraus schlussfolgere ich: für Desktop-Anwendungen die Threads nutzen um "flüssigeres" Arbeiten bereitzustellen, fällt eine einzelne Connection flach, dh 1-n "Klassenvariablen oder Connection-Pool (CP).
Connection-Pool: es fehlt mir immer noch ein Grund diese "Fremd-Bibliothek" einzusetzen. Beim suchen im Netz fand ich nichts das für Embedded+CP sprach. Desweitren schreckt mich ab: die x-te LIB die den Standard verbesserte und alles was mit Fremd-Libs zusammenhängt (Stichwort: JODA bzw DATE/TIME, Lizenz geraffel etc).
75% aller einfachen Programme laufen sowieso nicht mehr als paar sec, und vom Rest sind 24% Dummy-GUI-Programme, die auch nicht viel mehr leisten,
die ganze Diskussion ist für mich surreal,
Das wusst ich auch noch nicht. Hast du eine Quelle für diese Zahlen oder stammen sie aus eigener Forschungsarbeit?
Surreal ist allerdings, mit derartigen Argumenten gegen eine tausendfach bewährte best practice anzugehen.
inwiefern widerspricht das dem gerade von dir zitierten Satz 'eine Connection kann mehrere Statements haben'?
natürlich braucht man mehrere offene Query gleichzeitig und genau das leisten mehrere Statements auf eine Connection
zeig mal ein Thema hier im Forum mit ConnectionPool bei JDBC,
Hibernate und JPA sind sowieso viele Stufen höher, da wäre Vorgehen gegen das Framework eher schwierig,
gibt es für JDBC überhaupt einen Pool-Standard?
auch bei google auf die Schnelle nichts gesehen
Connection Pooling
mit OracleConnectionPoolDataSource sieht ja sehr exotisch aus ("JNDI-Lookup"..)
Das dürfte aber vom DBMS abhängen. MySQL kann das nämlich nicht. Wenn man das versucht, dann bekommt man eine lapidare Fehlermeldung, dass die Synchronisation verloren ist.
Beleg hierzu: Auszug aus der Dokumentation der aktuellen MySQL Version. Das Ergebnis einer Query muss demnach erst vollständig abgerufen werden oder das Ergebnis verworfen werden. In dem von mir aufgezeigten Beispiel kann man das Ergebnis aber nicht vorher vollständig in den Speicher laden und verwerfen möchte man es sicherlich auch nicht. Um in diesem Fall mit zwei Abfragen im Wechsel zu arbeiten, muss man zwei Verbindungen aufbauen.
@cmrudolph
nun, wenn das der Fall ist, wäre das ein Punkt, in der Tat,
habe hier zu Java noch nie ein Thema gesehen wo jemand für sequentielle Verarbeitung als Lösung zwei Connections brauchte,
auch für höhere Frameworks, etwa Hibernate getSession() eine gewisse interne Herausforderung, könnte ich mir vorstellen,
klappen Transaktion über mehrere Connections usw?
recht weit unten als Suchergebnis openoffice - dba dev - XOutParameters
mit fraglichen Java-Zusammenhang und auch sonst sehr wenig,
sicher dass das je in JDBC beobachet wurde?
Nein, denn man kann diese Fehlermeldung "umgehen", indem man immer mysql_store_result verwendet. Falls JDBC das intern so macht, tritt diese Fehlermeldung nie auf. Stattdessen würde man in meinem Beispiel einen Speicherfehler bekommen, weil die Ergebnismenge zu groß ist.
Ich werde mal googlen, wie JDBC das handhabt.
[EDIT]
Connector/J Dokumentation hat gesagt.:
By default, ResultSets are completely retrieved and stored in memory. In most cases this is the most efficient way to operate, and due to the design of the MySQL network protocol is easier to implement. If you are working with ResultSets that have a large number of rows or large values, and cannot allocate heap space in your JVM for the memory required, you can tell the driver to stream the results back one row at a time.
[...]
There are some caveats with this approach. You must read all of the rows in the result set (or close it) before you can issue any other queries on the connection, or an exception will be thrown.
Es ist genau wie ich es vermutet habe: per default wird die gesamte Ergebnismenge abgerufen. Wenn man aufgrund der Ergebnismengengröße die Daten zeilenweise abholt, sind keine parallelen Queries mehr möglich (siehe zweiter Teil des Zitates).[/EDIT]
auch für höhere Frameworks, etwa Hibernate getSession() eine gewisse interne Herausforderung, könnte ich mir vorstellen,
klappen Transaktion über mehrere Connections usw?
Nein, Transaktionen über mehrere Connections gibt SQL nicht her. Transaktionen sind zwar primär beim Schreiben von Daten relevant, wenn die Daten aber von einem gelesenen Datensatz abhängen, dürfte es Probleme mit der Transaktion geben. In diesem Fall könnte ich mir vorstellen, dass Hibernate und andere Frameworks Mechanismen wie Optimistic Offline Lock oder Pessimistic Offline Lock verwenden.
Damit werden diese Probleme umgangen.