Dynamisches Laden eines JDBC-Treibers und Verwendung mit Hibernate

MS-Tech

Erfahrenes Mitglied
Hallo Zusammen,

da ich nun die Datenbanktreiber für meine Anwendung nicht mehr direkt mitliefern möchte muss ich diese nun irgendwie nachladen. Es gibt eine Properties, in der sich die Treiberklasse und auch die Bezeichnung des Jar-Files befinden. Ein Benutzer kann nun seinen Datenbanktreiber in das Lib-Verzeichnis packen und die Properties anpassen. Nun muss eben der Treiber dynamisch geladen und dann Hibernate zur Verfügung gestellt werden.

Ich hab hier mal einen Codeabschnitt gefunden:

Code:
URL u = new URL("jar:file:/" + jarPath + "!/");
String classname = DatabaseProperties.getProperties().get("db.driver").toString();
URLClassLoader ucl = new URLClassLoader(new URL[] { u });
Driver d = (Driver) Class.forName(classname, true, ucl).newInstance();
DriverManager.registerDriver(new JDBCDriverWrapper(d));

Dies scheint schon mal zu funktionieren, nur wenn ich mir dann die Hibernate-Configuration zusammenbauen möchte, so erhalte ich plötzlich Exceptions, dass diese Klassen bzw. Treiber nicht gefunden werden können.

Bisher habe ich die DB-Treiber immer in den Classpath meiner Anwendung gelegt, also alle mitgeliefert, und dann über

Code:
config.setProperty("hibernate.connection.driver_class", "xyp");

eingebunden. Das scheint aber jetzt nicht mehr zu funktionieren.

Hat jemand eine Idee, wie ich so etwas bewerkstelligen kann?

Viele Grüße
Sascha
 
Hallo Sascha,

es wäre hilfreich, wenn du jetzt noch schreibst warum es sich erledigt hat und was die Lösung war.

Gruß
 
Hi,

gerne.

Also ich hab nun alle Datenbanktreiber aus dem Classpath meiner Anwendung geworfen. Damit ich die Treiber einbinden kann, gibt es db.properties. Darin sind 2 Properties angegeben, nämlich der Name der JAR-Datei und die Treiberklasse. Diese Properties werden nun beim Systemstart geladen, die Jar-Datei über eine Suchfunktion, innerhalb des Anwendungspfades, gesucht und über eine Methode, die ich hier gefunden habe

Code:
	public void addJarsToClassPath(ClassLoader classLoader, File[] jars) throws Exception {
		
		if (classLoader instanceof URLClassLoader) {
			
			try {
				Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
				addUrlMethod.setAccessible(true);
				
				if (null != addUrlMethod) {
					
					for (File jar : jars) {
						
						try {
							addUrlMethod.invoke(classLoader, jar.toURI().toURL());
						} catch (Exception e) {
							throw e;
						}
					}
				}
			} catch (Exception e) {
				throw e;
			}
		}	
	}

eingebunden. Die Treiberklasse benötige ich, für die Hibernate-Konfiguration. Ich kann nun verschiedene Datenbanken anbinden, es muss nur der Treiber irgendwo im Anwendungsverzeichnis oder in Verzeichnissen darunter vorhanden sein, es müssen die richtigen Properties in der db.properties stehen. Damit das gewährleistet ist, werden Exceptions geworfen, falls ich die JAR nicht finden kann oder die Treiberklasse nicht geladen werden konnte etc.

Ich beantworte gern weitere Fragen, sollten noch welche auftauchen.

Viele Grüße
Sascha
 
Also ich hätte da schon noch Fragen ... ;-)
Wie gibst du Hibernate den Hibernate-Dialekt mit? Das müsste ja nicht im JAR stehen.

Und wie gibst du den korrekten Connection-String mit? Du musst ja wissen ob es nun "jdbc:eek:racle:thin" oder "jdbc:jtds:sqlserver" usw. ist?

Gruss,
slowy
 
Hi,

ganz einfach. Ich hab mir ein Enum definiert, dass die entsprechenden Werte enthält, also z.B.

Code:
public enum DB {
   DB1("DB1Dialect", "DB1ConnectionString"),
   DB2("DB2Dialect", "DB2ConnectionString");       

   // the db dialect
   private String dialect;

   // the connectionstring
   private String conString;

   /**
    * creates new enum dB
    * @param dialect the dialect
    * @param conString the connectionString
    */
   public DB (String dialect, String conString) {
      dialect = dialect;
      conString = conString;
   }

   /**
    * return´s the connectionstring
    */
   public String getConnectionString() {
      return conString;
   }

   /**
    * return´s the dialect
    */
   public String getDialect() {
      return dialect;
   }
}

In diesem Enum gibt es verschieden Methoden, wie z.B. getConnectionString(), getDialect()...etc. Diese Methoden geben mir eben die Daten aus dem Enum zurück.

Dies kann ich undendlich ausbauen und kann so auf einfache Art und Weise neue Datenbanken hinzufügen.

Das alles speichere ich in einer Konfigurationsstruktur, also einer Config-Klasse, in der auch noch andere Konfigurationen gepsichert werden.

z.B.

Code:
public class ApplicationConfig() {

   /**
    * store the databse configuration
    */
   private DB dbConfig = null;

   /**
    * default constructor
    */
   public ApplicationConfig() {
      // empty Constructor
   }

   /**
    * return´s the dbConfig
    */
   public getDbConfig() {
      return dbConfig;
   }

   /**
    * set the dbConfig
    */
   public setDbConfig(DB dbConfig) {
      this.dbConfig = cbConfig;
   }
}

Wenn ich dann die Hibernate-Configuration aufbaue, dann nuss ich ja nur ApplicationConfig.getDb().getConnectionString() oder ApplicationConfig.getDb().getDialect() aufrufen. Das war´s.

Ach ja....ich arbeite nicht mit der XML-Konfiguration in Hibernate, sondern mach das alles per JAVA-Code.

Noch Fragen :)?

Grüße
Sascha
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück