Java DataSource, JDBC DataSource Voorbeeld

Java DataSource en JDBC DataSource programmering is de manier om met databases te werken in onze Java-programma’s. We hebben al gezien dat JDBC DriverManager kan worden gebruikt om relationele databaseverbindingen te verkrijgen. Maar als het op daadwerkelijke programmering aankomt, willen we meer dan alleen verbindingen.

Java DataSource

Meestal zijn we op zoek naar losse koppeling voor connectiviteit, zodat we gemakkelijk kunnen overschakelen tussen databases, verbindingen bundelen voor transactiebeheer en ondersteuning voor gedistribueerde systemen. JDBC DataSource is de voorkeursaanpak als u een van deze functies in uw toepassing nodig heeft. De Java DataSource-interface bevindt zich in het javax.sql-pakket en declareert slechts twee overlappende methoden: getConnection() en getConnection(String str1, String str2).

JDBC DataSource

Het is de verantwoordelijkheid van verschillende databaseleveranciers om verschillende soorten implementaties van de DataSource-interface te leveren. Bijvoorbeeld, de MySQL JDBC Driver biedt een basisimplementatie van de DataSource-interface met de klasse com.mysql.jdbc.jdbc2.optional.MysqlDataSource, en de Oracle-database driver implementeert het met de klasse oracle.jdbc.pool.OracleDataSource. Deze implementatieklassen bieden methoden waarmee we database-servergegevens kunnen verstrekken samen met gebruikersreferenties. Enkele van de andere veelvoorkomende functies die worden aangeboden door deze JDBC DataSource-implementatieklassen zijn;

  • Caching van PreparedStatement voor snellere verwerking
  • Instellingen voor verbindings-timeout
  • Logfuncties
  • Maximumgrootte drempelwaarde ResultSet

Voorbeeld van JDBC DataSource

Laten we een eenvoudig project maken met een voorbeeld van JDBC DataSource en leren hoe we de basisimplementatieklassen van MySQL en Oracle DataSource kunnen gebruiken om verbinding te maken met de database. Ons eindproject zal eruitzien zoals de onderstaande afbeelding.

Java JDBC DataSource – Database Setup

Voor we aan onze voorbeeldprogramma’s beginnen, hebben we wat database-instellingen nodig met tabel en voorbeeldgegevens. De installatie van een MySQL- of Oracle-database valt buiten de reikwijdte van deze tutorial, dus ik zal gewoon doorgaan en een tabel met voorbeeldgegevens instellen.

-- Maak de tabel Employee aan
CREATE TABLE `Employee` (
  `empId` int(10) unsigned NOT NULL,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`empId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Voeg enkele voorbeeldgegevens toe
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;

Laten we nu verder gaan met onze javaprogramma’s. Om de databaseconfiguratie losjes gekoppeld te hebben, zal ik ze lezen uit een eigenschappenbestand. db.properties-bestand:

# MySQL DB-eigenschappen
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-eigenschappen
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

Zorg ervoor dat bovenstaande configuraties overeenkomen met uw lokale opstelling. Zorg er ook voor dat u MySQL- en Oracle DB JDBC-jars hebt opgenomen in het build-pad van het project.

Java JDBC DataSource – MySQL, Oracle Voorbeeld

Laten we een fabrieksklasse schrijven die we kunnen gebruiken om een MySQL- of Oracle DataSource te krijgen.

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

Merk op dat zowel de Oracle- als MySQL-DataSource-implementatieklassen zeer vergelijkbaar zijn, laten we een eenvoudig testprogramma schrijven om deze methoden te gebruiken en enkele tests uit te voeren.

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

}

Let op dat de klasse van de client volledig onafhankelijk is van specifieke databaseklassen. Dit helpt ons om de onderliggende implementatiedetails te verbergen voor het clientprogramma en losse koppeling en abstractievoordelen te bereiken. Wanneer we het bovenstaande testprogramma uitvoeren, krijgen we de onderstaande uitvoer.

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

Voorbeeld van Apache Commons DBCP

Als je naar bovenstaande Java DataSource-fabrieksklasse kijkt, zijn er twee belangrijke problemen mee.

  1. De methoden van de fabrieksklasse om de MySQL- en Oracle DataSource te maken, zijn sterk gekoppeld aan de respectieve driver-API. Als we in de toekomst de ondersteuning voor de Oracle-database willen verwijderen of ondersteuning voor een andere database willen toevoegen, is codeaanpassing vereist.
  2. De meeste code om de MySQL- en Oracle DataSource te krijgen is vergelijkbaar, het enige verschil is de implementatieklasse die we gebruiken.

Apache Commons DBCP API helpt ons van deze problemen af te komen door een Java DataSource-implementatie te bieden die werkt als een abstractielaag tussen ons programma en verschillende JDBC-drivers. De Apache DBCP-bibliotheek is afhankelijk van de Commons Pool-bibliotheek, dus zorg ervoor dat beide in het build-pad aanwezig zijn zoals getoond in de afbeelding. Hier is de DataSource-fabrieksklasse die BasicDataSource gebruikt, dat is de eenvoudige implementatie van 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;
	}
}

Zoals je kunt zien, wordt afhankelijk van de gebruikersinvoer ofwel een MySQL- of Oracle DataSource gemaakt. Als je slechts één database ondersteunt in de applicatie, heb je zelfs deze logica niet nodig. Pas gewoon de eigenschappen aan en je kunt overschakelen van de ene database-server naar de andere. Het sleutelpunt waardoor Apache DBCP abstractie biedt, is de setDriverClassName()-methode. Hier is het clientprogramma dat bovenstaande fabrieksmethode gebruikt om verschillende soorten verbindingen te krijgen.

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

}

Als je het bovenstaande programma uitvoert, zal de uitvoer hetzelfde zijn als bij het vorige programma. Als je kijkt naar de Java JDBC DataSource en het bovenstaande gebruik, kan het ook worden gedaan met de normale DriverManager. Het belangrijkste voordeel van Java DataSource is wanneer het wordt gebruikt binnen een Context en met JNDI. Met eenvoudige configuraties kunnen we een databaseverbindingenpool maken die wordt onderhouden door de container zelf. De meeste servletcontainers zoals Tomcat en JBoss bieden hun eigen Java DataSource-implementatie en alles wat we nodig hebben, is om het te configureren via eenvoudige op XML gebaseerde configuraties en vervolgens JNDI-contextopzoeking te gebruiken om de Java DataSource te krijgen en ermee te werken. Dit helpt ons door het zorgen voor verbindingenpooling en -beheer vanaf onze applicatiekant naar de serverkant en geeft ons zo meer tijd om bedrijfslogica te schrijven voor de applicatie. In de volgende tutorial zullen we leren hoe we DataSource kunnen configureren in de Tomcat-container en het kunnen gebruiken in een webtoepassing.

Source:
https://www.digitalocean.com/community/tutorials/java-datasource-jdbc-datasource-example