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!
E' sufficiente scaricare il file ojdbc14.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!
... 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.
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:
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.
1.1
classes111.zip
7.3.4
1.2
classes12.zip
8.1.6
Core JDBC, JDBC 2.0 Extensions: Connection Pooling, JDBC-XA (no "recover()")
1.2/1.3
classes12.zip / .jar
9.2
1.4
ojdbc14.jar
9.2
JDBC 3.0 partial support: transaction savepoints, global/local transactions
1.4/1.5
ojdbc14.jar
10g R2
JDBC 3.0 full support
1.5
ojdbc5.jar
11g
JDK 1.5, JDBC 3.0 full support
1.6
ojdbc6.jar
11g
JDK 1.6, JDBC 4.0 almost full support (no SQLXML)
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 piu' recenti disponibili
ed almeno la versione corrispondente al DB utilizzato...
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, 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) (PORT=1521))
(ADDRESS=(PROTOCOL=TCP)(HOST=host2) (PORT=1521))
(CONNECT_DATA=(SERVICE_NAME=service)
(FAILOVER_MODE =
(TYPE = SELECT)
(METHOD = BASIC)
(RETRIES = 180)
(DELAY = 5))))
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.
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:
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.
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.
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.
Questa seconda tabella riporta le proprieta' quando si utilizza un datasource:
La configurazione si effettua impostando una serie di proprieta'.
Questa tabella riporta in parametri tipici di una configurazione JDBC:
Proprieta' Utilizzo hibernate.connection.driver_class jdbc driver class hibernate.connection.url jdbc URL hibernate.connection.username database user hibernate.connection.password database user password hibernate.connection.pool_size maximum number of pooled connections Proprieta' Utilizzo hibernate.connection.datasource datasource JNDI name hibernate.jndi.url URL of the JNDI provider (optional)
hibernate.jndi.class class of the JNDI InitialContextFactory (optional)
hibernate.connection.username database user (optional)
hibernate.connection.password database 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 name hibernate configuration key
c3p0.acquireIncrement hibernate.c3p0.acquire_increment
c3p0.idleConnectionTestPeriod hibernate.c3p0.idle_test_period
c3p0.initialPoolSize Not available -- uses minimum size
c3p0.maxIdleTime hibernate.c3p0.timeout
c3p0.maxPoolSize hibernate.c3p0.max_size
c3p0.maxStatements hibernate.c3p0.max_statements
c3p0.minPoolSize hibernate.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 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 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.
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>
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...
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/
Una lista piu' completa si puo' trovare sul sito
SUN.