Laden eines JDBC Treiber.

Status
Nicht offen für weitere Antworten.

BlackReloaded

Aktives Mitglied
Hi,

ich habe ein hoffentlich kleines Problem mit meinem Prgoramm und zwar versuche ich einen Datenbank Treiber von Apachen ( Derby ) über einen Classloader zu laden.

Der Classloader selber funktioniert auch bestens:

Code:
static Object newInstance( String path, String classname ) throws Exception
	  {
	    URL url = new File( getLocation() + path ).toURI().toURL();

	    URLClassLoader cl = new URLClassLoader( new URL[]{ url } );

	    Class<?> c = cl.loadClass( classname );

	    return  c.newInstance();
	  }

Ich muss den Treiber über einen Classloader laden, da er nicht im CLASSPATH vorhanden ist.
Die Funktion getLocation() gibt den Absolutenppfad zum Prgorammverzeichnis.
Nun zum Problem:

Code:
Object a = KlassenLader.newInstance("Treiber/derby.jar", "org.apache.derby.jdbc.EmbeddedDriver");

// Wenn der Treiber in dem CLASSPATH liegen würde, läd man so den Treiber
// dies funktioniert auch.
//Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();

//Verbindung zur Datenbank aufbauen
connection = DriverManager.getConnection("jdbc:derby:database/system_dbs;create=true;");

Bei dem Verbindungsaufbau bekomme ich eine SQLException die mir sagt, dass der Treiber nicht geladen ist.

Kann mir vielleicht jemand helfen wo mein Fehler oder denk Fehler ist?

Ich wäre für jede Hilfe dankbar...

MFG

Marc Kohlbau

PS: Wenn ich den Klassloader an anderer Stelle nutze funktioniert auch alles wunderbar.
Hier noch ein Beispiel:
Code:
Object Look = KlassenLader.newInstance("Treiber/synthetica.jar", "de.javasoft.plaf.synthetica.SyntheticaStandardLookAndFeel");
UIManager.setLookAndFeel((LookAndFeel) Look);
 
Mal abgesehen davon, daß das Laden eines DB-Treibers von externen Quellen zur Laufzeit recht ungewöhnlich ist, dürfte die Lösung des Rätsels hierin bestehen:

http://java.sun.com/j2se/1.5.0/docs/api/java/sql/DriverManager.html

When the method getConnection is called, the DriverManager will attempt to locate a suitable driver from amongst those loaded at initialization and those loaded explicitly using the same classloader as the current applet or application.
 
Anonymous hat gesagt.:
Mal abgesehen davon, daß das Laden eines DB-Treibers von externen Quellen zur Laufzeit recht ungewöhnlich ist,(...)

Wieso ist das so ungewöhnlich? Dieser "Treiber" ist ja die komplette Datenbank und ich brauche sie in 3 Jar Archiven die ich ausliefere, wenn die den "Treiber" in jedem Archiv packen würde wäre das Projekt knapp 6 MB größer und das wollte ich mir/den Usern ersparen.

Vielen dank für die Hilfe, hatte auch in der Doku geguckt aber den satzt total überlesen :cry:

Jetzt ist nur die Frage wie man es hinbekommt, wenn nicht der gleiche Classloader genutzt wird.

Ich habe es so versucht, aber leider kein vortschritt:

Code:
DriverManager.registerDriver( (Driver) a);

Diese Zeile läuft auch ohne Exception, nur der Treiber ist trotzdem nicht vorhanden?

MFG
Marc Kohlbau
 
Da bisher niemand anderes geantwortet hat, antworte ich nochmal, obwohl ich mich auf dünem Eis bewege.
Du sagst, daß du die "komplette" DB in dem Jar auslieferst, also Treiber + Daten?

Das ist in der Tat ungewöhlich, da der Treiber eigentlich lokal vorliegt und die Datenbank zentral für die Clients bereitsteht. Vielleicht verstehe ich nicht so ganz was du vor hast oder damit bezecken willst.

Der Client muß den Treiber doch letztendlich sowieso "laden" ob jetzt mit der Installation oder bei jedem Start der Anwendung. ???:L

Zu der Classloader-Problematik kann ich auch nicht viel mehr zu sagen, außer daß der DriverManager eigentlich veraltet ist und man heutzutage DataSources benutzt. Diese bieten eventuell die Möglichkeit einen Treiber dynamisch zu landen aber das ist nur eine Vermutung.
 
Hi,
danke für die Antwort soweit.

Jedoch verstehe ich nicht, was daran ungewöhnlich sein soll? Mal ein paar zusatz infos:
Ich programmiere eine Buchhaltunssoftware für zu Hause.
Da ich nicht davon ausgehen kann, dass jeder User einen Server mit einem Datenbanksystem vorrätig hat und
ich nicht den User zumuten/vertraue einen Localen Server zu installieren, habe ich mich entschlossen
die Datenbank von Apache zu nutzen, diese heißt Derby.
Derby bringt den Vorteil mit, dass die komplette DB in Java geschrieben ist.

Diese Software ( Jarfile ) kann man entweder Local nutzen in dem man aus der Kompletten Jarfile, den oben genannten
Treiber Läd ( Der dann, so denke ich, die Datenbank Localstartet ), oder man Läd den Netzwerktreiber
(Weiß ich gerade nicht auswendig wie der heißt ).
Jedoch ist das alles eine geschlossene Jar-Datei ( knapp 4 MB groß), diese muss ich ja jetzt in meine Jar-Datei integrieren... und genau das wollte ich vermeiden, das ich sie 3 mal ausliefere.

MFG
Marc Kohlbau
 
Der DriverManager vergleicht den ClassLoader des Aufrufers mit dem des Drivers, deswegen klappt auch DriverManager.registerDriver() nicht.

Du brauchst den DriverManager meiner Meinung nach aber nicht wirklich.
Code:
Driver driver = (Driver) KlassenLader.newInstance("Treiber/derby.jar", "org.apache.derby.jdbc.EmbeddedDriver"); 
connection = driver.connect("jdbc:derby:database/system_dbs;create=true;", new Properties());
 
Hallo Marc und alle übrigen,

ich suche auch gerade nach einer Lösung, einen JDBC-Treiber zur Programm-Laufzeit zu laden - insofern klingt das mit dem Klassenlader interessant...

Mein Programm arbeitet momentan noch mit Class.forName(). Läuft alles soweit ganz gut, wenn ich den Treiber (testweise momentan mySQL) im JAR mit ausliefere - das gefällt mir aber eigentlich nicht. Ich würde die Anwendung lieber unabhängig von einer konkreten Datenbank gestalten - wer eine Oracle-DB hat, nimmt dann halt den Oracle-Treiber, usw. Das Anwendungsprogramm kriegt dann einen Dialog zum Einstellen des Treibers und der URL, User und Passwort etc. Ungewöhnlich finde ich das auch nicht - habe bisher hauptsächlich Delphi-Programme geschrieben und die DB-Anbindung dann über ODBC eingerichtet. Die ODBC-DSN richtet dann der Kunde mit dem passenden DB-Treiber ein, das Anwendungsprogramm benutzt die ODBC-DSN. Hmm - und jetzt in Java? (Über die ODBC-JDBC-Schiene will ich nicht gehen, das klingt umständlich).

Lange Rede, kurze Frage: Funktioniert der zuletzt gepostete Code?
Oder gibt es für die beschriebene Anwendung einen besseren (üblicheren) Weg in Java?

Danke schonmal,
Sabine.
 
Hat sich erledigt, funktioniert jetzt bei mir über den Klassenlade (Code wie oben).
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben