Zauważ, że wywołujesz .getConnection()
wiele razy. Chociaż dokumentacja mogłaby być bardziej przejrzysta na tym froncie DataSource.getConnection()
faktycznie otwiera się nowe połączenie (w przeciwieństwie do zwracania istniejącego), dlatego musisz zamknąć każdą instancję zwróconą tą metodą.
Jako .getConnection()
tworzy nową instancję za każdym razem, gdy jest wywoływana, ta linia jest wyciekiem połączenia, ponieważ nie zamyka zwracanego połączenia:
pstmt = dataSource.getConnection().prepareStatement(query);
A ta linia marnotrawnie otwiera nowe połączenie tylko po to, by je natychmiast zamknąć:
dataSource.getConnection().close();
Wygląda na to, że próbujesz otworzyć i zamknąć oddzielne połączenie dla każdego wywołania isValidUser()
(ponieważ zamykasz połączenie na końcu wywołania tej metody). Nawet jeśli naprawisz opisany powyżej wyciek, nie jest to sposób, w jaki należy używać połączeń. Zamiast tego należy udostępnić jedno połączenie (lub niewielką ich liczbę) w całej aplikacji. Więc kiedy twój program się uruchamia, otwierasz takie połączenie, a raz cały program nie potrzebuje już połączenia (często na krótko przed zakończeniem), zamykasz je.
Ten rodzaj zachowania jest często implementowany przez wstrzykiwanie zależności , gdzie konstruujesz połączenia i inne zasoby, a następnie przekazujesz je do dowolnych obiektów, które ich potrzebują — oddziela to zarządzanie zasobami od kodu, który korzysta z tych zasobów. Jako uproszczony przykład:
public static void main(String[] args) {
DataSource dataSource = createDataSource();
try (Connection connection = dataSource.getConnection()) {
runProgram(connection);
}
}
/**
* this method doesn't need to worry about closing the Connection,
* it trusts that its caller will be responsible for that.
*/
private static void runProgram(Connection connection) {
// ...
}
Zgodnie z ogólną zasadą, obiekty powinny być odpowiedzialne tylko za zamykanie obiektów, które konstruują, i powinny unikać zamykania obiektów, które przekazują. W bieżącym kodzie UserDaoImpl
otwiera połączenie, więc powinien być odpowiedzialny za jego zamknięcie, ale proponuję przekazać w Connection
zamiast tego.