Java DataSource e la programmazione JDBC DataSource sono il modo di lavorare con il database nei nostri programmi Java. Abbiamo già visto che il JDBC DriverManager può essere utilizzato per ottenere connessioni al database relazionale. Ma quando si tratta di programmazione effettiva, vogliamo più di semplici connessioni.
Java DataSource
La maggior parte delle volte cerchiamo un accoppiamento lento per la connettività in modo da poter passare facilmente da un database all’altro, il pooling delle connessioni per la gestione delle transazioni e il supporto ai sistemi distribuiti. JDBC DataSource è l’approccio preferito se cerchi una qualsiasi di queste caratteristiche nella tua applicazione. L’interfaccia Java DataSource è presente nel pacchetto javax.sql
e dichiara solo due metodi sovraccaricati getConnection()
e getConnection(String str1,String str2)
.
JDBC DataSource
È responsabilità dei diversi fornitori di database fornire diversi tipi di implementazioni dell’interfaccia DataSource. Ad esempio, il driver JDBC di MySQL fornisce un’implementazione di base dell’interfaccia DataSource con la classe `com.mysql.jdbc.jdbc2.optional.MysqlDataSource`, mentre il driver del database Oracle lo implementa con la classe `oracle.jdbc.pool.OracleDataSource`. Queste classi di implementazione forniscono metodi attraverso i quali possiamo fornire dettagli del server del database insieme alle credenziali dell’utente. Alcune delle altre funzionalità comuni fornite da queste classi di implementazione JDBC DataSource includono:
- Caching di PreparedStatement per un’elaborazione più veloce
- Impostazioni di timeout della connessione
- Funzionalità di logging
- Soglia di dimensione massima del ResultSet
JDBC DataSource Esempio
Creiamo un semplice progetto di esempio JDBC DataSource e impariamo come utilizzare le classi di implementazione di base di MySQL e Oracle DataSource per ottenere la connessione al database. Il nostro progetto finale avrà un aspetto simile all’immagine seguente.
Java JDBC DataSource – Configurazione del Database
Prima di entrare nei nostri esempi di programmi, abbiamo bisogno di configurare un database con tabella e dati di esempio. L’installazione del database MySQL o Oracle è fuori dallo scopo di questo tutorial, quindi procederò con la creazione della tabella e l’inserimento di dati di esempio.
-- Creare la tabella Employee
CREATE TABLE `Employee` (
`empId` int(10) unsigned NOT NULL,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`empId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Inserire alcuni dati di esempio
INSERT INTO `Employee` (`empId`, `name`)
VALUES
(1, 'Pankaj'),
(2, 'David');
commit;
CREATE TABLE "EMPLOYEE"
(
"EMPID" NUMBER NOT NULL ENABLE,
"NAME" VARCHAR2(10 BYTE) DEFAULT NULL,
PRIMARY KEY ("EMPID")
);
Insert into EMPLOYEE (EMPID,NAME) values (10,'Pankaj');
Insert into EMPLOYEE (EMPID,NAME) values (5,'Kumar');
Insert into EMPLOYEE (EMPID,NAME) values (1,'Pankaj');
commit;
Ora passiamo ai nostri programmi Java. Per avere una configurazione del database poco accoppiata, li leggerò da un file di proprietà. File db.properties:
# Proprietà del database MySQL
MYSQL_DB_DRIVER_CLASS=com.mysql.jdbc.Driver
MYSQL_DB_URL=jdbc:mysql://localhost:3306/UserDB
MYSQL_DB_USERNAME=pankaj
MYSQL_DB_PASSWORD=pankaj123
# Proprietà del database Oracle
ORACLE_DB_DRIVER_CLASS=oracle.jdbc.driver.OracleDriver
ORACLE_DB_URL=jdbc:oracle:thin:@localhost:1521:orcl
ORACLE_DB_USERNAME=hr
ORACLE_DB_PASSWORD=oracle
Assicurati che le configurazioni sopra corrispondano alla tua configurazione locale. Assicurati anche di includere i jar JDBC di MySQL e Oracle nel percorso di compilazione del progetto.
Java JDBC DataSource – Esempio MySQL, Oracle
Scriviamo una classe factory che possiamo utilizzare per ottenere il DataSource MySQL o Oracle.
package com.journaldev.jdbc.datasource;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import oracle.jdbc.pool.OracleDataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
public class MyDataSourceFactory {
public static DataSource getMySQLDataSource() {
Properties props = new Properties();
FileInputStream fis = null;
MysqlDataSource mysqlDS = null;
try {
fis = new FileInputStream("db.properties");
props.load(fis);
mysqlDS = new MysqlDataSource();
mysqlDS.setURL(props.getProperty("MYSQL_DB_URL"));
mysqlDS.setUser(props.getProperty("MYSQL_DB_USERNAME"));
mysqlDS.setPassword(props.getProperty("MYSQL_DB_PASSWORD"));
} catch (IOException e) {
e.printStackTrace();
}
return mysqlDS;
}
public static DataSource getOracleDataSource(){
Properties props = new Properties();
FileInputStream fis = null;
OracleDataSource oracleDS = null;
try {
fis = new FileInputStream("db.properties");
props.load(fis);
oracleDS = new OracleDataSource();
oracleDS.setURL(props.getProperty("ORACLE_DB_URL"));
oracleDS.setUser(props.getProperty("ORACLE_DB_USERNAME"));
oracleDS.setPassword(props.getProperty("ORACLE_DB_PASSWORD"));
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return oracleDS;
}
}
Nota che le classi di implementazione del DataSource di Oracle e MySQL sono molto simili, scriviamo quindi un semplice programma di test per utilizzare questi metodi ed eseguire alcuni test.
package com.journaldev.jdbc.datasource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
public class DataSourceTest {
public static void main(String[] args) {
testDataSource("mysql");
System.out.println("**********");
testDataSource("oracle");
}
private static void testDataSource(String dbType) {
DataSource ds = null;
if("mysql".equals(dbType)){
ds = MyDataSourceFactory.getMySQLDataSource();
}else if("oracle".equals(dbType)){
ds = MyDataSourceFactory.getOracleDataSource();
}else{
System.out.println("invalid db type");
return;
}
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
stmt = con.createStatement();
rs = stmt.executeQuery("select empid, name from Employee");
while(rs.next()){
System.out.println("Employee ID="+rs.getInt("empid")+", Name="+rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Notare che la classe client è completamente indipendente da qualsiasi classe specifica del database. Ciò ci aiuta a nascondere i dettagli di implementazione sottostanti dal programma client e ottenere i benefici di accoppiamento lento e astrazione. Quando eseguiamo il programma di test sopra, otterremo l’output seguente.
Employee ID=1, Name=Pankaj
Employee ID=2, Name=David
**********
Employee ID=10, Name=Pankaj
Employee ID=5, Name=Kumar
Employee ID=1, Name=Pankaj
Apache Commons DBCP Example
Se guardi la classe factory di Java DataSource sopra, ci sono due problemi principali.
- I metodi della classe factory per creare il MySQL e Oracle DataSource sono strettamente accoppiati con le rispettive API del driver. Se vogliamo rimuovere il supporto per il database Oracle in futuro o aggiungere supporto per un altro database, sarà necessario modificare il codice.
- La maggior parte del codice per ottenere il MySQL e Oracle DataSource è simile, l’unica differenza è la classe di implementazione che stiamo usando.
La libreria Apache Commons DBCP ci aiuta a risolvere questi problemi fornendo un’implementazione di Java DataSource che funziona come uno strato di astrazione tra il nostro programma e i diversi driver JDBC. La libreria Apache DBCP dipende dalla libreria Commons Pool, quindi assicurati che entrambe siano nel percorso di compilazione come mostrato nell’immagine. Ecco la classe factory di DataSource che utilizza BasicDataSource, che è l’implementazione semplice di DataSource.
package com.journaldev.jdbc.datasource;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
public class DBCPDataSourceFactory {
public static DataSource getDataSource(String dbType){
Properties props = new Properties();
FileInputStream fis = null;
BasicDataSource ds = new BasicDataSource();
try {
fis = new FileInputStream("db.properties");
props.load(fis);
}catch(IOException e){
e.printStackTrace();
return null;
}
if("mysql".equals(dbType)){
ds.setDriverClassName(props.getProperty("MYSQL_DB_DRIVER_CLASS"));
ds.setUrl(props.getProperty("MYSQL_DB_URL"));
ds.setUsername(props.getProperty("MYSQL_DB_USERNAME"));
ds.setPassword(props.getProperty("MYSQL_DB_PASSWORD"));
}else if("oracle".equals(dbType)){
ds.setDriverClassName(props.getProperty("ORACLE_DB_DRIVER_CLASS"));
ds.setUrl(props.getProperty("ORACLE_DB_URL"));
ds.setUsername(props.getProperty("ORACLE_DB_USERNAME"));
ds.setPassword(props.getProperty("ORACLE_DB_PASSWORD"));
}else{
return null;
}
return ds;
}
}
Come puoi vedere, a seconda dell’input dell’utente, viene creato un oggetto DataSource per MySQL o Oracle. Se supporti solo un database nell’applicazione, non hai bisogno di questa logica. Basta cambiare le proprietà e puoi passare da un server di database all’altro. Il punto chiave attraverso il quale Apache DBCP fornisce l’astrazione è il metodo setDriverClassName(). Ecco il programma client che utilizza il metodo factory sopra per ottenere diversi tipi di connessione.
package com.journaldev.jdbc.datasource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
public class ApacheCommonsDBCPTest {
public static void main(String[] args) {
testDBCPDataSource("mysql");
System.out.println("**********");
testDBCPDataSource("oracle");
}
private static void testDBCPDataSource(String dbType) {
DataSource ds = DBCPDataSourceFactory.getDataSource(dbType);
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
stmt = con.createStatement();
rs = stmt.executeQuery("select empid, name from Employee");
while(rs.next()){
System.out.println("Employee ID="+rs.getInt("empid")+", Name="+rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Quando esegui il programma sopra, l’output sarà lo stesso del programma precedente. Se guardi il DataSource JDBC Java e l’utilizzo sopra descritto, può essere fatto anche con il normale DriverManager. Il maggior vantaggio di Java DataSource è quando viene utilizzato all’interno di un contesto e con JNDI. Con semplici configurazioni possiamo creare un pool di connessioni al database gestito dal container stesso. La maggior parte dei container servlet come Tomcat e JBoss fornisce la propria implementazione di Java DataSource e tutto ciò di cui abbiamo bisogno è configurarlo tramite semplici configurazioni basate su XML e quindi utilizzare la ricerca di contesto JNDI per ottenere il Java DataSource e lavorarci. Questo ci aiuta occupandosi del pooling delle connessioni e della gestione dal lato dell’applicazione al lato del server e ci permette di dedicare più tempo alla scrittura della logica di business dell’applicazione. Nel prossimo tutorial, impareremo come configurare il DataSource nel container Tomcat e usarlo in un’applicazione Web.
Source:
https://www.digitalocean.com/community/tutorials/java-datasource-jdbc-datasource-example