Jak poprawnie napisać monitor połączeń JDBC w aplikacji wielowątkowej?

0

Witam, mam problem z napisaniem poprawnego monitora połączeń JDBC.

Aplikacja o której mowa będzie się łączyć z jedną z 2-óch baz danych. Jest to tak naprawdę identyczna baza w trybie redundancji.

W aplikacji wpisujemy dane do połączenia dla obu baz, w momencie uruchomienia aplikacja sprawdza czy może nawiązać połączenie z bazą 1
lub w przypadku niepowodzenia z bazą 2.

Pseudokod:

// Wątek do testowania połączenia z bazą danych
  while(run) {
			switch (Constants.type) {
			case 0: // stan przy uruchomieniu aplikacji (brak wybranej domyslnej bazy danych)
				Constants.setDefaultDB(1);
				break;
			case 1:
				
				if (!Constants.connectionTested) {
					Constants.setDefaultDB(2);
				}
				break;
			case 2:
				
				if (!Constants.connectionTested) {
					Constants.setDefaultDB(1);
				}
				break;
			}
                }

W oknie aplikacji jest kontrolka mówiąca o stanie połączenia z bazą danych.

W chwili obecnej sprawdzam to tak:

class ConnectionTestClass extends Thread {

	static Logger log = Logger.getLogger(ConnectionTestClass.class);
	
	private volatile Connection conn = null;
	private volatile String url;
	
	public ConnectionTestClass(String url) {
		this.url = url;
	}
	
	@Override
	public void run() {
		try {
			this.conn = DriverManager.getConnection(url);
		} catch (SQLException e) {
//			log.error("Blad polaczenia z baza");
//			log.error(e);
//			e.printStackTrace();
		}
	}

	static synchronized public Connection getConnection(String url) {
		ConnectionTestClass d = new ConnectionTestClass(url);
		d.start();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return d.conn;
	}
}

Jeśli Connection == null --> brak połączenia, zmień bazę.

Szukałem w internecie i nie znalazłem konkretnej odpowiedzi, obecnie przy wyłączeniu aplikacji wątki nie killują się poprawnie i aplikacja się nie wyłącza, pomaga tylko kill procesu java.

Pytanie: jak napisać poprawne sprawdzanie połączenia z bazą?
Być może istnieją już jakieś biblioteki, albo gotowe rozwiązania.

2

Pytanie dlaczego robisz to synchronicznie?

class DbCheck extends TimerTask {

    private Connection c;

    DbCheck(Connection c) {
        this.c = c;
    }

    @Override
    public void run() {
        try{
            c.createStatement().execute("Select 0 from DUAL"); // Oracle w innych bazach inaczej
        }catch (SQLException sqle){
            InformationService.push(sqle);
        }
    }
}

InformationService jest klasą obsługującą zdarzenia/GUI/ cokolwiek gdzie publikujesz informację o nieudanym połączeniu.

Potem w kodzie:

Timer t = new Timer();
t.schedule(new DbCheck(c1), new Date(), 1000);
t.schedule(new DbCheck(c2), new Date(), 1000);

I co sekundę samo sprawdza czy się kręciła kręci.

0
Koziołek napisał(a):

Pytanie dlaczego robisz to synchronicznie?

Nie chcę zakładać nowego tematu, dlatego podepnę się jeszcze pod ten.
Zastanawiam się jak napisać poprawne testowanie połączenia? Obecnie robię to w ten sposób, że korzystając z Twojego rozwiązania staram się nawiązać połączenie z Bazą danych i sprawdzam otrzymane połączenie (if != null) pisząc prostego selekta do bazy. Jednakże, czas nawiązywania połączenia jest uzależniony od DBMS i mimo iż w TimerTasku mam ustawiony czas np. 2 sekundy to samo nawiązywanie może trwać nawet 60 sekund, to jest za dużo jak na monitor połączeń. Czy dobrym rozwiązaniem było by użycie np. C3PO do tworzenia puli połączeń, a potem tylko pobierać z puli połączenie i robić tego selekta?

0

Pula będzie bardzo OK. Szczególnie w przypadku gdy czas potrzebny na nawiąznanie połączenia jest bardzo długi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1