在一个Java应用程序中使用多个Oracle JDBC驱动程序?

我想通过JDBC连接到两个不同的Oracle数据库(一个8.0.5.0.0和一个12c)。 我有两个JDBC驱动程序,可以通过简单的“hello world”应用程序单独成功连接到相应的DB。 下面,我将它们放在一个Java应用程序中,遗憾的是它不再起作用(两个驱动程序都被加载)。

我已经阅读过这篇文章: 处理来自SAME VENDOR的多个JDBC驱动程序 。 提到的选项1可能有办法,但似乎有一个主要问题:

似乎OracleDataSource在旧版本8驱动程序中尚不存在,并且仅在更高版本中引入(在12c版本驱动程序中存在)。

关于如何使用一个Java应用程序和两个JDBC驱动程序连接这两个Oracle数据库的任何提示?

 import java.sql.*; class db { public static void main (String args []) throws SQLException { // Oracle 8 connection DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection c1 = DriverManager.getConnection( "jdbc:oracle:thin:@some-oracle-8-server:port:sid", "my-user", "my-password"); Statement s1 = c1.createStatement (); ResultSet r1 = s1.executeQuery ("SELECT banner FROM V$VERSION WHERE banner LIKE 'Oracle%'"); while (r1.next ()) { System.out.println(r1.getString (1)); } c1.close(); // Oracle 12 connection Connection c2 = DriverManager.getConnection( "jdbc:oracle:thin:@some-oracle-12-server:port:sid", "my-user", "my-password"); Statement s2 = c2.createStatement (); ResultSet r2 = s2.executeQuery ("SELECT banner FROM V$VERSION WHERE banner LIKE 'Oracle%'"); while (r2.next ()) { System.out.println(r2.getString (1)); } c2.close(); } } 

谢谢你!

如果您没有注册驱动程序,则可以避免它们被同一个类加载器加载。

然后,您可以使用两个不同的驱动程序通过单独的类加载器加载它们来创建连接:

 // Oracle 8 connection File jar = new File("/path/to/oracle8.jar"); URL[] cp = new URL[1]; cp[0] = jar.toURI().toURL(); URLClassLoader ora8loader = new URLClassLoader(cp, ClassLoader.getSystemClassLoader()); Class drvClass = ora8loader.loadClass("oracle.jdbc.driver.OracleDriver"); Driver ora8driver = (Driver)drvClass.newInstance(); Properties props = new Properties(); // "user" instead of "username" props.setProperty("user", "my-user"); props.setProperty("password", "my-password"); Connection ora8conn = ora8driver.connect("jdbc:oracle:thin:@some-oracle-8-server:port:sid",props); 

然后对Oracle 12驱动程序执行相同操作。

您也可以通过DriverManager仍然使用“其他”驱动程序,但我不确定。

在某些极端情况下,访问Oracle特定类会变得有点复杂,但一般情况下,您可以使用通过此创建的连接而不会出现任何问题。

我看到了针对不同星座的两种不同解决方案。

(使用具有不同版本的相同(?)类通常是OSGi的理想用例,或者如果您的应用程序是NetBeans RCP,它们的模块化系统。这使用类加载器将软件分成模块,因此在不同模块中使用可以装载不同版本的同一产品的不同jar子。)

(或者,可以使用自己的Oracle jar使用RMI访问不同的应用程序。)

您可以使用相同的技术:编写您自己的委托ClassLoader正确jar的ClassLoader ,或使用概念上更简单的RMI ,但需要管理系统资源。

所以

  1. 不要使用供应商的import; 这与JDBC的供应商独立性相反。

  2. 确保javax.sql接口来自java-ee jar。


选择ClassLoader解决方案:

最好让你自己的委托驱动程序用协议jdbc:myswitch:8: ...jdbc:myswitch:8: ... 然后它可以使用两个不同的类加载器实例。 例如,使用带有file:/...的URLClassLoader file:/... path。

可以创建两个单独的自定义委托驱动程序实例,因此可以使用委托模式。

 public static class MySwitchDriver implements Driver { private final String oraURIPrefix; private final Driver delegateDriver; public MySwitchDriver(String oraURIPrefix) { this.oraURIPrefix = oraURIPrefix; // "8:" or "12:" String jarFileURI = oraURIPrefi.equals("8") ? "file:/... .jar" : "file:/... .jar"; URLClassLoader classLoader = new" URLClassLoader(...); delegateDriver = classLoader.loadClass( "oracle.jdbc.driver.OracleDriver", true); DriverManager.registerDriver(this); } private String delegateURL(String url) { // Something safer than this: return "jdbc:" + url.substring( "jdbc:myswitch".length + oraURIPrefix.length); } @Override public Connection connect(String url, Properties info) throws SQLException { String url2 = delegateURL(url); Properties info2 = info; return delegateDriver.connect(url2, info2); } @Override public boolean acceptsURL(String url) throws SQLException { return url.startsWith("jdbc:myswitch:" + oraURIPrefix) && delegateDriver.acceptsURL(delegateURL(url)); } 

你可以使用Factory设计模式来获得你想要的连接,然后将它存储在一些Singleton中,它可以连接到每个数据库。

因此,您的每个数据库连接都是单例,并且由工厂根据给定的ENUM进行实例化,您将其作为参数。