Vous êtes sur la page 1sur 8

Acessando banco de dados em Java (PARTE 1)

Publicado por daltoncamargo em 17/08/2009 - 722.728 visualizaes comentrios: 34 Uma funcionalidade essencial em qualquer sistema a habilidade para comunicar-se com um repositrio de dados. Podemos definir repositrio de dados de vrias maneiras, por exemplo, como um pool de objetos de negcio num ORB ou um banco de dados. Bancos de dados constituem o tipo mais comum de repositrio. Java dispe de uma API para acessar repositrios de dados: a Java DataBase Connectivity API ou JDBC API. A JDBC implementa em Java a funcionalidade definida pelo padro SQL Call Level Interface ou SQLCLI. Um outro exemplo de API que implementa o SQL Call Level Interface o popularssimo ODBC das plataformas Wintel. A maioria dos fornecedores de bancos de dados oferece uma implementao particular de SQLCLI. A vantagem de JDBC a portabilidade da aplicao cliente, inerente da linguagem Java. A especificao corrente da JDBC API a 2.1. A JDBC compreende uma especificao para ambos: os desenvolvedores de drivers JDBC e os desenvolvedores de aplicaes clientes que precisem acessar bancos de dados em Java. Estaremos dando uma olhada no desenvolvimento de aplicaes em Java, ento, uma boa idia comear com o suporte de dados. Existem 4 tipos de diferentes de drivers JDBC (para uma lista de fornecedores por especificao e tipo, vide http://www.javasoft.com/products/jdbc/drivers.html ): - Uma vez que ODBC uma especificao padro do mundo Wintel, o tipo 1 um driver de ponte entre Java e ODBC. O driver de ponte mais conhecido o fornecido pela Sun o JDBCODBC bridge. Este tipo de driver no portvel, pois depende de chamadas a funes de ODBC implementadas em linguagem C e compiladas para Wintel, ou outra plataforma ODBC compatvel, as chamadas funes nativas. - O driver tipo 2 implementado parcialmente em Java e parcialmente atravs de funes nativas que implementam alguma API especfica do fornecedor de banco de dados. Este tipo faz o que se chama de wrap-out, ou seja, prov uma interface Java para uma API nativa noJava. - O tipo 3 um driver totalmente Java que se comunica com algum tipo de middleware que ento se comunica com o banco de dados - O tipo 4 um driver totalmente Java que vai diretamente ao banco de dados. Numa prxima parte veremos ainda um driver gratuito que permite acessar bancos de dados que ofeream suporte apenas ao Bridge (tipo 1) via rede. Veremos a seguir como acessar um banco de dados atravs de JDBC. Nosso cenrio bsico uma pequena aplicao de controle dos meus CDs (clssica !) implementada em algum xBase compatvel. Em prximos exemplos iremos utilizar outros bancos de dados. Para utilizarmos a JDBC num programa em Java, precisamos declarar o pacote que contm a JDBC API: Acessando bancos de dados em JDBC

1. import java.sql.*;

A primeira coisa a fazer estabelecer uma conexo com o banco de dados. Fazemos isso em dois passos: primeiro carregamos o driver para o banco de dados na JVM da aplicao (1). Uma vez carregado, o driver se registra para o DriverManager e est disponvel para a aplicao. Utilizamos ento a classe DriverManager para abrir uma conexo com o banco de dados (2). A interface Connection designa um objeto, no caso con, para receber a conexo estabelecida:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.

try //A captura de excees SQLException em Java obrigatria para usarmos JDBC. { // Este um dos meios para registrar um driver Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").getInstance(); // Registrado o driver, vamos estabelecer uma conexo Connection con = DriverManager.getConnection("jdbc:odbc:meusCdsDb","con ta","senha"); } catch(SQLException e) { // se houve algum erro, uma exceo gerada para informar o erro e.printStackTrace(); //vejamos que erro foi gerado e quem o gerou }

Estabelecida a conexo, podemos executar comandos SQL para o banco de dados. Vejamos como realizar uma consulta sobre o ttulo, numero de faixas e o artista de cada CD no banco de dados. Podemos usar 3 interfaces para executar comandos SQL no banco de dados. A primeira delas a interface Statement, que permite a execuo dos comandos fundamentais de SQL (SELECT, INSERT, UPDATE ou DELETE). A interface PreparedStatement nos permite usufruir de SQL armazenado ou pr-compilado no banco, quando o banco de dados suportar este recurso. A terceira interface CallableStatement, e permite executar procedimentos e funes armazenados no banco quando o banco suportar este recurso. Vejamos como utilizar a interface Statement. Nos prximos artigos sobre JDBC iremos investigar as outras.

1. 2. 3. 4. 5. 6.

// Aps estabelecermos a conexo com o banco de dados // Utilizamos o mtodo createStatement de con para criar o Statement Statement stm = con.createStatement(); // Vamos executar o seguinte comando SQL : String SQL = "Select titulo, autor, total_faixas from MeusCDs";

A interface ResultSet permite colher os resultados da execuo de nossa query no banco de dados. Esta interface apresenta uma srie de mtodos para prover o acesso aos dados:

1. 2. 3.

// Definido o Statement, executamos a query no banco de dados ResultSet rs = stm.executeQuery(SQL);

4. o 5. 6. 7. 8. 9. : 10. 11. 12. 13. 14. 15. 16. 17.

// O mtodo next() informa se houve resultados e posiciona o cursor do banc // na prxima linha disponvel para recuperao // Como esperamos vrias linhas utilizamos um lao para recuperar os dados while(rs.next()) { // Os mtodos getXXX recuperam os dados de acordo com o tipo SQL do dado String tit = rs.getString("titulo"); String aut = rs.getString("autor"); int totalFaixas = rs.getInt("total_faixas"); // As variveis tit, aut e totalFaixas contm os valores retornados // pela query. Vamos imprim-los

System.out.println("Titulo: "+tit+" Autor: "+aut+" Tot. Faixas: "+totalF aixas); 18. }

E nosso acesso est terminado. O importante agora liberar os recursos alocados pelo banco de dados para a execuo deste cdigo. Podemos fazer isso fechando o Statement, que libera os recursos associados execuo desta consulta mas deixa a conexo aberta para a execuo de uma prxima consulta, ou fechando diretamente a conexo, que encerra a comunicao com o banco de dados. Para termos certeza de que vamos encerrar esta conexo mesmo que uma exceo ocorra, reservamos o fechamento para a clusula finally() do tratamento de excees.

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.

finally { try { con.close(); } catch(SQLException onConClose) { System.out.println("Houve erro no fechamento da conexo"); onConClose.printStackTrace(); } }

Uma classe para listar uma tabela Vamos colocar tudo isso em conjunto para termos uma viso em perspectiva:

1. 2. 3.

package wlss.jdbcTutorial; import java.sql.*;

4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.

class Exemplo1 { public static void main(String args[]) {

// A captura de excees SQLException em Java obrigatria para usarmos JDBC. // Para termos acesso ao objeto con, ele deve ter um escopo mais amplo q ue o bloco try Connection con = null; try { // Este um dos meios para registrar um driver Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").getInstance(); // Registrado o driver, vamos estabelecer uma conexo con = DriverManager.getConnection("jdbc:odbc:meusCdsDb","conta","sen ha");

24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. do banco 36. 37. dados 38. 39. 40. 41. do dado: 42. 43. 44. 45. 46. os 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60.

// Aps estabelecermos a conexo com o banco de dados // Utilizamos o mtodo createStatement de con para criar o Statement Statement stm = con.createStatement(); // Vamos executar o seguinte comando SQL : String SQL = "Select titulo, autor, total_faixas from MeusCDs"; // Definido o Statement, executamos a query no banco de dados ResultSet rs = stm.executeQuery(SQL); // O mtodo next() informa se houve resultados e posiciona o cursor // na prxima linha disponvel para recuperao // Como esperamos vrias linhas utilizamos um lao para recuperar os while(rs.next()) { // Os mtodos getXXX recuperam os dados de acordo com o tipo SQL String tit = rs.getString("titulo"); String aut = rs.getString("autor"); int totalFaixas = rs.getInt("total_faixas"); // As variveis tit, aut e totalFaixas contm os valores retornad // pela query. Vamos imprim-los System.out.println(48:"Titulo: "+tit+" Autor: "+aut+"49: Tot. Faixas: "+totalFaixas); } } catch(SQLException e) { // se houve algum erro, uma exceo gerada para informar o erro e.printStackTrace(); //vejamos que erro foi gerado e quem o gerou } finally { try

61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72.

{ con.close(); } catch(SQLException onConClose) { System.out.println("Houve erro no fechamento da conexo"); onConClose.printStackTrace(); } } // fim do bloco try-catch-finally } // fim da main } // fim de nosso primeiro exemplo !

Na prxima parte deste artigo iremos analisar as extenses introduzidas pela API 2.1 e as interfaces PreparedStatement e CallableStatement.

Acessando Banco de Dados em Java (PARTE 2)


Publicado por daltoncamargo em 23/03/2010 - 159.586 visualizaes comentrios: 1 As chamadas de JDBC No artigo passado, mostramos o primeiro exemplo de acesso a um banco de dados com JDBC. Neste artigo comearemos a explicar alguns motivos implementados no padro utilizando o exemplo do artigo passado. O que nos chama a ateno logo de cara que o cdigo JDBC no se assemelha ao que o programador iniciante em Java est acostumado. Por exemplo, fazemos:

1. Connection con = DriverManager.getConnection(parametros da conexo);

ao invs de

1. Connection con = new Connection();

JDBC um padro onde est definida uma estrutura geral de acesso ao driver de banco de dados atravs de interfaces e o fornecedor se encarrega de implementar as classes que concretamente vo realizar o servio. Ora, cada fornecedor tem o seu driver especfico, construdo como uma classe JDBC. A chamada funo forName(classe) registra a classe nomeada na JVM corrente:

Quote: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").getInstance(); o Sun JDBC-ODBC bridge

Quote: Class.forName("COM.ibm.db2.jdbc.net.DB2Driver").newInstance(); para o IBM DB2 podemos ainda utilizar o mtodo registerDriver da classe DriverManager para isso:

Quote: DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); para o Oracle 8i O comportamento do driver JDBC uma incgnita. Depende sobretudo da arquitetura de acesso oferecida pelo banco de dados. Por exemplo, alguns bancos de dados vo exigir uma conexo com um cliente local. Outros utilizam arquivos de configurao. Para tratar com as diferenas entre os diversos produtos, DriverManager utiliza o padro Factory Method para instanciar Connection. Este padro utilizado por todas as interfaces de JDBC. Por exemplo:

1. Connection con = DriverManager.getConnection("jdbc:odbc:meusCdsDb","conta","se nha"); 2. 3. Statement stm = con.createStatement(); 4. 5. ResultSet rs = stm.executeQuery(alguma query SQL);

O problema simplesmente este: no sabemos, em tempo de compilao, qual a estrutura de classe ter a classe do driver que DriverManager ir carregar. Isto feito dinamicamente, no momento em que o driver registrado com DriverManager. Usando o padro FactoryMethod a necessidade de verificar a estrutura do driver estaticamente transformada numa chamada padro de funo que pode ser realizada em tempo de execuo. As classes que implementam concretamente essas interfaces no DB2, por exemplo, so DB2Connection, DB2Statement e DB2ResultSet e esto presentes no pacote db2java.zip. Para os programadores migrados de outros padres, este padro equivalente, no mundo dos objetos, s funes callback, to comuns nos SDKs do Windows. A diferena que um callback registra uma funo a ser chamada. O FactoryMethod cria um objeto. Se voc deseja saber mais sobre o padro FactoryMethod, recomendo "Design Patterns: Principles of Reusable Object Oriented Software" de Erich Gamma e outros.

Java Morrendo ??
Uma pergunta lanada numa lista de discusso nos ultimos dias me deixou realmente intrigado. Algum afirmou que a Microsoft estava parando o desenvolvimento em Java (provavelmente devido recente deciso judicial no caso Sun X Microsoft) e perguntou se por causa disso Java no estaria morrendo. A resposta (que continua sendo postada) foi um sonoro NO. Os argumentos variaram desde os motivos religiosos, tipo "M$ Jamais", at decises bem pensadas tipo "...adivinhe quantas companhias esto desenvolvendo uma JVM para a plataforma Wintel neste momento ?". Eu tenho minha humilde opinio a respeito. A aceitao e compromisso do mercado em relao a Java deve-se a diversos fatores:

1. Claramente h uma profunda mudana de viso sobre como construir sistemas em andamento no mercado. O modelo cliente-servidor apoiado na plataforma Wintel dispendioso, difcil de manter e no se ajusta s necessidades do mundo Internet. Ir desaparecer ? No, certamente que no, mas ir sendo posicionado num nicho ao invs de ser utilizado como uma soluo universal. O modelo Internet veio para ficar e mandar. 2. Java permite economia em escala quando seu modelo de portabilidade bem utilizado. Mesmo em ambientes com padres pblicos e conhecidos, como C++, portar cdigo um desafio. Em outros ambientes ainda mais populares e mais conhecidos, portar cdigo varia entre o impossvel e o pesadelo. Empresas como a PointBase, de bancos de dados pervasivos, esto, nas palavras de seu CEO: "...empregando mais engenheiros de portabilidade de cdigo que a Oracle, sem gastar um tosto na folha de pagamentos com isso. Onde esto eles ? Na Sun, Na IBM, Na HP..." (JDJ dez/2002). 3. Players pesados esto jogando neste mercado. Nomes como IBM, Oracle, HP, Inprise, (que, ao que parece, agora vai com tudo para o mercado Linux), o Apache.org e a prpria Sun, para citar alguns, deixam o desenvolvedor e o empresrio bastante tranqilos quanto a seu futuro. Linux ainda incipiente em relao a Java, mas a oferta de JVMs da IBM parece estar surtindo efeito tambm nesta plataforma. 4. XML vem com um modelo de representao de informao que, pela primeira vez, oferece um meio a baixo custo de expressar estruturas de dados complexas com a certeza de que sero lidas onde quer que sejam necessrias. A portabilidade dos dados demanda portabilidade do cdigo para sua interpretao, pois, como dito no item dois, manter portabilidade custa caro. Java tem uma proposta bastante interessante neste campo. Portanto, Java j ultrapassou a fronteira de sustentao que separa produtos de plataformas. O mximo que pode acontecer agora, IMHO, a linguagem se estabelecer num nicho e a ficar para sempre. Lembram do velho e bom FORTRAN ? Passa muito bem, obrigado.

Acessando Banco de Dados em Java (PARTE 3)


Publicado por daltoncamargo em 28/08/2009 - 125.867 visualizaes comentrios: 13 A interface Connection Como o exemplo anterior (Acessando Bancos de Dados em Java - PARTE 2) demonstrou, as interfaces fundamentais para obter acesso a um repositrio de dados em Java so: 1. Connection 2. Statement e suas variantes: PreparedStatement e CallableStatement 3. ResultSet A Interface Connection responsvel por manter a conexo estabelecida com o repositrio de dados atravs da chamada a DriverManager.getConnection(). A interface Connection tem 3 responsabilidades essenciais: criar ou preparar statements (sentenas SQL), executar o controle de transaes com o repositrio e criar objetos DatabaseMetaData, que permitem pesquisar dinamicamente que capacidades esto presentes no repositrio de dados. Recapitulando, vimos que a API JDBC usa o padro de chamada FactoryMethod, para possibilitar que a criao dos diversos objetos de controle de uma transao com um repositrio

de dados seja adiada para o momento da execuo, aps o JDBC Driver que possibilita o acesso ser registrado em DriverManager. Desta forma, cada objeto na cadeia de execuo de JDBC cria o seu sucessor na cadeia. Ou seja: DriverManager -> Connection -> Statement (ou variantes) -> ResultSet Connection pode criar Statement, PreparedStatement e CallableStatement atravs de um conjunto de chamadas: createStatement() -> cria uma instncia de Statement para execuo de SQL no repositrio createStatement(tipo de cursor, concorrncia) -> idem ao anterior, especificando o tipo de cursor a criar e o nivel de concorrncia da conexo. Antes da verso 2.0, s se podia conectar um banco de dados JDBC com cursores unidirecionais. Isto , uma aplicao que lia a linha 1 e em seguida a linha 2 da tabela no podia retornar linha 1 sem estabelecer um novo result set. A partir da verso 2, se o repositrio de dados suportar esta caracterstica, podemos estabelecer cursores bidirecionais de dois tipos: sensiveis, em que as alteraes havidas previamente na linha so refletidas na releitura, ou insensveis, em que as alteraes havidas na linha no se refletem na releitura. O tipo de cursor que o repositrio suporta uma informao retornada por DatabaseMetadata. O controle de transaes compreende basicamente 3 grupos de funes: getAutoCommit() e setAutoCommit(boolean toSet) -> permitem examinar ou definir que cada solicitao ao banco tenha commit imediato. getTransactionIsolation() e setTransactionIsolation(int transIso) -> permitem examinar ou definir com que tipo de isolamento de transaes aquela conexo deve operar. commit() e rollback() -> se o banco no est em modo autocommit, commit confirma a transao no banco enquanto que rollback cancela as alteraes da transao. Um grupo de funes pouco explorado da interface Connection o grupo que trata de ResultSets read-only, composto das funes isReadOnly() e setReadOnly(boolean setRead). Estas funes permitem estabelecer trancas de apenas leitura no banco de dados, evitando que o banco seja saturado por trancas de escrita (trancas de bloqueio), o que permite uma maior concorrncia no acesso ao banco.

Vous aimerez peut-être aussi