Java DataSource und JDBC DataSource Programmierung sind die Möglichkeiten, um mit Datenbanken in unseren Java-Programmen zu arbeiten. Wir haben bereits gesehen, dass die JDBC DriverManager verwendet werden kann, um Verbindungen zu relationalen Datenbanken herzustellen. Aber wenn es um die tatsächliche Programmierung geht, wollen wir mehr als nur Verbindungen.
Java DataSource
Die meiste Zeit suchen wir nach einer lockeren Kopplung für die Konnektivität, so dass wir leicht zwischen Datenbanken wechseln können, Verbindungspooling für die Transaktionsverwaltung und Unterstützung für verteilte Systeme. JDBC DataSource ist der bevorzugte Ansatz, wenn Sie eine dieser Funktionen in Ihrer Anwendung benötigen. Das Java DataSource-Interface befindet sich im Paket javax.sql
und deklariert nur zwei überladene Methoden getConnection()
und getConnection(String str1, String str2)
.
JDBC DataSource
Es ist die Verantwortung verschiedener Datenbankanbieter, unterschiedliche Implementierungen des DataSource-Interfaces bereitzustellen. Zum Beispiel bietet der MySQL JDBC-Treiber eine grundlegende Implementierung des DataSource-Interfaces mit der Klasse \texttt{com.mysql.jdbc.jdbc2.optional.MysqlDataSource}, während der Oracle-Datenbanktreiber es mit der Klasse \texttt{oracle.jdbc.pool.OracleDataSource} implementiert. Diese Implementierungsklassen bieten Methoden, über die wir Details zum Datenbankserver mit Benutzeranmeldeinformationen bereitstellen können. Einige der anderen gemeinsamen Funktionen, die von diesen JDBC-DataSource-Implementierungsklassen bereitgestellt werden, sind:
- Caching von PreparedStatement für schnellere Verarbeitung
- Timeout-Einstellungen für Verbindungen
- Protokollierungsfunktionen
- Maximale Größenbegrenzung für das ResultSet
Beispiel für JDBC DataSource
Erstellen wir ein einfaches Beispielprojekt für JDBC DataSource und erfahren, wie wir die grundlegenden Implementierungsklassen von MySQL und Oracle DataSource verwenden, um eine Datenbankverbindung zu erhalten. Unser endgültiges Projekt sieht wie das folgende Bild aus.
Java JDBC DataSource – Datenbank-Setup
Bevor wir mit unseren Beispielprogrammen beginnen, benötigen wir einige Datenbank-Setups mit Tabelle und Beispieldaten. Die Installation von MySQL oder Oracle-Datenbanken fällt nicht in den Rahmen dieses Tutorials, daher werde ich einfach die Tabelle mit Beispieldaten einrichten.
-- Erstellen Sie die Mitarbeiter-Tabelle
CREATE TABLE `Employee` (
`empId` int(10) unsigned NOT NULL,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`empId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Fügen Sie einige Beispieldaten ein
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;
Jetzt gehen wir zu unseren Java-Programmen über. Um die Datenbankkonfiguration lose gekoppelt zu haben, werde ich sie aus einer Eigenschaftsdatei lesen. db.properties-Datei:
# MySQL DB Eigenschaften
MYSQL_DB_DRIVER_CLASS=com.mysql.jdbc.Driver
MYSQL_DB_URL=jdbc:mysql://localhost:3306/UserDB
MYSQL_DB_USERNAME=pankaj
MYSQL_DB_PASSWORD=pankaj123
# Oracle DB Eigenschaften
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
Vergewissern Sie sich, dass die oben genannten Konfigurationen mit Ihrer lokalen Einrichtung übereinstimmen. Stellen Sie außerdem sicher, dass Sie die MySQL- und Oracle-DB-JDBC-Jars im Build-Pfad des Projekts enthalten haben.
Java JDBC DataSource – MySQL, Oracle Beispiel
Lassen Sie uns eine Fabrikklasse schreiben, die wir verwenden können, um MySQL- oder Oracle-Datenquellen zu erhalten.
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;
}
}
Beachten Sie, dass sowohl die Oracle- als auch die MySQL-DataSource-Implementierungsklassen sehr ähnlich sind. Schreiben wir ein einfaches Testprogramm, um diese Methoden zu verwenden und einige Tests durchzuführen.
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();
}
}
}
}
Beachten Sie, dass die Client-Klasse völlig unabhängig von spezifischen Datenbankklassen ist. Dies hilft uns, die zugrunde liegenden Implementierungsdetails vor dem Client-Programm zu verbergen und die Vorteile von lockerer Kopplung und Abstraktion zu erreichen. Wenn wir das obige Testprogramm ausführen, erhalten wir die folgende Ausgabe.
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 Beispiel
Wenn Sie sich die obige Java DataSource Factory-Klasse ansehen, gibt es zwei Hauptprobleme damit.
- Die Methoden der Factory-Klasse zur Erstellung der MySQL- und Oracle-Datenquelle sind eng mit den jeweiligen Treiber-APIs gekoppelt. Wenn wir in Zukunft die Unterstützung für die Oracle-Datenbank entfernen oder eine andere Datenbankunterstützung hinzufügen möchten, ist ein Codeänderung erforderlich.
- Der Großteil des Codes zum Abrufen der MySQL- und Oracle-Datenquelle ist ähnlich, der einzige Unterschied besteht in der Implementierungsklasse, die wir verwenden.
Die Apache Commons DBCP-API hilft uns, diese Probleme zu beseitigen, indem sie eine Java-DataSource-Implementierung bereitstellt, die als Abstraktionsschicht zwischen unserem Programm und verschiedenen JDBC-Treibern fungiert. Die Apache DBCP-Bibliothek ist abhängig von der Commons Pool-Bibliothek, stellen Sie also sicher, dass beide im Build-Pfad vorhanden sind, wie im Bild gezeigt. Hier ist die DataSource-Factory-Klasse unter Verwendung von BasicDataSource, die die einfache Implementierung der DataSource ist.
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;
}
}
Wie Sie sehen können, wird je nach Benutzereingabe entweder eine MySQL- oder eine Oracle-Datenquelle erstellt. Wenn Sie in der Anwendung nur eine Datenbank unterstützen, benötigen Sie diese Logik nicht einmal. Ändern Sie einfach die Eigenschaften und Sie können von einem Datenbankserver auf einen anderen wechseln. Der Schlüsselpunkt, durch den Apache DBCP Abstraktion ermöglicht, ist die Methode setDriverClassName(). Hier ist das Client-Programm, das die obige Factory-Methode verwendet, um verschiedene Arten von Verbindungen abzurufen.
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();
}
}
}
}
Wenn Sie das obige Programm ausführen, wird die Ausgabe wie im vorherigen Programm sein. Wenn Sie sich den Java JDBC-Datenquellen und der oben genannten Verwendung ansehen, kann dies auch mit dem normalen DriverManager durchgeführt werden. Der Hauptvorteil von Java DataSource besteht darin, dass es in einem Kontext und mit JNDI verwendet wird. Mit einfachen Konfigurationen können wir einen Datenbank-Verbindungspool erstellen, der vom Container selbst verwaltet wird. Die meisten Servlet-Container wie Tomcat und JBoss bieten ihre eigene Java DataSource-Implementierung an, und wir müssen sie nur über einfache XML-basierte Konfigurationen konfigurieren und dann den JNDI-Kontextlookup verwenden, um die Java DataSource abzurufen und damit zu arbeiten. Dies erleichtert uns die Verwaltung von Verbindungs-Pooling und -Management von unserer Anwendungsseite zur Serverseite und gibt uns so mehr Zeit, um die Geschäftslogik für die Anwendung zu schreiben. Im nächsten Tutorial lernen wir, wie wir die DataSource im Tomcat-Container konfigurieren und in einer Webanwendung verwenden können.
Source:
https://www.digitalocean.com/community/tutorials/java-datasource-jdbc-datasource-example