O banco de dados é onde persistimos (armazenamos) os dados que pertencem ao nosso sistema. A maioria dos bancos de dados comerciais hoje em dia é do tipo relacional e derivam de uma estrutura diferente da orientada a objetos.
Para executarmos o manuseio de informações em um banco de dados, devemos fazer uso de sub-linguagens de banco de dados (Database Sub Language – DSL), voltadas para as operações do banco de dados. Geralmente, as sub-linguagens de dados são compostas da combinação de recursos para a definição de dados (Data Definition Language – DDL) e recursos específicos para a manipulação de dados (Data Manipulation Language – DML). A conhecida linguagem de consulta SQL (Structured Query Language) é uma destas linguagens que fornece suporte tanto a DDL como a DML.
Para efetivarmos a conexão de um programa desenvolvido em Java com uma base de dados qualquer, a linguagem Java implementa um conceito de ponte, que implementa todas as funcionalidades que um banco de dados padrão deve nos fornecer.
No desenho acima podemos notar o relacionamento direto da JDBC com o banco de dados, porém este relacionamento depende também da extensão desta ponte que é representada pela implementação JDBC escolhida. Esta implementação depende do banco de dados com o qual queremos nos comunicar e a ela damos o nome de Driver. Para gerenciar estes drivers de conexão, a linguagem Java possui um gerente de drivers chamado java.sql.DriverManager.
O driver do MySQL pode ser adicionado através das Propriedades do Projeto, na aba Biblioteca utilize o botão Adicionar Biblioteca e selecione MySQL JDBC Driver.
caso você queria colocar o driver de outro banco de dados é preciso clicar no botão Adicionar JAR/Pasta e selecionar o arquivo .jar que representa o drive desejado (Obs: no site do fabricante é possível obter este driver).
Para criarmos uma conexão com o banco de dados primeiramente é necessário informarmos qual driver de conexão o DriverManager deve utilizar.
Feita essa disponibilização do arquivo de driver, na programação se faz necessário registrar o driver do banco de dados no sistema. Para isso, basta carregá-lo através do método Class.forName(). Esse método abre uma classe que se registra com o DriverManager.getConnection().
A partir da classe DriverManager, podemos utilizar um método chamado getConnection, com o qual poderemos nos conectar a uma determinada base de dados utilizando uma String padrão de conexão.
Na linha 20 estamos carregando o driver do banco de dados MySQL com.mysql.jdbc.Driver.
Na linha 21, utilizamos o método getConnection da classe DriverManager para criar uma conexão com o banco de dados armazenado em um objeto do tipo java.sql.Connection.
O método getConnection() recebe três parâmetros: 1˚ url de conexão com o banco de dados, 2˚ usuário e 3˚ senha.
Para fazer a conexão com o banco de dados precisamos tratar algumas exceções que podem ocorrer:
Na linha 23, tratamos a exceção java.sql.SQLException que é lançada caso não consiga criar uma conexão com o Banco de Dados.
Na linha 25, tratamos a exceção java.lang.ClassNotFoundException que é lançada caso não consiga carregar o driver do banco de dados.
Depois de utilizar a conexão com o banco de dados é muito importante que liberemos esta conexão, ou seja, precisamos encerrar a conexão com o banco de dados.
Na linha 32 temos o método desconectar que recebe uma Connection como parâmetro, dentro deste método estamos verificando se a conexão com o banco ainda não foi encerrada para depois encerra-la. Quando tentamos encerrar uma conexão com o banco também pode ocorrer alguma exceção para isso na linha 38 estamos tratando caso ocorra alguma java.sql.SQLException.
Quando executamos esta classe, temos a seguinte saída no console:
Consulta de dados
Uma vez conectado, podemos então solicitar a execução de comandos SQL, para que tenhamos acesso a este tipo de chamada ao banco de dados é necessário criarmos um java.sql.Statement.
O Statement é o objeto que servirá de instrumento para a execução de comandos SQL, porém é importante ressaltar que o intuito de uma consulta a um banco de dados é o de receber uma informação, logo, é fundamental que essa resposta seja armazenada em uma estrutura. Para isso podemos utilizar a classe java.sql.ResultSet que deve receber o retorno do método executeQuery que é responsável por executar a consulta.
Exemplo:
Quando executamos essas classe, temos a seguinte saída no console:
Note pelo exemplo anterior que o método responsável por executar a consulta na base de dados foi o executeQuery na linha 24. Observe também a forma como o ResultSet foi percorrido na linha 26.
A classe ResultSet oferece o método next() para percorrer a resposta dada pelo banco de dados. Caso nossa consulta acima lista houvesse retornado 4 linhas, por padrão o ResultSet estaria com seu ponteiro posicionado na posição -1, logo, antes de ler a primeira linha de resposta de sua consulta é necessário a chamada a este método next() para que o ponteiro passe para a primeira posição e possa resgatar as informações desejadas. O método next() retorna true, caso ainda existam novas linhas na resposta e false quando não tem mais registros para percorrer.
É importante ressaltar que apenas um único objeto ResultSet pode ser aberto por vez por Statement ao mesmo tempo.
Para resgatar as informações desejadas, a classe ResultSet oferece métodos do tipo get para todos os tipos de dados primitivos, exceto char. Todos estes métodos devem receber como parâmetro o nome da coluna de resposta, assim como no exemplo anterior, ou o número correspondente a posição da coluna retornada.
Manipulação de dados
Podemos utilizar a classe Statement para guardar (persistir) ou atualizar as informações na base de dados, utilizando o método execute.
Na linha 24, pedimos para o Statement adicionar um novo registro na tabela PESSOA do banco de dados.
Na linha 40, pedimos para o Statement atualizar um registro da tabela PESSOA do banco de dados.
Note que para adicionar ou atualizar as informações no banco de dados, podemos utilizar o método execute.
A classe Statement possui o método execute para adicionar ou atualizar um registro no banco de dados e o método executeUpdate para atualizar as informações no banco de dados, a diferença é que este método retorna um inteiro com a quantidade de registros que foram alterados.
Após a conclusão das operações e leitura ou de manipulação de dados, é importante a chamada ao método close(), tanto da classe Statement como da classe Connection, para que a conexão com o banco de dados seja finalizada.
Relação de algumas bases de dados
Exemplo de aplicação C.R.U.D. (Create, Read, Update, Delete)
Neste exemplo vamos, passo a passo, criar uma aplicação completa de acesso a uma base de dados utilizando JDBC.
Para esta aplicação, iremos criar um sistema de cadastro de veículos. Para tal, criamos a classe Carro:
Agora que já temos modelado a nossa classe principal, devemos definir como nosso programa irá interagir com a base de dados.
Para estabelecermos a conexão com a base de dados de uma maneira mais simples, faremos uso da classe Conexao:
Utilizaremos um padrão de projeto chamado DAO (Data Acess Object). O DAO deve saber buscar os dados do banco e converter em objetos para ser usado pela sua aplicação. Semelhantemente, deve saber como pegar os objetos, converter em instruções SQL e mandar para o banco de dados. Desta forma conseguimos distinguir fortemente a modelagem do sistema da modelagem de dados e das regras de negócio.
Geralmente, temos um DAO para cada objeto do domínio do sistema, ou seja, para nosso exemplo criaremos uma classe CarroDAO com as quatro operações básicas, definidas por seus métodos.
Para que a classe acima não apresente nenhum erro de compilação, é necessário que você acrescente a biblioteca (arquivo .jar) correspondente ao seu banco de dados. Para o nosso exemplo, devemos importar o arquivo correspondente ao banco de dados MySQL.
Observe que nosso método incluir() apenas recebe o objeto Carro a ser inserido na base de dados e internamente faz toda a operação relacionada ao banco de dados. Desta forma, conseguimos isolar toda esta interação com a base de dados do restante do código, tornando-o mais simples de se realizar qualquer tipo de manutenção.
O método consultarPorPlaca recebe apenas a placa de um carro (imagine que esta informação é uma chave da tabela e que não devemos ter mais de um carro com a mesma placa) e que retorna um objeto do tipo Carro com todos os seus atributos devidamente alimentados.
O método alterarPorPlaca() recebe um objeto Carro e a partir de sua placa faz a atualização nos atributos placa e potencia.
O método excluir() recebe o Carro como parâmetro e o apaga da base de dados,
Para testarmos nosso sistema, crie um programa semelhante ao abaixo:
Ao executarmos a classe TestarCarro, temos a seguinte saída no console:
A console fica aguardando até que digitemos alguma opção, primeiro vamos criar um novo carro para isto vamos entrar com a opção I:
Se consultarmos todos os carros cadastrados no banco de dados aparecerá o carro que acabamos de criar:
Agora vamos utilizar a opção C para consultar um carro pela placa abc-1234:
Agora vamos utilizar a opção A para alterar as informações de modelo e potencia:
Se consultarmos todos os carros cadastrados no banco de dados aparecerá o carro que acabamos de alterar:
Agora vamos utilizar a opção E para apagar o carro do banco de dados.
Se consultarmos todos os carros, não teremos nenhum registro no banco de dados: