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)