DB Connection schliessen

Status
Nicht offen für weitere Antworten.

bambi

Bekanntes Mitglied
Hi,

Also ich haeng' hier seit einiger Zeit an einem Problem. Wir haben hier eine Application, die ab und zu mal ein paar
FinderExceptions wirft. Der Grund dafuer ist wohl, dass einfach zu viele DB-Verbindungen offen sind. Leider tritt der Fehler
nicht immer auf und ist auch nicht reproduzierbar.

Und nun ein paar Fragen (vielleicht ein bissl' daemlich, aber ich bin echt am Verzweifeln :? )

1. Kann es sein, dass eine finder()-Methode eine DB-Verbindung aufbaut und nicht wieder schliesst? Nein, oder?
2. Wie lange dauert es bis eine Verbindung geschlossen ist? Kann man das irgendwie sagen?
3. Gibt's noch eine andere Moeglichkeit, dass eine DB-Verbindung geoeffnet wird und offen bleibt?
(Ausser wenn man die Connection, ResultSet und Statement erzeugt und nicht wieder schliesst.)

Also ihr sehr schon - bin verzweifelt. Bitte, bitte helfen...

Danke schon mal...
 
G

Guest

Gast
Ich nehme an, Dir geht es um BMP. Normalerweise verwendet man hierzu DataSource
mit einem ConnectionPool.

Die Connections, Resultsets, PreparedStatements etc. sollten wieder freigegeben
werden, wenn kein wichtiger Grund dafür besteht, sie offen zu halten.
Eine Typische Finder-Methode (bei BMP) könnte den folgenden Aufbau haben
Code:
public Collection findAllByName(String name) throws SQLException {
  Connection con = null;
  PreparedStatement ps = null;
  ResultSet res = null;

  try {
    con = Locator.getConnection(); // Connection Objekt holen
    ps = con.prepareStatement("SELECT ....");
    ps.setString(1, name);
    res = ps.executeQuery();
    Collection result = createList(100);  // Anfangsgröße = Erfahrungswert; wiederverwenden, wenn möglich
    while(res.next()) {
      result.add(createPK(res)); // PK aus aktueller Zeile
    }
    return result;
  }
  catch(SQLException e) {
    logger.error(e);
    throw e;
  }
  catch (NamingException e) {
    logger.fatal(e);
    throw new SQLException(e);
  }
  finally {
    try { if(res != null) res.close(); } catch(Exception e) { logger.error(e); }
    try { if(ps != null)  ps.close();  } catch(Exception e) { logger.error(e); }
    try { if(con != null) con.close(); } catch(Exception e) { logger.error(e); }
  }
}
Man kann es auch verallgemeinern, so dass man nur die Query und die Parameter
an eine allgemeine Methode übergibt und Collection mit PK-Objekten kriegt.
z.B.
Code:
public Collection findAllByName(String name) throws SQLException {
  return execListFinderQuery(
    "SELECT ...",
    new Object[] { name }
  );
}
wobei execListFinderQuery eine verallgemeinerte Abfrage ist (wie oben im Beispiel)

Der Locator, dann wie folgt
Code:
public class Locator {

  private static DataSource dataSource = null;

  public static Connection getConnection() throws NamingException {
    if(dataSource == null) {
      InitialContext ctx = new InitialContext();
      dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/WhateverDS");
      ctx.close();
    }
    return dataSource.getConnection();
  }

}

Connection.close() bewirkt, dass das Connection-Objekt in den ConnectionPool
freigegeben wird.
Ich habe damit noch nie Probleme gehabt und es ist schnell genug (bei JBoss 3.x).

Ich hoffe, dies beantwortet Deine Fragen.
 

Bleiglanz

Gesperrter Benutzer
Und nun ein paar Fragen (vielleicht ein bissl' daemlich, aber ich bin echt am Verzweifeln
dämlich ist vor allem, dass du nicht schreibst welcher Appserver und welche DB und wann wo und wie der finder benutzt wird

-> datenbank profiler anschmeissen und schauen, welche conns da sind

-> doku zum Appserver lesen wie man einen Connection pool configuriert

usw.
Gibt's noch eine andere Moeglichkeit, dass eine DB-Verbindung geoeffnet wird und offen bleibt?
leider genügend

Code:
...gefaehrlicheMethode();
...conn.close();
  }
  catch(SQLException e){}
}

sowas machen natürlich nur ganz schlechte progger, die Exception wegwerfen und das close nicht im finally-block...

wenn du solchen code hast und die Ex nur ganz selten fliegt, dann gehen dir irgendwann die Connections aus (bedingt durch das Pooling merkt man von aussen überhaupt nicht, dass da irgendwo eine geöffnete Connection rumliegt)
 

Bleiglanz

Gesperrter Benutzer
@Gast

Wenn du mal öfters hier reinschaust wirst du auch irgendwann staunend feststellen, dass sehr viele Fragesteller nichteinmal in der Lage sind, ihr Problem einigermassen genau zu beschreiben :)

Manche wollen wohl keine supergeheimen GeheimBetriebsgeheimnisse verraten
und stellen dann Fragen wie

"Mich juckts irgendwo, wo könnte das sein?"
 

bambi

Bekanntes Mitglied
Bleiglanz hat gesagt.:
dämlich ist vor allem, dass du nicht schreibst welcher Appserver und welche DB und wann wo und wie der finder benutzt wird
Na danke! Sorry, hab' ich in meiner Verzweiflung ganz vergessen - wenn Dir der Chef am Hintern klebt und dauernd fragt,
wann Du den Fehler (den irgendwer anderer in der x-1000 Zeilen Application fabriziert hat) gefunden hast, dann kann das
ja wohl mal passieren...

Also Server: WebLogic (Version muesst ich jetzt nachsehen :oops: )
DB Oracle 9.irgendwas

Also die Finder werden ganz normal in den CMPs im Doc definiert also im /** ... */. Da duerfte ja nix schiefgehen - mit
offenen Connections, etc...

Also in dem Code, den ich bis jetzt gecheckt habe, wurden alle Connections, Statements und ResultSets immer brav
mit
Code:
try {
...
} catch (SQLException se) {
... 
} finally {
   if (connection != null)
      connection.close();
   if (resultSet!= null)
      resultSet.close();
   if (statement!= null)
      statement.close();
...
}
geschlossen.
 
G

Guest

Gast
bambi hat gesagt.:
Also Server: WebLogic (Version muesst ich jetzt nachsehen :oops: )
DB Oracle 9.irgendwas

Also die Finder werden ganz normal in den CMPs im Doc definiert also im /** ... */. Da duerfte ja nix schiefgehen - mit
offenen Connections, etc...
Sorry, mit WebLogic habe ich noch nie gearbeitet, kenne die ganzen Konfigurationsmöglichkeiten bei dem Server nicht.
CMPs im Doc definiert also im /** ... */ klingt nach XDoclet. Schwierig zu sagen, was falsch ist, ohne den Code zu sehen. Ich vermute aber, dass es ein reiner Konfigurationsfehler sein wird.

bambi hat gesagt.:
Also in dem Code, den ich bis jetzt gecheckt habe, wurden alle Connections, Statements und ResultSets immer brav
mit
Code:
try {
...
} catch (SQLException se) {
... 
} finally {
   if (connection != null)
      connection.close();
   if (resultSet!= null)
      resultSet.close();
   if (statement!= null)
      statement.close();
...
}
geschlossen.
Das ist jetzt aber garantiert kein CMP. Bei CMP hast Du mit JDBC so gut wie gar nichts mehr zu tun.

Was Du machen könntest, ist die Datenbank zu beobachten, ob alle Cursor auch freigegeben werden, wieviele Connections werden geöffnet etc. Langsam die Fehlerquelle einkreisen.
 

Bleiglanz

Gesperrter Benutzer
das ist die falsche Reihenfolge, und oben - im try blocl - muss natürlich nach dem close "genullt" werden!!!

erst resultset, dann statement, dann connection

(sonst fliegt ja beim resultset.close eine ex, weil sie schon zu ist ... und weils diese nicht abgefangen wird, wird u.U. die ganze Transaktion zurückgesetzt - aber eigentlich sollte bei conn.close die schon richtig in den Pool zurückgelegt werden!)


Wenn ihr nur CMP verwendet, dann sollte das Prob eigentlich nicht auftauchen...

Fehler liegt bestimmt bei händischer Programmierung einer SQL Abfrage und hat NICHTS mit dem Finder zu tun...

=> Datenbank profilen, oder mit Weblogic mal den "Monitoring" Tab in der Admin Console auswählen, "Monitor all Transactions by REssource" und die Datasource anzeigen lassen

möglicherweise ist aber auch der verwendete Pool tatsächlich zu klein (zu viele gleichzeitige user?) => was ist initial Capacity, maximum capacity etc.
 

semi

Top Contributor
Noch eine Möglichkeit können Table- oder Row-Locks in den Tabellen sein.
IsolationLevel bzw. Transaktionsverhalten allgemein.
Wie ich schon schrieb, gucken, was der Server treibt.
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen


Oben