ClassLoader - dymisches Laden von JDBC Drivers

Status
Nicht offen für weitere Antworten.

chearius

Mitglied
Hallo! In meiner Java-Anwendung kann der Benutzer sich aussuchen mit welcher Datenbank er sich verbinden will. Wenn die Treiber-Klasse in ClassPath ist, läuft alles in Ordnung, die Verbindung kann problemlos hergestellt werden. Wenn die Treiber-Klasse nicht in ClassPath ist, erscheint ein Dialog, in dem eine JAR-Datei mit dem Treiber auszuwählen ist. Mittels URLClassLoader kann der JDBC-Treiber geladen werden, aber wenn ich dann Versuche eine SQL-Verbindung herzustellen, kommt ein Fehler.

Code:
URLClassLoader jcl = new URLClassLoader(new URL[] {jarFile.toURL()});
Driver d = (Driver) Class.forName(driver, true, jcl).newInstance();
DriverManager.registerDriver(d);
DriverManager.getConnection(url);
....

Es kommt folgender Fehler:
Code:
java.sql.SQLException: No suitable driver
at java.sql.DriverManager.getConnection(DriverManager.java:545)
at java.sql.DriverManager.getConnection(DriverManager.java:171)
at de.uni_karlsruhe.stud.uabqk.kim.utilities.pseudo.DatabaseUtils.initializeDBPool(DatabaseUtils.java:29)

Gibst eine Möglichkeit die JDBC-Treiber-Klassen dynamisch zu laden?

Danke für Hilfe!

Chearius
 
übergib mal den URL ClassLoader als zweiten Parameter noch den Default(Parent)-Classloader.
Zusätzlich musst du die Klasse ja auch noch laden.

Code:
URLClassLoader urlc = new URL.....
Class driverClass = urlc.loadClass(driver);

und dann noch folgendes:

Code:
Class.forName(driverClass);
Connection con = DriverManager.getConnection("url", "user", "pass");

P.S.: Du bist in Karlsruhe auf der UNI ?
 
Hallo! Danke für Deine Antwort, aber es hat leider nicht geholfen, ... - Der DriverManager sagt immer, dass er keinen Treiber finden kann :bahnhof:. Ich habe am Wochende verschiedenes versucht, bin leider nicht zum Ziel gekommen. In der GUI-Anwendung habe ich folgende funktion selectDriverJar - die wird nur dann ausgefühtr, wenn der Treiber nicht im ClassPath ist:
Code:
private void selectDriverJar() {
	File jarFile = null;
	
	JFileChooser jfc = new JFileChooser();
	jfc.setFileFilter(new JarFileFilter());
	int result = jfc.showOpenDialog(this);
	if (result == JFileChooser.APPROVE_OPTION) {
		jarFile = jfc.getSelectedFile();
	}
		
	try {
		URLClassLoader jcl = new URLClassLoader(new URL[] {jarFile.toURL()}, MainDialog.class.getClassLoader());
		jcl.loadClass(databaseDriver.getText());
		Class.forName(databaseDriver.getText(), true, jcl);
		DatabaseUtils.initializeDBPool(jcl, databaseDriver.getText(), databaseURL.getText(), 
                             databaseUser.getText(), new String(databasePassword.getPassword()));
		fetchDatabaseInfo();
	} catch (Exception ex) {
		JOptionPane.showMessageDialog(this, strings.getObject("error.dbdriver"));
		ex.printStackTrace(System.out);
		System.exit(1);
	}
}
Nach dem ich dasJAR-Archiv mit dem Treiber selektiere, kann der URLClassLoader die Treiber-Klasse (ich habe org.postgresql.Driver getestet) ohne Probleme laden. Das Problem entsteht erst in der Funktion initializeDBPool.

Die Funktion DatabaseUtils.initializeDBPool sieht so aus:
Code:
public static void initializeDBPool(ClassLoader cl, String driver, 
    String url, String user, String pwd) throws Exception {
	cl.loadClass(driver);
	Driver d = (Driver) Class.forName(driver, true, cl).newInstance();
	DriverManager.registerDriver(d);
	conn = DriverManager.getConnection(url, user, pwd);
		
//	ds = new ComboPooledDataSource();
//	ds.setDriverClass(driver);
//	ds.setJdbcUrl(url);
//	ds.setUser(user);
//	ds.setPassword(pwd);
//	ds.setMinPoolSize(1);
//	ds.setMaxPoolSize(20);
//		ds.setAcquireIncrement(5);
}

Also wie gesagt, ist der Treiber in ClassPath, dann funtioniert alles.

Sorry, dass ich mit diesem störe, aber ich kann das Problem nicht selber lösen :bahnhof:

Danke für Eure Tips!

Marek AKA Chearius

P.S. (KSG9|sebastian) Ja ich studiere an der Uni in Karlsruhe (Physik) :+)
 
ich hatte heute das gleiche problem...konnte es aber lösen (hab auch tierisch zeit verbraten)

Lösung:

Dein code:
---------------
Code:
URLClassLoader jcl = new URLClassLoader(new URL[] {jarFile.toURL()});
Driver d = (Driver) Class.forName(driver, true, jcl).newInstance();
DriverManager.registerDriver(d);
DriverManager.getConnection(url);
--------------

wenn du mit DriverManager.getConnection(url) die Verbindung aufbauen willst, dann nimmt der DriverManager nicht deinen URLClassLoader, welchem ja dein jar file bekannt ist und er die klasse schon geladen hat. Stattessen den ClassLoader System ClassLoader.
Ich hab mir einfach den DriverManager kopiert als MyDriverManager und dann allen methoden getConnection( .. ) noch als parameter ClassLoader mitgegeben. In der Methode selber nutze ich dann diesen Classloader ( In deinem Fall der URLClassLoader, denn du mit übergibst )
Einfach von DriverManager erben und methoden überschreiben geht leider nicht, da der Konstruktur privat ist.

Ich hoffe es funktioniert auch bei dir.

gruß wako
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben