Oracle JDBC Drivers

Collegarsi all'RDBMS Oracle da un'applicazione Java e' semplice: basta utilizzare i corretti driver JDBC!

Sulla creazione ed utilizzo di driver JDBC per Oracle avevo gia' scritto tempo fa qualche documento...
Ma e' passato tanto tempo, ci sono parecchie novita' e puo' essere utile un documento pratico e... in italiano!

Per chi ha fretta!

E' sufficiente scaricare il file ojdbc6.jar dal sito Oracle, porlo nel CLASSPATH ed utilizzarlo nell'applicazione con:

 jdbc:oracle:thin:@<server>[:<1521>]:<database_name>

Impostando il nome del server, l'eventuale porta (default 1521) ed il SID: l'applicazione Java accede direttamente alla base dati Oracle!

Per chi ha tempo da perdere...

... ricominciamo dal principio!
JDBC e' un standard, che fa parte della piu' ampia definizione J2EE, e che definisce come debbono comportarsi le classi di accesso alle basi dati. I driver possono essere di tipo diverso a seconda dell'implementazione (eg. type 4: realizzato completamente in Java). Nel tempo sono state rilasciate diverse versioni dello standard, ciascuna con funzionalita' aggiuntive: JDBC, JDBC 2, JDBC 3, JDBC 4, ... Oracle distribuisce gratuitamente un driver JDBC di tipo 4 (chiamato Oracle Thin Driver) scritto completamente in Java ed utilizzabile quindi senza bisogno di altre librerie e/o installazioni.

Dal punto di vista del protocollo di rete, il thin driver di Oracle implementa il dialogo SQL*Net/NetX o, per essere piu' precisi, un suo sottoinsieme. La cosa fondamentale e' che rispetta lo standard JDBC e quindi l'applicazione che lo utilizza e' una normale applicazione Java.
L'applicazione puo' essere un classico Client/Server: quindi un'applicazione che accede in modo diretto alla base dati richiedendo servizi ad Oracle. Oppure si puo' trattare di un'applicazione mantenuta in un Java container ospitata un framework J2EE.

Sulla creazione e sull'utilizzo di driver JDBC per Oracle avevo gia' scritto tempo fa qualche documento (eg. Using Java Standard Interfaces to Oracle, Developing Custom and Standard Interfaces to Oracle in Java, Ditelo con... JDBC), A tali documenti rimando chi ha voglia di sorbirsi un po' di teoria sulle specifiche JDBC, sulle tipologie di driver o ha nostalgia del passato...
Nel seguito di questo documento si trova qualche ulteriore informazione su: versioni Oracle Thin Driver, Oracle RAC, internazionalizzazione, OCI ed altri driver JDBC; utilizzo con: Hibernate e C3P0, Tomcat, JBOSS, XA; altri driver JDBC, ... Sulle differenze tra le varie versioni di Oracle si puo' leggere invece questo simpatico documento.

Versioni

Nel tempo sono state rilasciate versioni differenti di driver JDBC Oracle. Anche il nome del file e' cambiato rispetto alle prime versioni... la seguente tabella riassume le principali versioni e driver:

Oracle JDBC thin driver
JDK
Driver File Name
Since Oracle Version
Up to
Date (from)
Note
1.1 classes111.zip 7.3.4 9.2 1996
1.2 classes12.zip 8.1.6 10.2 1999 Core JDBC, JDBC 2.0 Extensions: Connection Pooling, JDBC-XA (no "recover()")
1.2/1.3 classes12.zip / .jar 9.2 10.2 2002 jar from 9.2.0.7
1.4 ojdbc14.jar 9.2 10.2 2002 JDBC 3.0 partial support: transaction savepoints, global/local transactions
1.4/1.5 ojdbc14.jar 10g R2 10.2 2005 JDBC 3.0 full support
1.5 ojdbc5.jar 10g R2 11.2 2005 JDK 1.5, JDBC 3.0 full support
1.6/1.7 ojdbc6.jar 11g 2007-08
2011-09
JDK 1.6, JDBC 4.0 almost full support (no SQLXML)
JDK 1.7 for 11.2.0.3 and succ.
1.7/1.8 ojdbc7.jar 12g 2013-07 JDK 1.7, JDBC 4.1; JDK 1.8

La tabella precedente e' volutamente incompleta... Il suffisso puo' essere .zip o .jar. Il package che contiene il thin driver e' oracle.jdbc ed il nome e' OracleDriver, nelle versioni Oracle 8.x e precedenti il driver era contenuto nel package oracle.jdbc.driver. I driver possono essere scaricati gratuitamente dal sito Oracle nella sezione download (sezione JDBC).
Oracle garantisce la compatibilita' backward e forward tra i driver JDBC e le versioni di Oracle. Attualmente (1-APR-2010 NdE) tutte le versioni di Oracle supportate possono essere accedute da tutte le versioni di driver distribuite: i driver JDBC distribuiti dalla 9.2 e successivi possono collegarsi a tutti i database Oracle 9.2 e successivi (tutti i driver dalla 9.2 alla 11gR2 possono connettersi con tutti gli RDBMS dalla 9.2 alla 11gR2). Naturalmente per sfruttare le nuove features inserite in ogni versione vanno utilizzati i driver piu' recenti. Generalmente conviene utilizzare le versioni piu' recenti disponibili ed almeno la versione corrispondente al DB utilizzato...

Sul supporto Oracle ha politiche precise... quindi quanto segue non ha alcuna giustificazione ufficiale. Dal punto di vista funzionale la matrice di compatibilita' tra versioni JDBC/RDBMS e' molto piu' ampia rispetto a quella SQL*Net Client/Server. Quindi operare con vecchie versioni non e' supportato, ma funziona lo stesso!

Anche le stringhe di connessione sono cambiate nel tempo e sono supportati due differenti formati:

 jdbc:oracle:thin:@<server>[:<1521>]:<SID>

 jdbc:oracle:thin:@//<server>[:<1521>]/<SERVICE_NAME>

Con l'ulteriore possibilita', disponibile su molti driver, di indicare anche utenza/password prima del server!

Oracle RAC

La configurazione Oracle RAC consente di avere due server con due istanze che operano sullo stesso database in alta affidabilita'.
Una normale connessione JDBC non funzionerebbe... ecco tre esempi, via via piu' completi e corretti, per collegarsi via JDBC:

jdbc:oracle:thin:@host1:1521:sid1

jdbc:oracle:thin:@(DESCRIPTION=(LOAD_BALANCE=on)
(ADDRESS=(PROTOCOL=TCP)(HOST=host1) (PORT=1521))
(ADDRESS=(PROTOCOL=TCP)(HOST=host2) (PORT=1521))
(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=service)))

jdbc:oracle:thin:@(DESCRIPTION=(LOAD_BALANCE=on)
 (ADDRESS=(PROTOCOL=TCP)(HOST=host1-vip) (PORT=1521))
 (ADDRESS=(PROTOCOL=TCP)(HOST=host2-vip) (PORT=1521))
 (CONNECT_DATA=(SERVICE_NAME=service)
  (FAILOVER_MODE =
     (TYPE = SELECT)
     (METHOD = BASIC)
     (RETRIES = 180)
     (DELAY = 5))))

Dalla versione 11g R2 e' disponibile una nuova tipologia di configurazione del listener: Oracle SCAN (Single Client Access Name). In tale configurazione si sfrutta la possibilita' di associare ad un singolo nome piu' IP con un'assegnazione round robin sul DNS.

jdbc:oracle:thin:@(DESCRIPTION=
 (ADDRESS=(PROTOCOL=TCP)(HOST=scan_name) (PORT=1521))
 (CONNECT_DATA=(SERVICE_NAME=service)))

Per utilizzare lo SCAN listener anche il client deve essere in versione 11g R2 o superiore, altrimenti e' necessario utilizzare le stringhe di connessione indicate in precedenza.

I18N

Oracle supporta da parecchio tempo i caratteri nazionali. Basta impostare il character set del DB o usare le relative funzioni. Ora i browser e Java "conoscono" lo Unicode ed e' possibile utilizzare il character set Unicode anche nel DB. Ci sono diverse possibilita':

Dal punto di vista di linguaggio non vi sono problemi: Java supporta lo Unicode in modo nativo.

Il thin driver Oracle supporta i principali character set (eg. WE8DEC, WE8ISO8859P1, e UTF8). Nel caso servissero altri character set si utilizza orai18n.jar (nelle versioni Oracle precedenti si utilizzava nls_charset12.zip). Gli statement prepared sono trattati come CHAR se non viene cambiato il valore di default della property oracle.jdbc.defaultNChar (disponibile dalla versione 10g: tratta tutti i caratteri come nazionalizzati) e le stringhe vengono convertite prima del processing se non viene cambiato il valore di default della property oracle.jdbc.convertNcharLiterals.
Per controllare il contenuto di una colonna con caratteri nazionalizzati e' utile il comando SELECT DUMP(col,1016) FROM table;
Per maggiori dettagli si puo' consultare questo utile documento Oracle ed anche le mie pagine sulla nazionalizzazione Oracle e UTF-8.

Oracle OCI Driver (ed altri ancora)

Fino ad ora abbiamo parlato del thin driver di Oracle, che e' un driver di tipo 4 (ovvero completamente Java senza librerie esterne). In realta' non e' l'unico disponibile. E' infatti fornito da Oracle un driver di tipo 2 che utilizza le OCI e quindi richiede la presenza delle librerie di NetX per accedere all'RDBMS. La sintassi per l'utilizzo e' la seguente:

jdbc:oracle:oci:@<database_name>

Si tratta di un driver meno diffuso... La ragione e' che richiede l'installazione delle librerie client di Oracle. Tuttavia dal punto di vista di "dialogo" SQL*Net, di gestione dell'internazionalizzazione e, in alcuni casi, di prestazioni, risulta piu' completo. Nella versione 8 di Oracle il driver era chiamato oci8...
Nella stragrande maggioranza dei casi la scelta migliore e' il thin driver. L'OCI e' necessario nel caso in cui si utilizzi un protocollo di rete diverso dal TCP-IP. Oltre al driver OCI vi sono altri driver JDBC utilizzati dalle JVM Oracle. L'elenco completo delle funzionalita' disponibili nei driver JDBC Oracle e le versioni corrispondenti e' riportata in questa lista.

Molto piu' importanti sono i driver di terze parti che permettono l'accesso ad Oracle (eg. jdbc:bea:oracle://dbserver:port). Piu' avanti ne sono riportati alcuni.

J2EE

Sebbene sia possibile scrivere applicazioni Java che accedono direttamente via JDBC ai dati, questo non e' l'unico modo di accedere ai DB. Java e' un linguaggio object-oriented e le piu' recenti modalita' di programmazione con tale linguaggio sfruttano appeno tale possibilita'. Risulta quindi comune non utilizzare direttamente un driver JDBC ma altre strati intermedi come Hibernate e C3P0.

Hibernate

Hibernate consente di sviluppare classi persistenti con tutte le proprieta' piu' tipiche (eg. association, inheritance, polymorphism, composition, collections, ...) associate a tabelle di un database relazionale. Le query possono essere scritte in SQL nativo oppure nella forma portabile (HQL). L'associazione tra tabelle ed entita' viene realizzata con un file di mapping scritto in linguaggio XML.
La configurazione si effettua impostando una serie di proprieta'. Questa tabella riporta in parametri tipici di una configurazione JDBC:
Proprieta'Utilizzo
hibernate.connection.driver_classjdbc driver class
hibernate.connection.urljdbc URL
hibernate.connection.usernamedatabase user
hibernate.connection.passworddatabase user password
hibernate.connection.pool_sizemaximum number of pooled connections

Questa seconda tabella riporta le proprieta' quando si utilizza un datasource:

Proprieta'Utilizzo
hibernate.connection.datasourcedatasource JNDI name
hibernate.jndi.urlURL of the JNDI provider (optional)
hibernate.jndi.classclass of the JNDI InitialContextFactory (optional)
hibernate.connection.usernamedatabase user (optional)
hibernate.connection.passworddatabase user password (optional)

C3P0

Benche' presente, la gestione del pooling di risorse di Hibernate e' piuttosto rudimentale e quindi si preferiscono altri strumenti per la gestione dei pool di sessioni come il c3p0. c3p0 e' una semplice libreria per rendere Enterprise i normali driver JDBC realizzando le estensioni previste dalle specifiche jdbc3. In particolare fornisce il supporto per:

L'implementazione di c3p0 e' di ottima qualita': i DataSources sono Referenceable e Serializable, implementa tutte le specifiche JDBC2 e JDBC3, vengono effettuate tutte le "pulizie" necessarie di connessioni e statement, ... La configurazione di c3p0 avviene su file c3p0.properties (oppure come System properties o ancora con il file c3p0-config.xml). La configurazione e' leggermente diversa diversa se viene utilizzato da hibernate... in ogni caso i parametri principali sono i seguenti:

c3p0-native property namehibernate configuration key
c3p0.acquireIncrementhibernate.c3p0.acquire_increment
c3p0.idleConnectionTestPeriodhibernate.c3p0.idle_test_period
c3p0.initialPoolSizeNot available -- uses minimum size
c3p0.maxIdleTimehibernate.c3p0.timeout
c3p0.maxPoolSizehibernate.c3p0.max_size
c3p0.maxStatementshibernate.c3p0.max_statements
c3p0.minPoolSizehibernate.c3p0.min_size
c3p0.testConnectionsOnCheckout hibernate.c3p0.validate (hibernate 2.x only!)

Vista la teoria ecco un paio di esempi. Il primo esempio riporta una configurazione tipica Hibernate/C3P0 per Oracle:

hibernate.connection.driver_class = oracle.jdbc.driver.OracleDriver
hibernate.connection.url = jdbc:oracle:thin:@<server>[:<1521>]:<database_name>
hibernate.connection.username = scott
hibernate.connection.password = tiger
hibernate.c3p0.min_size=3
hibernate.c3p0.max_size=10
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=20
hibernate.dialect = org.hibernate.dialect.OracleDialect
Il secondo esempio riguarda Hibernate ed un Application Server utilizzando un datasource indirizzato mediante JNDI:
hibernate.connection.datasource = java:/comp/env/jdbc/test
hibernate.transaction.factory_class = org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_lookup_class = org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.dialect = org.hibernate.dialect.OracleDialect

Tomcat

Tomcat e' un Servlet/JSP container, tra tutti sicuramente il piu' noto e diffuso. Tomcat viene distribuito con una licenza Open molto libera (Apache).
Per configurare l'accesso ad Oracle con Tomcat sono necessari due passi:

Le applicazioni ospitate su Tomcat sono tipicamente JSP o Servlet e vengono deployate con file .war

Ecco un esempio di configurazione (il file e' server.xml e la risorsa va posta nel contesto dell'applicazione):

<Resource name="jdbc/myoracle" auth="Container"
   type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
   url="jdbc:oracle:thin:@db.xenialab.it:1569:testdb"
   username="scott" password="tiger" maxActive="20" maxIdle="10"
   maxWait="-1"/> 

JBoss

JBoss e' un EJB container. Per configurare l'accesso ad Oracle su JBoss sono necessari due passi:

Le applicazioni tipicamente ospitate su JBoss sono degli Enterprise Java Bean e vengono distribuite come file .ear.
Anche JBoss e' distribuito con una licenza Open. Vi sono diverse alternative commerciali a JBoss. Si tratta di ambienti complessi e di livello Enterprise: BEA Weblogic, IBM WebSphere, Oracle Application Server, ... tranne qualche eccezione la configurazione e' analoga!

Ecco un esempio (il file deve chiamarsi oracle-ds.xml):

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
  <local-tx-datasource>
    <jndi-name>DefaultDS</jndi-name>
    <connection-url>jdbc:oracle:thin:@db.xenilab.it:1569:xe</connection-url>
    <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
    <user-name>SCOTT</user-name>
    <password>TIGER</password>
    <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
    <metadata>
      <type-mapping>Oracle9i</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>

E le eccezioni? Sono tutte variazioni sul tema... Per esempio BEA fornisce due driver: weblogic.jdbcx.oracle.OracleDataSource (XA) e weblogic.jdbc.oracle.OracleDriver (non XA). E l'URL di connessione e': jdbc:bea:oracle://dbserver:port.

XA

Tutte le versioni dei Driver JDBC Oracle, eccetto le piu' obsolete, supportano l'interfaccia XA. Siete davvero interessati? Date un'occhiata a Il protocollo Two Phase Commit in Oracle.

Ecco comunque un esempio:

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
  <xa-datasource>
    <jndi-name>XAOracleDS</jndi-name>
    <track-connection-by-tx/>
    <isSameRM-override-value>false</isSameRM-override-value>
    <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
    <xa-datasource-property name="URL">jdbc:oracle:thin:@db.xenialab.it:1569:testdb</xa-datasource-property>
    <xa-datasource-property name="User">scott</xa-datasource-property>
    <xa-datasource-property name="Password">tiger</xa-datasource-property>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
    <no-tx-separate-pools/>
      <metadata>
         <type-mapping>Oracle9i</type-mapping>
      </metadata>
  </xa-datasource>
  <mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter" 
         name="jboss.jca:service=OracleXAExceptionFormatter">
    <depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
  </mbean>
</datasources>

Altro!

Oltre ai driver JDBC distribuiti da Oracle vi sono driver forniti da altri produttori per accedere all'RDBMS Oracle stesso... E naturalmente Oracle non e' l'unico DB utilizzabile con via JDBC. La seguente tabella riporta alcuni esempi...

Database
Connection string
Web site
Oracle jdbc:oracle:thin:@<server>[:<1521>]:<database_name> http://www.oracle.com/technology/tech/java/sqlj_jdbc/htdocs/jdbc_faq.htm
jdbc:oracle:oci:@<database_name>
jdbc:oracle:oci8:@<database_name>
jdbc:oracle:kprb:@
jdbc:bea:oracle://dbserver:port http://edocs.bea.com/wls/docs90/jdbc_drivers/oracle.html
jdbc:inetora:<hostname>
jdbc:inetpool:inetora:<hostname>
http://www.inetsoftware.de/products/jdbc-driver
jdbc:datadirect:oracle://<hostname>:<port>;<ServiceName=SID>[; ...]
DB2 jdbc:db2:<dbname> http://www-306.ibm.com/software/data/db2
jdbc:db2://<server>:<6789>/<db-name>
MySQL jdbc:mysql://<hostname>[<:3306>]/<dbname>[?<param>=<value>] http://dev.mysql.com
Cache jdbc:Cache://<host>:1972/<database> http://www.intersystems.com/cache/index.html
Firebird jdbc:firebirdsql:[//host[:port]/]<database> http://www.firebirdsql.org
HSQLDB jdbc:hsqldb:<databaseName> http://www.hsqldb.org
jdbc:hsqldb:hsql://<server>[:<1476>]
jdbc:hsqldb:http://<server>[:<1476>]
SQL Server jdbc:microsoft:sqlserver://<server_name>:<1433>[;DatabaseName=] http://msdn.microsoft.com/sql
jdbc:weblogic:mssqlserver4://<DB>@<HOST>:<1433>
jdbc:JTurbo://<HOST>:<1433><DB>
jdbc:inetdae://<HOST>:<1433>?database=<DB>
JDBC-ODBC jdbc:odbc:<alias> http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/bridge.doc.html
Informix jdbc:informix-sqli://<host>:<port>/<db>:INFORMIXSERVER=<server> http://www.informix.com
Sybase jdbc:sybase:Tds:<host>:<port>/<DBNAME> http://www.sybase.com/products/middleware/jconnectforjdbc
jdbc:sybase:Tds:<host>:<port>?ServiceName=<DBNAME>
PostgreSQL jdbc:postgresql:[<//host>[:<5432>/]]<database> http://jdbc.postgresql.org
INGRES jdbc:ingres://<host>:<Instance>/<database> http://www.ingres.com
Interbase jdbc:interbase://<server>/<full_db_path> http://info.borland.com/devsupport/interbase/opensource
PointBase jdbc:pointbase://embedded[:<PORT>]/<DB>
Apache Derby
Cloudscape
jdbc:derby:<DB>
jdbc:cloudscape:<DB>
IDS jdbc:ids://<HOST>:<PORT>/conn?dsn='<ODBC_DSN_NAME>'
SQLite jdbc:sqlite:<DB file> http://www.zentus.com/sqlitejdbc/
Hive jdbc:hive2://<host>:<10000>/<database> http://hive.apache.org

Una lista piu' completa si puo' trovare sul sito SUN.


Testo: Oracle JDBC
Data: 17 Gennaio 2007
Versione: 1.0.10 - 14 Febbraio 2014
Autore: mail@meo.bogliolo.name