Pick your JDBC driver at runtime

If you're going to do any sort of database activity in Java, you'll probably be using JDBC. Like ODBC before it, JDBC is a great way to insure that your program is free of any ties to the underlying database. Traditionally, the mechanism is that you put the JDBC driver somewhere in the classpath and then use class.forName() to find and load the driver.

One problem with this is that it presumes that your driver is in the classpath. This means either packaging the driver in your jar, or having to stick the driver somewhere (probably unpacking it too), or modifying your classpath.

"But why not use something like URLClassLoader and the overload of class.forName() that lets you specify the ClassLoader?" Because the DriverManager will refuse to use a driver not loaded by the system ClassLoader. Ouch!

The workaround for this is to create a shim class that implements java.sql.Driver. This shim class will do nothing but call the methods of an instance of a JDBC driver that we loaded dynamically. Something like this:

 
class CustomDriver implements Driver {
    private Driver driver;

    CustomDriver(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();
    }

    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return this.driver.getParentLogger();
    }
}
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 CunstomDriver(d));
            DriverManager.getConnection("jdbc:postgresql://host/db", "user", "pw");
            // Success!
        }
will_work() works because DriverShim was loaded by the system class loader, and the DriverManager doesn't care that it invokes a class that wasn't. We must perform the registration on the instance ourselves, because although Class.forName() will cause a registration to take place, that particular registration will fail for the same reason that will_not_work() fails.

转载于:https://www.cnblogs.com/alycat/archive/2013/06/04/3117023.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值