2013-01-14 11 views
10

Mamy żądania obsługi serwera WWW od klientów. Jeden składnik tego serwera sieci Web zawiera połączenie z bazą danych.Czy istnieje bezpieczny sposób na stwierdzenie, czy połączenie JDBC jest nadal w porządku?

Muszę być w stanie rozpoznać, czy połączenie zostało zamknięte lub w jakiś sposób nie funkcjonuje, zanim zacznę go używać. Obecnie robię coś takiego:

// Decide connection details on alias. 
private String alias = null; 
// I must have my own because I prepare statements. 
private Connection connection = null; 

public Connection getConnection() { 
    try { 
    if (connection.isClosed()) { 
     // Start afresh. 
     connection = null; 
    } 
    // ** More tests here to check connection is ok. 
    if (connection == null) { 
     // Make a new connection. 
     connection = Connections.getConnection(alias); 
    } 
    } catch (SQLException ex) { 
    // Cause a NPE further down the line. 
    connection = null; 
    } 
    return connection; 
} 

Niestety czasami zwraca takie nieaktualne połączenie, że dostaję jeden z różnych błędów. Jednym z takich wygląda następująco:

java.sql.SQLException: Io wyjątek: Oprogramowanie spowodowało przerwanie połączenia: błąd zapisu gniazda

Należy pamiętać, że jest to tylko jeden z błędów rejestrowanych i ten dzieje się po około 72 godziny bezczynności.

To, czego szukam, to minimalny tester połączenia z bazą danych, który powinien konsekwentnie określać, czy połączenie działa, działa i jest stabilne. czy to możliwe?

Nie mam nic przeciwko uruchomieniu bardzo niewielkiej kwerendy przeciwko niemu, ale musi to być zarówno agnostyka bazy danych, jak i nie zabierać zbyt mało czasu/zasobów.

BTW: Używam Java 5, więc Connection.isValid nie jest rozwiązaniem dla mnie.


Dodany

Dla tych z Was, odwiedzając tę ​​kwestię później - w końcu wziął zaproponowane rozwiązania i przeniosła się do prawdziwego puli połączeń i nie tylko było to zadziwiająco łatwe do zrobienia, ale wszystko z moje problemy zniknęły.

Jedyną dziwną częścią było uświadomienie sobie, że z pulą połączeń po zakończeniu połączenia musisz uzyskać close - basen przechwytuje zamknięcie i zwraca go do puli za kulisami.

+1

Co masz przeciwko gotowym pulom połączeń, które sprawdzają połączenia w trybie rutynowym? –

+0

@MarkoTopolnik - nic - jako takie - ale przygotowałem oświadczenia dołączone do tych połączeń, więc muszę sam je obsłużyć. A może ja? – OldCurmudgeon

+1

W rzeczywistości jest to problem, który te pule również obsługują, z przygotowanymi pulami instrukcji. BTW moim wyborem byłby * boneCP *. –

Odpowiedz

11

Najlepszym sposobem jest wykonanie prostej instrukcji SQL, takiej jak SELECT 1 lub SELECT 1 FROM DUAL dla Oracle. (Proszę zapoznać się z bazą danych dotyczącą składni specyficznej dla dostawcy.)

Jeśli się nie powiedzie, odśwież połączenie. To właśnie robią serwery aplikacji Java EE, takie jak WebLogic, aby je przetestować, jeśli je skonfigurujesz.

+0

Myślę, że byłoby wskazane, jeśli podświetlisz fakt (który wydaje się nieco implikowany w twojej odpowiedzi), że niektóre serwery aplikacji wykonują już tę kontrolę automatycznie (jeśli je skonfigurujesz). Przykładem może być WebSphere. – Isaac

+0

Gotowe - dziękuję. – duffymo

+0

Czy "WYBIERZ 1" działa przeciwko wszystkim bazom danych? – OldCurmudgeon

8

Spróbuj

java.sql.Connection.isValid(int timeout) 

Zwraca TRUE jeśli połączenie nie zostało zamknięte i jest nadal ważny.

+0

Przepraszam - powinienem był wypróbować, że pracuję pod Javą 5. – OldCurmudgeon

+0

Po dodaniu trochę informacji, według mojej wiedzy, metoda 'java.sql.Connection.isValid (int timeout)' wywołuje 'SELECT 1' – JackB

4

Każda baza danych ma zapytanie, które nie zależy od istniejących tabel.Dla Oracle, spróbuj

select 1 from dual 

dla wielu innych baz danych (MySQL, H2), spróbuj

select 1 

DB2 ma swój własny, unikalny składni:

values 1 
+0

" wartości 1 "? To nie jest żaden SQL, który rozpoznaję ... – duffymo

+1

DB2 używa tej składni do tworzenia tabel ad-hoc z listy wartości. Wyszukaj w dokumentacji instrukcję 'VALUES statement'. –

+0

Dzięki, ale nie używam DB2 (dzięki Bogu). – duffymo

0

Im moim przypadku używam java .sql.Connection.isValid (int timeout):

Mam metodę getConnection (lub getInstance no poll w tym przykładzie):

try { 
    if (connect == null) || ! connect.isValid()) { 
     connect.DriverManager.getConnection(...); 
} catch (SQLException e) { 
    logger.error(...); 
    connect = null; 
} 
return connect; 
+0

Z pewnością warto mieć to rozwiązanie jako opcję, ale pamiętaj, że 'isValid' jest dostępny tylko w Javie 1.6. Ogólnie - moja rada byłaby * przejściem do puli połączeń *. – OldCurmudgeon

Powiązane problemy