segunda-feira, 7 de junho de 2010

Acessando banco de dados MySQL com JDBC

Olá povo,

Acabei de terminar de ministrar uma turma de Java Programmer na Especializa Treinamentos, e escutei a reclamação de um dos alunos dizendo que eu só postava assuntos sobre Android. Então resolví dá um espaço pro Java básico aqui no blog. Vou começar mostrando como acessar um banco de dados MySQL com a JDBC API.

Apesar dos desenvolvedores contarem com frameworks JPA como Hibernate, que facilitam o acesso de aplicações Java a SGDB (Sistemas Gerenciadores de Banco de Dados), é bom saber o que acontece por trás dos bastidores desses frameworks.

Normalmente, isola-se a parte de acesso aos dados das telas da aplicação através de uma classe que recebe objetos de negócio e as persiste no banco de dados para posterior recuperação. Esse processo é o que chamamos de "mapeamento objeto-relacional".

Apresentaremos a classe realiza as operações de cadastrar, recuperar, atualizar e excluir registros em um banco de dados. Essa classe não se preocupa com qual interface gráfica o desenvolvedor está trabalhando: swing, jsp, applet, etc.

Mãos a obra! A API JDBC provê um conjunto de interfaces que permite um acesso uniforme a banco de dados em Java, deixando a cargo de cada fabricante implementar o acesso ao seu banco de dados da maneira que achar mais conveniente. Essas interfaces estão no pacote java.sql.*. Dessa forma, a primeira coisa que precisamo é baixar o banco de dados do banco de dados que você utilizará. Para baixar o Driver para MySQL clique aqui.

Uma vez de posse do seu JAR, adicione ao classpath do seu projeto e escreva o código abaixo:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class RepositorioPessoaDB  {

// Método que estabele a conexão com o banco de dados
private Connection getConnection() throws
  ClassNotFoundException, InstantiationException,
  IllegalAccessException, SQLException {
  
 String userName = "root";
 String password = "root";
 String url = "jdbc:mysql://localhost/pessoasDB";
 String driver = "com.mysql.jdbc.Driver";

 // Registra o driver do banco de dados
 Class.forName(driver).newInstance();

 // Estabele a conexão passando url, usuário e senha
 Connection conn = DriverManager.getConnection(
   url, userName, password);

 return conn;
}

// Método que inclui um objeto pessoa
// no banco de dados
public void incluir(Pessoa pessoa) {
 Connection conn = null;
 try {
   // Obtém a conexão
   conn = getConnection();

   // Declara e prepara a instrução
   // pra ser executada no BD
   PreparedStatement s;
   s = conn.prepareStatement(
     "INSERT INTO Pessoa (nome, telefone)"+
     "VALUES(?, ?)");

   // Cada interrogação será substituída
   // pelos atributos do objeto
   s.setString(1,  pessoa.getNome());
   s.setString(2,  pessoa.getTelefone());

   int count = s.executeUpdate();
   s.close();

   System.out.println(count +
     " Linhas foram inseridas");

 } catch (Exception e) {
   throw new RuntimeException(
     "Falha ao inserir registro.");

 } finally {
   // Fecha a conexão
   if (conn != null) {
     try {
       conn.close();
       System.out.println("Conexão encerrada.");
     } catch (Exception e) {}
   }
 }
}

// Método que exclui uma pessoa do
// banco de dados baseado no código
public void excluir(int codigoPessoa) {
 Connection conn = null;
 try {
   conn = getConnection();
     
   PreparedStatement s;
   s = conn.prepareStatement(
     "DELETE FROM Pessoa WHERE codigo = ?");
   s.setInt(1, codigoPessoa);

   int count = s.executeUpdate();
   s.close();

   System.out.println(
     count + " linhas foram excluídas");
  
 } catch (Exception e) {
   throw new RuntimeException(
     "Falha ao excluir registro.");

 } finally {
   if (conn != null) {
     try {
       conn.close();
       System.out.println("Conexão encerrada.");
     } catch (Exception e) {}
   }
 }
}

// Método que atualiza as informações
// de uma pessoa no banco
public void alterar(Pessoa pessoa) {
 Connection conn = null;
 try {
   conn = getConnection();

   PreparedStatement s;
   s = conn.prepareStatement(
     "UPDATE Pessoa SET nome = ?, telefone = ? "+
     "WHERE codigo = ?");

   s.setString(1, pessoa.getNome());
   s.setString(2, pessoa.getTelefone());
   s.setInt(3, pessoa.getCodigo());

   int count = s.executeUpdate();
   s.close();
   System.out.println(
     count + " linhas atualizadas");

 } catch (Exception e) {
   throw new RuntimeException(
     "Falha ao alterar");

 } finally {
   if (conn != null) {
     try {
       conn.close();
       System.out.println(
         "Conexão com o banco foi finalizada.");
     } catch (Exception e) { }
   }
 }
}

// Método que retorna uma lista de objetos
// pessoa vindos do banco de dados
public List<Pessoa> pesquisar(String nome) {

 ArrayList<Pessoa> lista =
   new ArrayList<Pessoa>();

 Connection conn = null;
 try {
   conn = getConnection();

   System.out.println("Conexão estabelecida!");
   PreparedStatement s = conn.prepareStatement(
     "SELECT * FROM PessoaWHERE nome LIKE ?");
   s.setString(1, "%"+ nome +"%");
   s.executeQuery();

   // Resultset representa o resultado da
   // busca no banco de dados
   ResultSet rs = s.getResultSet();

   // Percorrendo o resultado da busca
   int count = 0;
   while (rs.next()) {
     // Criando e preenchendo objeto pessoa
     Pessoa pessoa = new Pessoa();
     pessoa.setCodigo( rs.getInt("codigo") );
     pessoa.setNome( rs.getString("nome"));
     pessoa.setTelefone( rs.getString("telefone"));

     // adicionando objeto à lista a ser retornada
     lista.add(pessoa);

     ++count;
   }
   rs.close();
   s.close();

   System.out.println(
     count + " linhas recuperadas");

 } catch (Exception e) {
   System.err.println("Falha ao conectar.");
   e.printStackTrace();

 } finally {
   if (conn != null) {
     try {
       conn.close();
       System.out.println("Conexão finalizada");
     } catch (Exception e) {}
   }
 }

 return lista;
}
}


A entidade de negócio que utilizamos é a classe Pessoa que tem os seguintes atributos: código, nome e telefone. Ela é uma classe simples com GETs e SETs, por isso não mostraremos ela aqui.

O código está comentado, mas a explicação do código é bem simples. Para todas as operações uma conexão é estabelecida para daí ser feita a solicitação para o banco. Para as operações de incluir, alterar e excluir é feita uma chamada para o método executeUpdate() em um objeto do tipo PreparedStatement. Esse objeto representa a solicitação que é feita ao banco de dados. Já para a busca de registros é utilizado o método executeQuery(). Após a busca, obtemos um objeto ResultSet que armazena as informações do banco de dados. Um vez estando com o resultado da busca, preenchemos uma lista de objetos Pessoa.

Vejam que com essa classe isolamos o acesso ao banco de dados em uma única classe. Cabe a você agora implementar a interface gráfica de sua preferência.

Qualquer dúvida, mandem seus comentários.

4br4ç05,
nglauber

4 comentários:

Anônimo disse...

Boa tarde Glauber...fiz exatamente oq tem ai, porem no momento que é para conectar aparece o seguinte erro:Could not find class 'javax.naming.StringRefAddr', referenced from method com.mysql.jdbc.ConnectionPropertiesImpl$ConnectionProperty.storeTo

Ja procurei em varios tópicos e n encotrei a solução você poderia me ajudar?

Abraços!

Nelson Glauber disse...

Oi Anônimo,

O código acima deveria funcionar em PCs, mas se você estiver querendo fazer isso no Android, provavelmente não funcionará. Isso porque, até o momento eu não conheço Driver JDBC MySQL para Android.

4br4ç05,
nglauber

Frederico Brigatte disse...

Como ficaria hoje para Android?

Nelson Glauber disse...

Oi Frederico,

A ideia é que o Android não acesse diretamente um banco MySQL. Normalmente, ele acessaria um WebService e este acessaria o MySQL.

4br4ç05,
nglauber