我们平时在连接数据库时需要加载驱动,通常做法是将JDBC驱动程序放在类路径中的某个位置,然后用Class.forName()查找并加载驱动程序。
这也就意味着要么将驱动程序打包到jar中,要么将驱动程序粘贴到某个地方(可能也将其解包),要么修改类路径。
但是为什么不使用URLClassLoader和class.forName()的重载来指定类加载器呢?因为DriverManager将拒绝使用一个不能未被系统类加载器加载的驱动。
解决方法是创建一个实现java.sql.Driver的实现类。这个实现类只调用动态加载的JDBC驱动程序实例的方法。像这样的:
import java.sql.*;
class DriverShim implements Driver {
private Driver driver;
DriverShim(Driver d) {
this.driver = d;
}
public boolean acceptsURL(String u) throws SQLException {
return this.driver.acceptsURL(u);
}
public Connection connect(String u, Properties p) throws SQLException {
return this.driver.connect(u, p);
}
public int getMajorVersion() {
return this.driver.getMajorVersion();
}
public int getMinorVersion() {
return this.driver.getMinorVersion();
}
public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {
return this.driver.getPropertyInfo(u, p);
}
public boolean jdbcCompliant() {
return this.driver.jdbcCompliant();
}
}
class test {
public will_not_work() {
URL u = new URL("jar:file:/path/to/pgjdbc2.jar!/");
String classname = "org.postgresql.Driver";
URLClassLoader ucl = new URLClassLoader(new URL[] { u });
Class.forName(classname, true, ucl);
DriverManager.getConnection("jdbc:postgresql://host/db", "user", "pw");
// That will throw SQLException: No suitable driver
}
public will_work() {
URL u = new URL("jar:file:/path/to/pgjdbc2.jar!/");
String classname = "org.postgresql.Driver";
URLClassLoader ucl = new URLClassLoader(new URL[] { u });
Driver d = (Driver)Class.forName(classname, true, ucl).newInstance();
DriverManager.registerDriver(new DriverShim(d));
DriverManager.getConnection("jdbc:postgresql://host/db", "user", "pw");
// Success!
}
}