PooledConnection früher schließen oder abarbeitung queuen? wie vorgehen

PFEdi

Mitglied
Hi,

Ich habe hier in einem Projekt vor mir folgenden Code.
Der sieht eigentlich halbwegs sauber aus - aber das Problem ist das die Methode wohl zu oft aufgerufen wird.
Die Datenbank geht wegen der vielen Verbindungen in die Knie (oder eher auf den Boden)
Wenn dann der Finally-block abgearbeitet wird und die Verbindungen zurück gegeben werden ist die Datenbank aber schon hinüber und es bringt nichts mehr.

daher wollte ich euch mal fragen was man da machen kann am Code ohne alles auf den Kopf zu stellen.
Kann man die Verbindung früher schließen und nicht erst "nach dem return" und trotzdem so generisch bleiben?

Oder kann man innerhalb der Methode eine queue machen um es bis zu einer max Anzahl an Verbindungen zu zu lassen und dann eben blockiert?
Da dieser Bereich eigentlich nicht "mein" code ist wollte ich daran möglichst eingeschränkt Änderungen durchführen.

Ich hoffe ihr könnt mir ein paar tips geben


Code:
private <T> T executeQuery(String query, ResultContainer<T> resultContainer, PreSetter... preSetters) throws Exception{
        try {
            Connection c = null;
            try {
                PooledDataSource dataSource = atomicPooledDataSource.get(); // AtomicReference<PooledDataSource>
                if (dataSource == null) {
                    throw new Exception("No DB Connection");
                }
                c = dataSource.getConnection();
                PreparedStatement s = null;
                try {
                    int i = 1;
                    s = c.prepareStatement(query);
                    for (PreSetter preSetter : preSetters) {
                        i = preSetter.prepare(s, i);
                    }
                    ResultSet rs = null;
                    try {
                        rs = s.executeQuery();
                        return resultContainer.result(rs);
                    } finally {
                        if (rs != null) {
                            rs.close();
                        }
                    }
                } finally {
                    if (s != null) {
                        s.close();
                    }
                }
            } finally {
                if (c != null) {
                    c.close();
                }
            }
        } catch (SQLException e) {
            throw new Exception(e.getMessage(), e);
        }
    }

Code ist ein bisschen vereinfacht - aber es sollte alles da sein.
 

mrBrown

Super-Moderator
Mitarbeiter
Code ist ein bisschen vereinfacht
Das ist vereinfachter Code? Dann möchte ich wirklich nicht die normale Variante sehen :p (oder vielleicht doch, ein bisschen Horror mag doch jeder...)

Die Datenbank geht wegen der vielen Verbindungen in die Knie (oder eher auf den Boden)
begrenz doch die Anzahl der möglichen Verbindungen? Wenn du ConnectionPools nutzt, sollte das doch problemlos möglich sein.
In der Methode braucht man dafür nichts ändern (und wenn du da doch was änderst: lösch sie und schreib sie in ~5 Zeilen neu)

Kann man die Verbindung früher schließen und nicht erst "nach dem return" und trotzdem so generisch bleiben?
Die Verbindung wird bereits so früh wie möglich geschlossen, nämlich direkt nachdem du sie benutzt. Vor'm benutzten kannst du sie logischerweise nicht schließen ;)
 

PFEdi

Mitglied
Das ist vereinfachter Code? Dann möchte ich wirklich nicht die normale Variante sehen :p (oder vielleicht doch, ein bisschen Horror mag doch jeder...)
Na zum glück is es dann nicht meiner ... der wäre vl noch schlimmer :D


begrenz doch die Anzahl der möglichen Verbindungen? Wenn du ConnectionPools nutzt, sollte das doch problemlos möglich sein.
In der Methode braucht man dafür nichts ändern (und wenn du da doch was änderst: lösch sie und schreib sie in ~5 Zeilen neu)
Genau dürfte es eine "ComboPooledDataSource()" sein.
Bei der ist wie ich sehe der default 15
https://www.mchange.com/projects/c3p0/#maxPoolSize
sie wird auch nicht anders konfiguriert so wie ich das sehe ... werde noch schauen ob vl andere config geladen wird (bin grad unterwegs und hab keinen zugriff).
Dher verstehe ich dass dann aber auch nicht. Wenn es nur 15 Verbindungen sein sollten- was ist den da los (kann mir nur vorstellen, das das ganze mehrfach instanziiert wird ... was aber auch nicht sein darf (in den logs sehe ich die Initialisierung nur ein mal)

Aber wenn die Limitierung funktionieren würde, würden dann die weiteren aufrufe von "executeQuery" nicht fehlschlagen?
Oder werden die Blockiert bis eine connection frei ist?

In 5 Zeilen? Glaub ich nicht ;)


Die Verbindung wird bereits so früh wie möglich geschlossen, nämlich direkt nachdem du sie benutzt. Vor'm benutzten kannst du sie logischerweise nicht schließen ;)
Hmmm dann dürfte es aber gar kein Problem geben - am Datenbank Server sehe ich aber das die Verbindungen nach oben gehen ... das verstehe ich dann nicht.
 

mihe7

Top Contributor
In 5 Zeilen? Glaub ich nicht
Puh, da musste ich doch ein paar extra Zeilenumbrüche einbauen, damit ich auf die 5 Zeilen komme:
Java:
private <T> T executeQuery(String query, 
        ResultContainer<T> resultContainer, 
        PreSetter... preSetters) throws Exception {
    executeQuery(atomicPooledDataSource.get(), query, resultContainer, preSetters);
}
SCNR :p
 

mrBrown

Super-Moderator
Mitarbeiter
In 5 Zeilen? Glaub ich nicht ;)

7 ist gar nicht so weit entfernt von "etwa 5" (wenn man Klammern mal ignoriert...):p

Java:
private <T> T executeQuery(String query, ResultContainer<T> resultContainer, PreSetter... preSetters) throws SQLException {
    try (Connection c = Objects.requireNonNull(atomicPooledDataSource.get(), "No DB Connection").getConnection();
            PreparedStatement s = c.prepareStatement(query)) {
        int i = 1;
        for (PreSetter preSetter : preSetters) {
            i = preSetter.prepare(s, i);
        }
        return resultContainer.result(s.executeQuery());
    }
}

(Semantik bzgl Exceptions hat sich etwas geändert, da nicht mehr einfach Exception geworfen wird (aber das ist ja auch nicht grundlos Bad Practice....))

(Und dass Objects.requireNonNull lässt sich auch noch vermeiden, wenn man die Klasse drum herum etwas anders aufbaut. Entweder man verhindert null oder ergänzt einen extra Getter für die Connection)
 
Zuletzt bearbeitet:

PFEdi

Mitglied
Muss ich das verstehen?

Java:
private <T> T executeQuery(String query, ResultContainer<T> resultContainer, PreSetter... preSetters) throws SQLException {
    try (Connection c = Objects.requireNonNull(atomicPooledDataSource.get(), "No DB Connection").getConnection();
            PreparedStatement s = c.prepareStatement(query)) {
        int i = 1;
        for (PreSetter preSetter : preSetters) {
            i = preSetter.prepare(s, i);
        }
        return resultContainer.result(s.executeQuery());
    }
}

(Semantik bzgl Exceptions hat sich etwas geändert, da nicht mehr einfach Exception geworfen wird (aber das ist ja auch nicht grundlos Bad Practice....))
OK, sieht natürlich besser aus (wobei erst dann auffällt das resultContainer.result() und preSetter.prepare() exceptions wirft) - aber das probleme mit den connections ist ja nach wie vor das selbe (die connections werden nicht aufgeräumt).
Die limitation ändert sich nicht - und blockieren/warten lässt sich so auch nicht.
 

mihe7

Top Contributor
Muss ich das verstehen?
Nö.

wobei erst dann auffällt das resultContainer.result() und preSetter.prepare() exceptions wirft
Wie meinst Du das?

Die limitation ändert sich nicht - und blockieren/warten lässt sich so auch nicht.
In der Antwort ging es ja auch nur um die Reduzierung des Codes.

Zur Lösung hat Dir @mrBrown ja schon geschrieben, dass Du die Zahl der Verbindungen begrenzen kannst, da Du ja einen Connection Pool verwendest. Was passiert, wenn die maximale Anzahl der Verbindungen erreicht ist, kannst Du ebenfalls einstellen. Siehe dazu https://www.mchange.com/projects/c3p0/#configuring_recovery

Nachtrag: https://www.mchange.com/projects/c3p0/#checkoutTimeout
 

PFEdi

Mitglied
Ach jetzt hätte ich fast darauf vergessen.

Schade - hätte ich aber geren.


Wie meinst Du das?
Die Methoden können Exceptions werfen - aber zu dem grundproblem/dem Thema hier ist das eigentlich eh unwichtig/nebensächlich.


In der Antwort ging es ja auch nur um die Reduzierung des Codes.
Aso :)

Zur Lösung hat Dir @mrBrown ja schon geschrieben, dass Du die Zahl der Verbindungen begrenzen kannst, da Du ja einen Connection Pool verwendest. Was passiert, wenn die maximale Anzahl der Verbindungen erreicht ist, kannst Du ebenfalls einstellen. Siehe dazu https://www.mchange.com/projects/c3p0/#configuring_recovery

Nachtrag: https://www.mchange.com/projects/c3p0/#checkoutTimeout
Naja - das hat ja wie erwähnt nichts geracht ...

Aber das zugrundeliegende Problem dürfte sein, dass die ganze Klasse mehrfach von dem aufrufenden Projekt instanziiert wird - das entzieht sich aber meinem einfluss/einblick (und dürfte sich eben in der letzten version geändert haben).

Sprich meine ideen und eure hilfe sind wohl leider von einem falschen Rahmen-Setting ausgegangen, dass ich erst jetzt erkannt habe. momentan habe ich eine funktionierende version die eplizit die verbindung verwaltet (aufbaut & schließt).

Damit klappte es auch wenn ich keinen einfluss auf die aufrufende Instanz habe.

Sorry, dass mir erst so spät die eigentlich ausschlaggebenden Rahmenbedingungen aufgefallen sind und danke für den input.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
R Wiederholungsrate von Tastatureingaben früher kommen lassen Allgemeine Java-Themen 5
C anderes Programm schließen! Allgemeine Java-Themen 5
MaxG. Swing Frame schließen Allgemeine Java-Themen 9
T Fenster schließen verhindern Allgemeine Java-Themen 13
Tausendsassa Threads Einen Thread sich selbst schließen lassen Allgemeine Java-Themen 17
Tausendsassa Interface Eine Gui von einer anderen schließen lassen Allgemeine Java-Themen 3
F Fenster schließen bei Klick auf Kreuz Allgemeine Java-Themen 14
A Applet Alle Threads beim schließen des Applets beenden Allgemeine Java-Themen 8
T Methode beim Schließen der xhtml Seite? Allgemeine Java-Themen 4
D Dialog soll sich beim Klick auf Button schließen Allgemeine Java-Themen 8
E externen Prozess schließen, wenn Programm geschlossen wird Allgemeine Java-Themen 2
Landei DDE-Probleme und Programm schließen Allgemeine Java-Themen 2
B Algorythmus Lücke in Sequenz schließen Allgemeine Java-Themen 7
B Applet Destruktor beim Browser schließen? Allgemeine Java-Themen 5
B Öffnen und schließen von Pdf-Files Allgemeine Java-Themen 8
nrg Java Observer in SysTray laufen lassen / Console schließen Allgemeine Java-Themen 2
A HTML-Seite wieder schließen Allgemeine Java-Themen 2
A Java-Anwendung "richtig" schließen ohne JVM zu beenden Allgemeine Java-Themen 2
N JTree nicht genutzte Pfade schließen Allgemeine Java-Themen 2
M Programm schließen? Allgemeine Java-Themen 2
E Alle unter Prozesse der beim schließen mit schließen Allgemeine Java-Themen 3
S GUI komplett schließen und wieder Neu laden? Allgemeine Java-Themen 4
A Problem mit ShutdownHook beim schließen Allgemeine Java-Themen 7
O File zum löschen "schließen" Allgemeine Java-Themen 2
M Programm schließen und wieder neu starten Allgemeine Java-Themen 9
MQue Datei- referenz schließen Allgemeine Java-Themen 5
M Methode vor dem Schließen aufrufen Allgemeine Java-Themen 4
P DockingFrames schließen Allgemeine Java-Themen 2
P Pfad schließen xml Allgemeine Java-Themen 3
W Das schließen des JFrame abfangen, wiei? Allgemeine Java-Themen 6
C externes Programm läuft erst nach schließen des mainprogramm Allgemeine Java-Themen 7
G Java-Applet bzw. Browser schließen Allgemeine Java-Themen 3
S automatisches schließen des prog Allgemeine Java-Themen 2
S mit welchem befehl kann ich mein programm autom. schließen Allgemeine Java-Themen 3
Q Methode soll auf schließen eines Frames warten Allgemeine Java-Themen 4
D Fremdes Programm schließen (ohne process.destroy()) Allgemeine Java-Themen 8
A öffnen und schließen von programmen aus java Allgemeine Java-Themen 3
M ALT-F4 fenster schließen unterdrücken Allgemeine Java-Themen 2
P Java --> Anwendungen Starten/Schließen Allgemeine Java-Themen 10
U JFrame, JOptionPane - vor dem Schließen Benutzer fragen Allgemeine Java-Themen 10
N Java Fenster schließen Allgemeine Java-Themen 2
G Fenster/Frame schließen Allgemeine Java-Themen 16
T CMD nach aufruf von javaw Programmname wieder schließen Allgemeine Java-Themen 3
J JFrame Problem beim schließen Allgemeine Java-Themen 2
V Button schließen - NullPointerException Allgemeine Java-Themen 6
J Chatprog schließen,AWT + Swing Allgemeine Java-Themen 4

Ähnliche Java Themen

Neue Themen


Oben