2015-01-27 2 views
5

Я хочу подключиться к двум различным базам данных Oracle (один 8.0.5.0.0 и один 12c) через JDBC. У меня есть оба драйвера JDBC, которые могут индивидуально и успешно подключаться к соответствующей БД через простые приложения «привет мир». Ниже я поместил их вместе в одно приложение Java, которое, к сожалению, больше не работает (с загрузкой обоих драйверов).Использование нескольких драйверов JDBC Oracle в одном приложении Java?

Я прочитал это сообщение: Handle multiple JDBC drivers from the SAME VENDOR. Вариант 1, упомянутый здесь, может быть, может идти, но, похоже, есть одна серьезная проблема:

Похоже, что OracleDataSource еще не существует в старой версии 8 и был введен только в более поздних версиях (в 12c версия драйвера существует).

Любые подсказки о том, как подключиться к этим двум базам данных Oracle с помощью одного приложения Java и двух драйверов JDBC?

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

Спасибо, adavnce!

+0

мм Я бы использовал последний драйвер для обоих соединений и просто определил 2 отдельных источника данных. Совместимость драйверов AFAIK jdbc довольно прочная. – BigMike

+0

Я глуп, но драйверы оракулов обратно совместимы. Последний драйвер не работает для устаревшей базы данных? – Gimby

+2

Драйвер 12c не будет работать с базой данных 8i, нет; они обратно совместимы, но только до определенной точки. См. [Часто задаваемые вопросы JDBC] (http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#01_03) и [примечание поддержки Oracle 207303.1] (http://support.oracle .com/epmos/faces/DocumentDisplay? id = 207303.1) –

ответ

6

Если вы не зарегистрировали драйвер, вы его не загрузили одним и тем же загрузчиком классов.

Затем вы можете создать соединения с помощью двух различных драйверов, загрузив их через отдельные загрузчиков классов:

// 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 становится немного сложным, но в целом вы можете использовать созданные через него соединения без каких-либо проблем.

+0

Возможно ли, что там может быть опечатка? Мой Eclipse жалуется на строку «Driver ora8driver ...», в которой говорится: «Несоответствие типов: невозможно преобразовать из класса В драйвер» – tschlein

+0

@kwirschau: вы правы. 'loadClass()' возвращает 'Class', а не' Driver'. Извините, печатал из памяти. –

+0

Да! Это сработало! Faboulous! – tschlein

1

Я вижу два разных решения для разных созвездий.

(Использование же (?) Классов с различными версиями обычно было бы использование idealh случае OSGi, или если ваше приложение является RCP NetBeans, модульная системой. Это работает с использованием загрузчиков классов, которые разделяют программу на модули, так один в различных модулях может загружать различные баночки с разными версиями одного и того же продукта.)

(в качестве альтернативы можно было бы другое приложение со своим собственным Oracle баночку, доступ с помощью RMI.)

Вы могли бы используйте ту же технику: либо напишите свое собственное делегирование ClassLoader, загружающее правильную банку, или используйте концептуально более простой RMI, который, однако, требует управления системными ресурсами.

Так

  1. Не использовать импорт от поставщиков; что противоречит неопределенности поставщика JDBC.

  2. Убедитесь, что интерфейсы javax.sql поставляются из java-ee jar.


Выбор решения ClassLoader:

Было бы лучше, чтобы сделать свой собственный делегирующий драйвер говорить с протоколом jdbc:myswitch:8: .... Затем он может использовать два разных экземпляра класса загрузчика. Например, используя URLClassLoader с контуром file:/....

Можно создать два отдельных экземпляра пользовательского делегирующего драйвера, чтобы можно было использовать шаблон делегирования.

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)); 
    } 
1

Вы можете использовать шаблон фабричного проектирования, чтобы получить какое соединение, которое вы хотели бы иметь, а затем сохраните его с помощью Singleton, который подключается к каждой базе данных.

Итак, каждое из ваших соединений с базой данных - это Singletons, и, будучи instanated Factory с заданным ENUM, вы ставите его в качестве параметра.

Смежные вопросы