Programação Orientada a Objetos (DPADF 0063) Aula 9 JDBC (Java Database Connectivity) Universidade Federal de Santa Maria Colégio Agrícola de Frederico Westphalen Curso Superior de Tecnologia em Sistemas para Internet Prof. Bruno B. Boniati www.cafw.ufsm.br/~bruno
Conexão e manipulação de bases de dados relacionais
Conceitos Banco de dados Coleção organizada de dados; SGBD ou DBMS Sistema Gerenciador de Banco de dados (Database Management System) SQL (Structured Query Language) Linguagem padrão para definição, consulta e manipulação de dados em SGBDs relacionais.
Desenvolvimento de aplicações em camadas Com a utilização de um SGBD o desenvolvimento do software passa a ser dividido em camadas lógicas... Camada de lógica Camada de dados Camada de dados Fisicamente em um único computador Camada de lógica Fisicamente em computadores diferentes
Java e Banco de Dados Como temos camadas de software independentes, precisamos de um DRIVER para intermediar a comunicação entre elas; Um driver JDBC permite aos aplicativos Java conectar-se a um banco de dados em um SGBD particular e manipular seus dados utilizando uma API. Drivers JDBC normalmente são fornecidos pelos fabricantes ou comunidades de usuários (http://devapp.sun.com/product/jdbc/drivers)
Interfaces e Classes JDBC Para conectar a um banco de dados, recuperar e manipular informações, precisamos de pelo menos três objetos: Connection Banco de Dados ResultSet Statement
Conectando um banco de dados Connection Gerencia a conexão entre o programa Java e o banco de dados. //Url de conexão String db_url = "jdbc:mysql://localhost/books"; //Carrega a o driver apropriado Class.forName( "com.mysql.jdbc.driver" ) //Declara a conexão Connection con = null; //Obtém uma instância para o objeto que representa a conexão con = DriverManager.getConnection(db_url, "user", "senha");
Class.forName( "com.mysql.jdbc.driver" ) x import com.mysql.jdbc.driver; Driver driver = new Driver(); Ambos os códigos acima fazem a mesma coisa... No primeiro caso o método forname da classe Class tenta carregar dinâmicamente a classe passada como parâmetro (com.mysql.jdbc.driver) No segundo caso a classe é instanciada de forma estática (fixa no código). Qual das duas alternativas é melhor? No primeiro caso, se o banco de dados for alterado basta alterar a string que representa o driver, no segundo caso todo o código precisa ser alterado.
Drivers JDBC SGBD Formato da URL de conexão jdbc:oracle:thin:@host:porta:nomebd (Porta padrão 1521) jdbc:postgresql://host:porta/nomebd (Porta padrão 5432) jdbc:db2://host:porta/nomebd (Porta padrão 446, 6789, ou 50000) jdbc:sqlserver://host:porta;databasename=nomebd (Porta padrão 1433) jdbc:mysql://host:porta/nomebd (Porta padrão 3306) jdbc:firebirdsql:host/porta:caminhoarquivo.fdb (Porta padrão 3050) jdbc:sqlite:caminhoarquivo jdbc:odbc:nomebd
Executando instruções SQL Statement Executa instruções SQL em uma base de dados //String para armazenar o comando SQL String sql_ins = "insert into alunos (id, nome) values(1, 'Ana')"; //Cria o objeto a partir da conexão Statement stmt = con.createstatement(); //Executa o comando de atualização pré-definido int linhas_afetadas = stmt.executeupdate(sql_ins); //Retorna o número de linhas afetadas (insert, delete, update) //ou zero (comandos como grant, alter, create).
Executando instruções SQL PreparedStatement Instruções pré-compiladas Executa instruções SQL pré-compiladas em uma base de dados //String para armazenar o comando SQL genérico String sql_ins = "insert into alunos (id, nome) values(?,?)"; //Cria o objeto a partir da conexão PreparedStatement stmtalunos = con.preparestatement(sql_ins); //Ajusta os parâmetros do comando SQL stmtalunos.setinteger(1, 10); //parâmetro 1 = 10 (id) stmtalunos.setstring(2, "Ana"); //parâmetro 2 = Ana (Nome) //Executa o comando de atualização pré-compilado int linhas_afetadas = stmtalunos.executeupdate();
Recuperando dados ResultSet Recupera um conjunto de dados de um comando de seleção //String para armazenar o comando SQL genérico String sql_sel = "select id, nome from alunos"; //Cria um objeto Statement a partir da conexão para enviar o SQL Statement stmt = con.createstatement(); //Declara o conjunto de dados ResultSet dados; //Executa a instrução de consulta e guarda o resultado dados = stmt.executequery(sql_sel);
Utilizando de dados de um resultado ResultSet TYPE_SCROLL_INSENSITIVE Permite navegar para frente e para traz no ResultSet CONCUR_READ_ONLY Impede que os dados ResultSet sejam atualizados no BD Statement stmt = con.createstatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); ResultSet dados = stmt.executequery("select id, nome from alunos"); //Percorre o ResultSet listando os dados da coluna 2 while ( dados.next() ) { //Enquanto houver um próximo registro String nomealuno = dados.getstring(2); System.out.println(nomeAluno); } dados.first(); //posiciona no primeiro registro do ResultSet //Percorre o ResultSet listando os dados da coluna "NOME_ALUNO" while ( dados.next() ) { String nomealuno = dados.getstring("nome_aluno"); System.out.println(nomeAluno); }
Obtendo metadados (dados sobre os dados) ResultSetMetaData ResultSet dados = stmt.executequery("select id, nome from alunos"); ResultSetMetaData metadados = dados.getmetadata(); int numcolunas = metadados.getcolumncount(); //Percorre e lista as colunas resultantes da consulta for (int i = 1; i<=numcolunas; i++) { String nomecoluna = metadados.getcolumnname(i); String tipocoluna = metadados.getcolumntypename(i); System.out.println(nomeColuna + " é do tipo " + tipocoluna); }
Exercícios para fixação
Construtor SQL... Que tal implementar uma ferramenta para execução interativa de SQL. O construtor SQL deve permitir: Conectar; Desconectar; Abrir consultas SQL; Executar comandos SQL (create, delete, insert, update)