我需要测试与数据库的JDBC连接。执行此操作的Java代码应该如下所示:
DriverManager.getConnection("jdbc connection URL", "username", "password");
驱动程序管理器将查找给定连接URL的相应驱动程序。但是我需要能够在运行时加载JDBC驱动程序(jar)。即我在运行上述代码片段的java应用程序的类路径中没有JDBC驱动程序。
所以我可以使用此代码加载驱动程序,例如:
URLClassLoader classLoader = new URLClassLoader(new URL[]{"jar URL"}, this.getClass().getClassLoader());
Driver driver = (Driver) Class.forName("jdbc driver class name", true, classLoader).newInstance();
但是后来驱动程序管理器仍然不会接受它,因为我无法告诉它使用哪个类加载器。我尝试设置当前线程的上下文类加载器,但它仍然不起作用。
任何人都对实现这一目标的最佳方法有任何想法?
答案 0 :(得分:18)
来自文章Pick your JDBC driver at runtime;我将在这里发布代码以供参考。
这个想法是欺骗驱动程序管理器认为驱动程序是从系统类加载器加载的。为此,我们使用这个类:
public class DelegatingDriver implements Driver
{
private final Driver driver;
public DelegatingDriver(Driver driver)
{
if (driver == null)
{
throw new IllegalArgumentException("Driver must not be null.");
}
this.driver = driver;
}
public Connection connect(String url, Properties info) throws SQLException
{
return driver.connect(url, info);
}
public boolean acceptsURL(String url) throws SQLException
{
return driver.acceptsURL(url);
}
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
{
return driver.getPropertyInfo(url, info);
}
public int getMajorVersion()
{
return driver.getMajorVersion();
}
public int getMinorVersion()
{
return driver.getMinorVersion();
}
public boolean jdbcCompliant()
{
return driver.jdbcCompliant();
}
}
这样,您注册的驱动程序是DelegatingDriver
类型,它加载了系统类加载器。您现在只需要使用您想要的任何类加载器加载您真正想要使用的驱动程序。例如:
URLClassLoader classLoader = new URLClassLoader(new URL[]{"path to my jdbc driver jar"}, this.getClass().getClassLoader());
Driver driver = (Driver) Class.forName("org.postgresql.Driver", true, classLoader).newInstance();
DriverManager.registerDriver(new DelegatingDriver(driver)); // register using the Delegating Driver
DriverManager.getDriver("jdbc:postgresql://host/db"); // checks that the driver is found
答案 1 :(得分:5)
问题是DriverManager
使用直接调用者的类加载器实例执行“任务”。见Secure Coding Guidelines for the
Java Programming Language, version 2.0的准则6-3。在这种情况下,系统类加载器并不特别。
只是为了踢,我不久前写了一篇关于这个主题的blog entry。我的解决方案虽然比Nick Sayer's solution更复杂,但更完整,甚至可以使用不受信任的代码。另请注意,URLClassLoader.newInstance
优先于new URLClassLoader
。