Database driver-class dynamic loading

删除回忆录丶 提交于 2019-12-11 03:52:15

问题


I want to develop a DB-Agnostic application in java. I have chosen hibernate as ORM. The problem with jdbc is that , it is just an interface and we need the driver class of the db in the class path. Since the database should be configurable i have to go for loading the driver class of DB dynamically. (User should keep the driver class in a folder and it should be loaded dynamically ) Below is my code.

File driverJar = new File("E:\\Jomon\\backup_2017_05_25\\2.2\\WS\\2.2_1\\lib\\Drivers\\postgresql-42.1.1.jar");
URL[] urls = new URL[] { driverJar.toURL() };
URLClassLoader classLoader = new URLClassLoader(urls,DBUtils.class.getClassLoader());
Class.forName("org.postgresql.Driver", true, classLoader);

No error till now. But after this, while initializing hibernate connection, I am getting error java.lang.ClassNotFoundException: org.postgresql.Driver.

May I know what is the problem here.


回答1:


Finally I got the solution by myself, The problem here is , I have created a new classloader and loaded the jar into it.

The hibernate is searching for driver class in system class loader , not in the user defined class loaders.

The problem here can be solved by load the jar into system class loader as below.

File driverJar = new File("E:\\Jomon\\backup_2017_05_25\\2.2\\WS\\2.2_1\\lib\\Drivers\\postgresql-42.1.1.jar");
URL myJarFile = new URL("jar", "", "file:" + driverJar.getAbsolutePath() + "!/");
URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();

Class sysClass = URLClassLoader.class;
Method sysMethod = sysClass.getDeclaredMethod("addURL", new Class[] { URL.class });
sysMethod.setAccessible(true);
sysMethod.invoke(sysLoader, new Object[] { myJarFile });

Class.forName("org.postgresql.Driver", true, classLoader); // Now no error in this line.



回答2:


Hibernate will always to attempt the load the driver from the current thread classloader and in your case, it doesn't have the driver.

You own class loader works fine and just before you initialize sessionFactory ,set your custom loader into contextClassLoader like this.

    File f = new File( "E:\\Jomon\\backup_2017_05_25\\2.2\\WS\\2.2_1\\lib\\Drivers\\postgresql-42.1.1.jar" );
    URLClassLoader urlCl = new URLClassLoader( new URL[] { f.toURL() }, System.class.getClassLoader() );
    Class postGreDriver = urlCl.loadClass( "org.postgresql.Driver" );
    System.out.println( postGreDriver.newInstance() );

    Thread.currentThread().setContextClassLoader(postGreDriver);

    //Hibernate can start

    //you should restore your old classloader when hibernate services end

This may not be the best solution. Have got this snippet from this discussion

Hope this helps!!!



来源:https://stackoverflow.com/questions/44346826/database-driver-class-dynamic-loading

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!