Acessando bancos de dados com o JDBC Notas de Aula: Java Como Programar, 8/E Prof. Anselmo Cardoso Paiva Prof. Geraldo Braz Junior Introdução Um banco de dados é uma coleção organizada de dados. Um sistema de gerenciamento de bancos de dados - SGBD fornece mecanismos para armazenar, organizar, recuperar e modificar dados para muitos usuários. SQL é a linguagem padrão internacional utilizada quase universalmente com bancos de dados relacionais para realizar consultas e para manipular dados. Microsoft SQL Server Oracle Sybase IBM DB2 Informix PostgreSQL MySQL O JDK vem agora com um RDBMS puro Java chamado Java DB — a versão da Sun para o Apache Derby. 2 Introdução Os programas Java comunicam-se com bancos de dados e manipulam seus dados utilizando a Java Database Connectivity (JDBC™) API. Um driver JDBC permite aos aplicativos Java conectar-se a um banco de dados em um DBMS particular e permite a você manipular esse banco de dados utilizando o JDBC API. 3 Banco de dados books O banco de dados consiste em três tabelas: Authors AuthorISBN Titles. Chave estrangeira — uma coluna em uma tabela que corresponde à coluna de chave primária em outra tabela. A chave estrangeira ajuda a manter a Regra de Integridade Referencial — cada valor de chave estrangeira deve aparecer como outro valor de chave primária da tabela. Há um relacionamento um para muitos entre uma chave primária e sua chave estrangeira correspondente. 4 Modelo ER 5 SQL 6 Manipulando bancos de dados com o JDBC O programa ilustra a conexão com o banco de dados, consultando o banco de dados e processando o resultado. 7 8 9 Resultado 10 Consultando e conectando-se a um banco de dados O URL do banco de dados identifica o nome do banco de dados ao qual se conectar, bem como informações sobre o protocolo utilizado pelo driver JDBC. O JDBC 4.0 suporta a descoberta de driver automática. Para assegurar que o programa pode localizar a classe de driver do banco de dados, você deve incluir a localização da classe no classpath do programa ao executar o programa. Para o MySQL inclua o arquivo mysql-connectorjava-5.1.7-bin.jar no classpath do programa, como em: java -classpath .;c:\mysql-connector-java5.1.7\mysql-connector-java-5.1.7bin.jar DisplayAuthors 11 Connection Um objeto que implementa a interface Connection gerencia a conexão entre o programa Java e o banco de dados. Os objetos Connection permitem que os programas criem instruções SQL que manipulam banco de dados. O método DriverManager static getConnection tenta se conectar ao banco de dados especificado pelo seu URL. Três argumentos: uma String que especifica o URL do banco de dados. uma String que especifica o nome de usuário uma String que especifica a senha do usuário. 12 URL de conexão O URL jdbc:mysql://localhost/books especifica: o protocolo de comunicação (jdbc). o subprotocolo para comunicação (mysql). a localização do banco de dados (//localhost/books, onde localhost é o host executando o servidor MySQL ebooks é o nome do banco de dados). O subprotocolo mysql indica que o programa utiliza um subprotocolo específico ao MySQL para conectar-se ao banco de dados MySQL. 13 Por SGDB... 14 Statement e ResultSet O método Connection.createStatement obtém um objeto que implementa a interface Statement (pacote java.sql). Usado para enviar instruções SQL para o banco de dados. O método executeQuery do objeto Statement envia uma consulta para o banco de dados. Retorna um objeto que implementa a interface ResultSet e contém os resultados da consulta. Os métodos ResultSet permitem que programa manipule o resultado da consulta. O ResultSetMetaData de um ResultSet descreve o conteúdo do ResultSet. Pode ser usado programaticamente para obter informações sobre nomes de coluna e tipos do ResultSet. O método ResultSetMetaData getColumnCount recupera o número de colunas no ResultSet. 15 ResultSet A primeira chamada para o método ResultSet next posiciona o cursor ResultSet para a primeira linha. Retorna o valor boolean true se for capaz de se posicionar na próxima linha; caso contrário, o método retorna false. O método ResultSetMetaData getColumnType retorna um inteiro constante da classe Types (pacote java.sql) que indica o tipo de uma coluna especificada. Os métodos ResultSet get em geral recebem como um argumento um número de coluna (como um int) ou um nome de coluna (como uma String) indicando que valor da coluna obter. O método ResultSet getObject retorna um valor de coluna como um Object. 16 Dicas 17 ResultSetMetaData O método ResultSetMetaData getColumnClassName obtém o nome de classe completamente qualificado da coluna especificada. getColumnCount obtém o número de colunas no ResultSet. getColumnName obtém o nome da coluna no ResultSet. absolute posiciona o cursor ResultSet em uma linha específica. last posiciona o cursor ResultSet na última linha no ResultSet. getRow obtém o número da linha atual no ResultSet. 20 Interface RowSet A interface RowSet fornece vários métodos set que permite especificar as propriedades necessárias para estabelecer uma conexão e criar uma Statement. RowSet também fornece vários métodos get que retornam essas propriedades. Dois tipos de objetos RowSet — conectado e desconectado. Um objeto RowSet conectado conecta-se ao banco de dados uma vez e permanece conectado enquanto o objeto estiver em uso. Um objeto RowSet desconectado conecta-se ao banco de dados, executa uma consulta para recuperar os dados do banco de dados e depois fecha a conexão. Um programa pode alterar os dados em um RowSet desconectado enquanto ele estiver desconectado. Dados modificados podem ser atualizados no banco de dados depois que um RowSet desconectado restabelecer a conexão com o banco de dados. 21 Interface RowSet O pacote javax.sql.rowset contém duas subinterfaces de RowSet — JdbcRowSet e CachedRowSet. JdbcRowSet, um RowSet conectado, atua como um empacotador em torno de um objeto ResultSet e permite aos programadores percorrer e atualizar as linhas no ResultSet. Um objeto JdbcRowSet é rolável e atualizável por padrão. CachedRowSet, um RowSet desconectado, armazena os dados em cache de um ResultSet na memória e desconecta-se do banco de dados. Um objeto CachedRowSet é rolável e atualizável por padrão. Também serializável, então ele pode ser passado entre aplicativos Java por uma rede, como a Internet. 22 Exemplo RowSet 23 24 25 26 RowSet Implementação O pacote com.sun.rowset fornece implementações de referência da Sun para as interfaces no pacote javax.sql.rowset. A implementação de referência da Sun da interface JdbcRowSet é JdbcRowSetImpl. Alguns bancos de dados podem fornecer suas próprias implementações RowSet. O método JdbcRowSet setUrl especifica o URL do banco de dados. O método JdbcRowSet setUsername especifica o nome de usuário. O método JdbcRowSet setPassword especifica a senha. O método Jdbc-RowSet setCommand especifica a consulta SQL que será usada para preeencher o RowSet. 27 RowSet Implementação O método JdbcRowSet execute executa a consulta SQL. O método execute realiza quatro ações: Estabelece uma Connection com o banco de dados. Prepara a consulta Statement. Executa a consulta. Armazena o ResultSet retornado pela consulta. As consultas Connection, Statement e ResultSet são encapsuladas no objeto JdbcRowSet. O método JdbcRowSet close fecha as consultas ResultSet, Statement e Connection do RowSet encapsulado. 28 PreparedStatements A interface PreparedStatement permite criar instruções SQL compiladas que executam mais eficientemente do que os objetos Statement. Pode também especificar parâmetros, tornando-os mais flexíveis do que as Statements. Os programas podem executar a mesma consulta repetidamente com valores de parâmetro diferentes. 29 PreparedStatements Para localizar todos os títulos de livro de um autor com um sobrenome e um nome específicos: PreparedStatement authorBooks = connection.prepareStatement( "SELECT LastName, FirstName, Title " + "FROM Authors INNER JOIN AuthorISBN " + "ON Authors.AuthorID=AuthorISBN.AuthorID " + "INNER JOIN Titles " + "ON AuthorISBN.ISBN=Titles.ISBN " + "WHERE LastName = ? AND FirstName = ?" ); Os dois pontos de interrogação (?) são um espaço reservado para valores que serão passados como parte da consulta ao banco de dados. 30 PreparedStatements Antes de executar uma PreparedStatement, o programa deve especificar os valores de parâmetro utilizando os métodos set da interface PreparedStatement. Para a consulta anterior, ambos os parâmetros são strings que podem ser configuradas com o método PreparedStatement setString como mostrado a seguir: authorBooks.setString( 1, "Deitel" ); authorBooks.setString( 2, "Paul" ); Os números de parâmetro são contados a partir de 1, iniciando com o primeiro ponto de interrogação (?). A interface PreparedStatement fornece métodos set para cada tipo SQL suportado. 31 PreparedStatements Invoque o método Connection prepareStatement para criar uma PreparedStatement. Chamar o método PreparedStatement executeQuery retorna um ResultSet contendo as linhas que correspondem à consulta. O método PreparedStatement executeUpdate executa a instrução SQL que modifica o banco de dados. 32 33 34 35 Procedures armazenadas Muitos sistemas de gerenciamento de bancos de dados podem armazenar 36 instruções de SQL individuais ou conjuntos de instruções de SQL em um banco de dados, de modo que os programas que acessam esse banco de dados possam invocá-las. Tais coleções identificadas de instruções SQL são chamadas de procedures armazenadas. O JDBC permite aos programas invocar procedures armazenadas usando objetos que implementam a interface CallableStatement. Além disso, CallableStatements podem especificar parâmetros de saída em que uma procedure armazenada pode colocar valores de retorno. A interface também inclui métodos para obter os valores de parâmetros de saída retornados de uma procedure armazenada. Para aprender mais sobre CallableStatements, visite java.sun.com/javase/6/docs/technotes/guides/jdbc /getstart/ callablestatement.html#999652 Procedures armazenadas 37 Processamento de transações Muitos aplicativos do banco de dados impõem garantias de que 38 uma série de inserções, atualizações e exclusões no banco de dados executem corretamente antes de os aplicativos continuarem o processamento da próxima operação de banco de dados. O processamento de transação permite que um programa que interage com um banco de dados trate uma operação de banco de dados (ou conjunto de operações) como uma operação única. Essa operação também é conhecida como operação atômica ou transação. No fim de uma transação, pode-se tomar a decisão de confirmar a transação ou reverter a transação. Confirmar a transação finaliza a(s) operação(ões) de banco de dados. A reversão da transação deixa o banco de dados no seu estado anterior à operação de banco de dados. Processamento de transações O método Connection setAutoCommit especifica se cada instrução SQL é confirmada depois de ser completada (um argumento true) ou se várias instruções SQL devem ser agrupadas como uma transação (um argumento false). Se o argumento para setAutoCommit for false, o programa deve seguir a última instrução SQL na transação com uma chamada para o método Connection commit ou método Connection rollback. A interface Connection também fornece o método getAutoCommit para determinar o estado autocommit para Connection. 39