Objetivo da JDBC Vantagens Visão geral do acesso a SGBDs ◆ ◆ ◆ Drivers JDBC Conexão com o BD Envio de comandos e recebimento de resultados Informações sobre o tipo da tabela Transações ■ ■ ■ Doutorando na USP/PCS Laboratório de Técnicas Inteligentes [email protected] Introdução ■ Jomi Fred Hübner ■ ■ Prof. na Universidade Regional de Blumenau Departamento de Sistemas e Computação ■ JDBC é uma API (Application Program Interface) para acesso a SGBD (Sistemas Gerenciadores de Banco de Dados) relacionais por meio de comandos SQL (Structured Query Language) ■ ■ ■ Programa Java API JDBC ■ a API para programação do sistema é a mesma para qualquer SGBD, não há necessidade de se desenvolver aplicações voltadas (e amarradas) para um BD específico permite a construção de páginas WWW que acessam BD pois dispensa a configuração da máquina cliente mantém a independência de plataforma da linguagem Java “A aplicação roda em qualquer sistema operacional acessando qualquer BD” !? SGBD ■ A API encapsula ◆ ◆ ◆ ■ o estabelecimento da conexão com o BD o envio de comandos SQL o processamento dos resultados ◆ Exemplo Connection con = DriverManager.getConnection ( "jdbc:odbc:sample", "login", "password"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery( "SELECT a, b, c FROM Table1"); while (rs.next()) { int x = getInt("a"); String s = getString("b"); float f = getFloat("c"); } Os drivers ODBC são escritos em C, o que limita a portabilidade e auto-instalação dos programas Java o ODBC tem que ser instalado e configurado na máquina do cliente ✦ ■ ODBC tem o mesmo propósito e existe para várias plataformas, por que não usar ODBC? ◆ ■ imagine instalar e configurar o ODBC em 40.000.000 computadores da Internet! Entretanto, bancos de dados que utilizam ODBC podem ser utilizados em aplicações Java via a ponte JDBC-ODBC. 1 1 Arquitetura de duas camadas: cliente/servidor cliente servidor driver oracle TDS SQLNet Oracle ODBC SyBase Access ! " ◆ ◆ # $ RMI, CORBA, Socket, JDBC independente, ... Dispensa o cliente de conhecer o protocolo do SGBD e, consequentemente, carregar seu driver Melhora o tempo de resposta em aplicações na Internet ■ servidor Java JDBC Dirvers Oracle SyBase outros ◆ ◆ # $ # Class.forName ("oracle.jdbc.driver.OracleDriver"); Class.forName ("sun.jdbc.odbc.JdbcOdbcDriver"); a JVM deve poder encontrar estas classes ■ a comunicação entre o cliente e a SGBD da-se no protocolo do SGBD, contudo, como o driver é escrito em Java, dispensa a instalação/configuração do driver no cliente. Vários drivers podem ser carregados com o método Class.forName. Por exemplo: ■ a API JDBC chama procedimentos do driver nativo do SGBD instalado na máquina local Driver com protocolo proprietário escrito em Java ✦ ◆ Ponte com ODBC Acesso ao driver nativo ✦ ◆ aplicação Java ou applet servidor middleware – o driver JDBC deve ser “carregado” no cliente – se a aplicação for um applet, o SGBD deve estar na mesma máquina que o servidor Web api JDBC driver ponte sybase ODBC ■ Desvantagens aplicação Java cliente ■ ◆ Driver independente de SGBD ◆ para aplicações, a variável de ambiente CLASSPATH deve incluir os drivers para applets, o parâmetro archive deve apontar para o driver. ✦ utilizado pelo cliente para conectar-se com o middleware os dois primeiros tipos são recomendados para Intranets, pois exigem configuração da máquina cliente os outros dois podem ser utilizados na Internet, preferencialmente o último, que tem menor tempo de download. ■ ■ % ■ & A abertura da conexão é feita pelo método getConnection, que recebe uma URL (Universal Resource Location) como argumento ◆ O DriverManager tenta conectar com o primeiro driver carregado, se não consegue, tenta o driver seguinte ◆ JDBC URLs são formadas por: um protocolo (normalmente jdbc), um sub-protocolo (normalmente é o tipo de driver) e informações para o SGBD. ◆ ponte ODBC Connection conn = DriverManager.getConnection ("jdbc:odbc:Sample", "admin", "temp"); // o serviço Sample tem que estar configurado no // ODBC manager da máquina ◆ protocolo nativo com driver Java ' ■ ■ ( # ) * O envio de um comando SQL é feito por meio de um Statement Um statement pode ser criado a partir de três classes: ◆ ◆ ◆ Statement ✦ é utilizado para enviar comandos SQL simples PreparedStatement ✦ o comando SQL é pré-compilado e utilizado posteriormente, sendo mais eficiente nos casos onde o mesmo comando é utilizado várias vezes CallableStatement ✦ utilizado para chamar procedimentos SQL armazenados no BD Connection conn = DriverManager.getConnection ("jdbc:oracle:thin:@mariscal:1521:ORAP", "scott", "tiger"); 2 2 , + Statement Um objeto desta classe é criado pelo envio da mensagem createStatement à conexão com o BD ■ A classe ResultSet oferece à aplicação a tabela resultante de um Select e ◆ mantém um cursor posicionado em uma linha da tabela. Inicialmente este cursor está antes da primeira linha e a mensagem next() movimenta o cursos para frente. ◆ Permite à aplicação pegar os dados das colunas da linha corrente através de mensagem getXXX(<cloluna>). ✦ XXX é o tipo da coluna ✦ <coluna> é o nome da coluna ou sua posição (a partir de 1) ■ Class.forName ("sun.jdbc.odbc.JdbcOdbcDriver"); Connection conn = DriverManager.getConnection ("jdbc:odbc:Sample", "admin", "temp"); Statement stmt = conn.createStatement (); Execução de comandos SQL ■ método executeQuery: usado para comandos SQL que retornam uma tabela ◆ ResultSet rs = stmt.executeQuery("select * from EMP"); & ( ResultSet rs = stmt.executeQuery( "select a, b, c from table1"); while (rs.next()) { int x = rs.getInt("a"); String s = rs.getString(2); float f = rs.getFloat("c"); método executeUpdate: usado para executar comandos SQL que alteram a tabela, retorna o número de colunas alteradas ◆ import java.sql.*; class ExAcessoOracleApp { public static void main (String args []) throws SQLException, ClassNotFoundException { Class.forName ("oracle.jdbc.driver.OracleDriver"); Permite obter informações sobre o tipo de tabela que resultou o select. ◆ Quais os nomes e os tipos das colunas ◆ Se a coluna do tipo é numérico com sinal ◆ Se a coluna pode ser alterada ◆ .... ■ Connection conn = DriverManager.getConnection( "jdbc:oracle:thin:@inf.furb.rct-sc.br:1521:ORAP", "scott", "tiger"); ResultSet result = stmt.executeQuery( "SELECT * FROM TabEx ORDER BY id DESC"); Statement stmt = conn.createStatement(); ResultSetMetaData meta = result.getMetaData(); ResultSet rset = stmt.executeQuery ( "select ENAME from EMP"); int columns = meta.getColumnCount(); for (int i=1;i<=columns;i++) { while (rset.next ()) System.out.println (rset.getString (1)); } System.out.println (meta.getColumnLabel(i) + "\t" + meta.getColumnTypeName(i)); } } ■ , Exemplo de criação e inserção em uma tabela utilizando a mensagem executeUpdate ao Statement. " ■ st.executeUpdate( "create table Alunos ( nome varchar (32), idade integer);"); st.executeUpdate("insert into Alunos values ('Jonas',18);"); st.executeUpdate(”update Alunos set idade = 18 where idade = 20"); - Uma transação é um conjunto de Statements que são validados no BD com commit ou cancelados com rollbabk ◆ Statement st = con.createStatement(); Por default, todos os comandos no JDBC são auto-commit. con.setAutoCommit(false); // muda o default Statement s = con.createStatement(); try { s.executeUpdate("SQL statement 1"); s.executeUpdate("SQL statement 2"); con.commit(); // valida os 2 updates } catch (Exception e) { con.rollback(); // senão, desfaz os updates } con.close(); 3 3