Java DataSource e a programação JDBC DataSource são as maneiras de trabalhar com banco de dados em nossos programas Java. Já vimos que O JDBC DriverManager pode ser usado para obter conexões com bancos de dados relacionais. Mas quando se trata de programação real, queremos mais do que apenas conexões.
O Java DataSource
Na maioria das vezes, buscamos um acoplamento flexível para a conectividade, para que possamos alternar facilmente entre bancos de dados, pooling de conexões para o gerenciamento de transações e suporte a sistemas distribuídos. O JDBC DataSource é a abordagem preferida se você procura alguma dessas características em sua aplicação. A interface Java DataSource está presente no pacote javax.sql
e declara apenas dois métodos sobrecarregados: getConnection()
e getConnection(String str1, String str2)
.
O JDBC DataSource
É responsabilidade de diferentes fornecedores de banco de dados fornecer diferentes tipos de implementação da interface DataSource. Por exemplo, o driver JDBC do MySQL fornece uma implementação básica da interface DataSource com a classe \texttt{com.mysql.jdbc.jdbc2.optional.MysqlDataSource}, enquanto o driver do banco de dados Oracle a implementa com a classe \texttt{oracle.jdbc.pool.OracleDataSource}. Essas classes de implementação fornecem métodos por meio dos quais podemos fornecer detalhes do servidor de banco de dados com credenciais de usuário. Algumas das outras características comuns fornecidas por essas classes de implementação do JDBC DataSource são;
- Armazenamento em cache de PreparedStatement para processamento mais rápido
- Configurações de timeout de conexão
- Recursos de registro
- Limite máximo de tamanho de ResultSet
Exemplo de JDBC DataSource
Vamos criar um projeto simples de exemplo usando JDBC DataSource e aprender como usar as classes de implementação básica do MySQL e Oracle DataSource para obter a conexão com o banco de dados. Nosso projeto final ficará semelhante à imagem abaixo.
Java JDBC DataSource – Configuração do Banco de Dados
Antes de entrarmos em nossos programas de exemplo, precisamos de alguma configuração de banco de dados com tabela e dados de exemplo. A instalação do banco de dados MySQL ou Oracle está fora do escopo deste tutorial, então vou apenas configurar a tabela com dados de exemplo.
-- Crie a tabela Funcionário
CREATE TABLE `Employee` (
`empId` int(10) unsigned NOT NULL,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`empId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- insira alguns dados de exemplo
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;
Agora vamos avançar para nossos programas Java. Para ter a configuração do banco de dados desacoplada, vou lê-los de um arquivo de propriedades. Arquivo db.properties:
# Propriedades do banco de dados 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
# Propriedades do banco de dados 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
Verifique se as configurações acima correspondem à sua configuração local. Certifique-se também de incluir os jars JDBC do MySQL e Oracle DB no caminho de construção do projeto.
Java JDBC DataSource – Exemplo MySQL, Oracle
Vamos escrever uma classe factory que podemos usar para obter o DataSource do MySQL ou 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;
}
}
Observe que as classes de implementação DataSource do Oracle e MySQL são muito similares. Vamos escrever um programa de teste simples para usar esses métodos e executar alguns testes.
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();
}
}
}
}
Observe que a classe cliente é totalmente independente de qualquer classe específica de banco de dados. Isso nos ajuda a ocultar os detalhes de implementação subjacentes do programa cliente e obter benefícios de acoplamento fraco e abstração. Quando executamos o programa de teste acima, obtemos a seguinte saída.
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
Exemplo do Apache Commons DBCP
Se você observar a classe de fábrica de fonte de dados Java acima, existem dois problemas principais.
- Os métodos da classe de fábrica para criar a fonte de dados MySQL e Oracle estão fortemente acoplados com as respectivas APIs de driver. Se quisermos remover o suporte ao banco de dados Oracle no futuro ou adicionar suporte a algum outro banco de dados, será necessário fazer alterações no código.
- A maior parte do código para obter a fonte de dados MySQL e Oracle é semelhante, a única diferença é a classe de implementação que estamos usando.
A API do Apache Commons DBCP nos ajuda a resolver esses problemas, fornecendo uma implementação de fonte de dados Java que funciona como uma camada de abstração entre nosso programa e diferentes drivers JDBC. A biblioteca Apache DBCP depende da biblioteca Commons Pool, portanto, certifique-se de que ambas estejam no caminho de compilação, conforme mostrado na imagem. Aqui está a classe de fábrica de fonte de dados usando o BasicDataSource, que é uma implementação simples 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 você pode ver, dependendo da entrada do usuário, é criado um DataSource MySQL ou Oracle. Se você estiver suportando apenas um banco de dados na aplicação, então nem mesmo precisa dessa lógica. Basta alterar as propriedades e você pode alternar de um servidor de banco de dados para outro. O ponto chave pelo qual o Apache DBCP fornece abstração é o método setDriverClassName(). Aqui está o programa cliente usando o método de fábrica acima para obter diferentes tipos de conexão.
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 você executa o programa acima, a saída será a mesma do programa anterior. Se você olhar para o Java JDBC DataSource e o uso acima, também pode ser feito com o DriverManager normal. O principal benefício do Java DataSource é quando é usado dentro de um Contexto e com JNDI. Com configurações simples, podemos criar um Pool de Conexões de Banco de Dados que é mantido pelo próprio Contêiner. A maioria dos contêineres de servlet, como Tomcat e JBoss, fornecem sua própria implementação de Java DataSource e tudo o que precisamos é configurá-lo por meio de configurações simples baseadas em XML e, em seguida, usar a pesquisa de contexto JNDI para obter o Java DataSource e trabalhar com ele. Isso nos ajuda cuidando do pool de conexões e gerenciamento do lado da aplicação para o lado do servidor e, assim, nos dando mais tempo para escrever lógica de negócios para a aplicação. No próximo tutorial, aprenderemos como podemos configurar o DataSource no Contêiner Tomcat e usá-lo na Aplicação Web.
Source:
https://www.digitalocean.com/community/tutorials/java-datasource-jdbc-datasource-example