Java DataSource y la programación de JDBC DataSource son la forma de trabajar con bases de datos en nuestros programas Java. Ya hemos visto que JDBC DriverManager se puede usar para obtener conexiones con bases de datos relacionales. Pero cuando se trata de programación real, queremos más que solo conexiones.
Java DataSource
La mayoría de las veces buscamos un acoplamiento suelto para la conectividad, para poder cambiar fácilmente entre bases de datos, y soporte para la gestión de transacciones y sistemas distribuidos. JDBC DataSource es el enfoque preferido si buscas alguna de estas características en tu aplicación. La interfaz Java DataSource está presente en el paquete javax.sql
y solo declara dos métodos sobrecargados: getConnection()
y getConnection(String str1, String str2)
.
JDBC DataSource
Es responsabilidad de diferentes proveedores de bases de datos proporcionar diferentes tipos de implementaciones de la interfaz DataSource. Por ejemplo, el controlador JDBC de MySQL proporciona una implementación básica de la interfaz DataSource con la clase `com.mysql.jdbc.jdbc2.optional.MysqlDataSource`, mientras que el controlador de la base de datos Oracle lo implementa con la clase `oracle.jdbc.pool.OracleDataSource`. Estas clases de implementación proporcionan métodos a través de los cuales podemos proporcionar detalles del servidor de la base de datos junto con las credenciales del usuario. Algunas de las otras características comunes proporcionadas por estas clases de implementación de JDBC DataSource son;
- Caching de PreparedStatement para un procesamiento más rápido
- Configuración de tiempo de espera de conexión
- Funciones de registro
- Límite máximo de tamaño de ResultSet
Ejemplo de JDBC DataSource
Creemos un proyecto de ejemplo simple de JDBC DataSource y aprendamos cómo utilizar las clases de implementación básica de MySQL y Oracle DataSource para obtener la conexión a la base de datos. Nuestro proyecto final se verá como la imagen a continuación.
Java JDBC DataSource – Configuración de Base de Datos
Antes de entrar en nuestros programas de ejemplo, necesitamos configurar una base de datos con una tabla y datos de muestra. La instalación de la base de datos MySQL u Oracle está fuera del alcance de este tutorial, así que procederé a configurar la tabla con datos de muestra.
-- Crear tabla de empleados
CREATE TABLE `Employee` (
`empId` int(10) unsigned NOT NULL,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`empId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- insertar algunos datos de muestra
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;
Ahora pasemos a nuestros programas en Java. Para tener la configuración de la base de datos desacoplada de forma flexible, los leeré de un archivo de propiedades. Archivo db.properties:
# Propiedades de la base de datos 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
# Propiedades de la base de datos 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
Asegúrate de que las configuraciones anteriores coincidan con tu entorno local. También asegúrate de tener incluidos en la ruta de construcción del proyecto los archivos JAR JDBC de MySQL y Oracle.
Java JDBC DataSource – Ejemplo MySQL, Oracle
Escribamos una clase de fábrica que podamos usar para obtener un DataSource de MySQL u 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;
}
}
Observa que las clases de implementación de DataSource de Oracle y MySQL son muy similares, escribamos un programa de prueba simple para usar estos métodos y ejecutar algunas pruebas.
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();
}
}
}
}
Tenga en cuenta que la clase cliente es totalmente independiente de cualquier clase específica de base de datos. Esto nos ayuda a ocultar los detalles de implementación subyacentes del programa cliente y obtener beneficios de acoplamiento suelto y abstracción. Cuando ejecutamos el programa de prueba anterior, obtendremos la salida siguiente.
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
Ejemplo de Apache Commons DBCP
Si observamos la clase fábrica de DataSource de Java anterior, hay dos problemas principales con ella.
- Los métodos de la clase fábrica para crear el DataSource de MySQL y Oracle están estrechamente acoplados con la API del controlador respectivo. Si queremos eliminar el soporte para la base de datos Oracle en el futuro o queremos agregar soporte para otra base de datos, requerirá un cambio de código.
- La mayor parte del código para obtener el DataSource de MySQL y Oracle es similar, lo único diferente es la clase de implementación que estamos usando.
La API de Apache Commons DBCP nos ayuda a deshacernos de estos problemas al proporcionar una implementación de DataSource en Java que funciona como una capa de abstracción entre nuestro programa y los diferentes controladores JDBC. La biblioteca Apache DBCP depende de la biblioteca Commons Pool, así que asegúrese de que ambas estén en la ruta de construcción como se muestra en la imagen. Aquí está la clase fábrica de DataSource que utiliza BasicDataSource, que es una implementación simple de 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;
}
}
Como puedes ver, según la entrada del usuario, se crea un DataSource de MySQL u Oracle. Si solo estás dando soporte a una sola base de datos en la aplicación, ni siquiera necesitas esta lógica. Solo cambia las propiedades y puedes cambiar de un servidor de base de datos a otro. El punto clave a través del cual Apache DBCP proporciona abstracción es el método setDriverClassName(). Aquí tienes el programa cliente que utiliza el método de fábrica anterior para obtener diferentes tipos de conexión.
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();
}
}
}
}
Cuando ejecutas el programa anterior, la salida será la misma que en el programa anterior. Si observas el DataSource de JDBC de Java y su uso anterior, también se puede hacer con el DriverManager normal. El principal beneficio del DataSource de Java es cuando se usa dentro de un Contexto y con JNDI. Con configuraciones simples podemos crear un Pool de Conexiones de Base de Datos que es mantenido por el Contenedor mismo. La mayoría de los contenedores de servlets, como Tomcat y JBoss, proporcionan su propia implementación de DataSource de Java y todo lo que necesitamos es configurarlo a través de configuraciones simples basadas en XML y luego usar la búsqueda de contexto JNDI para obtener el DataSource de Java y trabajar con él. Esto nos ayuda a ocuparnos del agrupamiento y gestión de conexiones desde el lado de nuestra aplicación hasta el lado del servidor y, por lo tanto, nos da más tiempo para escribir la lógica de negocios para la aplicación. En el próximo tutorial, aprenderemos cómo podemos configurar DataSource en el Contenedor Tomcat y usarlo en una Aplicación Web.
Source:
https://www.digitalocean.com/community/tutorials/java-datasource-jdbc-datasource-example