Apostila: Curso de java III

7

Click here to load reader

Transcript of Apostila: Curso de java III

Page 1: Apostila: Curso de java III

Curso de Java – Módulo IIIJDBC

Fábio Mengue – [email protected] de Computação - Unicamp

Conceitos

A tecnologiaJDBCfoi criadaparafacilitar o acessodeprogramasJavaa qualquerbancode dadosrelacional.A idéia era criar uma maneirasimplesde prover acessoà sintaxeSQL,propiciandoao programadoro usode SELECT’s,UPDATE’s e outroscomandosrelevantesnasintaxe.

O JDBC existedesdea versão1.1 da JDK, e participada API básica(pacotejava.sql).Masa partir daversão1.2,existeum pacoteadicionaldeclassesparaextensãodo pacotesql,queprovênovasfuncionalidades,comosuportea pool de conexõese transação(pacotejavax.sql).Neste treinamento, iremos nos ater apenas ao pacote básico.

A seguir,descrevemoso quedeveserinstaladoe ospassosparao acessoa um bancodedadosemmáquinaWindows.Parao acessoa outrasplataformas,o procedimentoé basicamenteo mesmo.

Instalando o ambiente

Claro queparacriar um programaJavaquefaz acessoa banco,deve-seinstalara JDK.Ao fazer isso,já existena API o acessoao pacotebásico.Após a instalaçãodo Java,devemosinstalarum driver que irá permitir a conexãoda JVM com o bancode dadosem questão.OsdriversJDBCpodemserfeitosemcódigonativodo sistemaoperacionalondefuncionam(comoos driversdosSGBD paraWindows)ou podemser feitos independentede plataforma(comoamaioria dos drivers de SGBD Open Souce).

De qualquermaneira,existeminstruçõesde comofazerissono pacotedo SGBD.Nessematerial, utilizaremosum bancode dadosbaseadosno Access.As máquinasWindows nãopossuemdriver JDBC gratuito,portantoa Suncriou uma“ponte” quepermiteo JDBC acessardriversODBC (nativoda Microsoft). O Windowsnormalmentepossuino “Painel de Controle”um ícone chamado“Fontes de Dados (ODBC)”. Esseaplicativo permite a criaçãode umaligaçãoODBC entreo arquivo .MDB e qualqueraplicativo quetenhaa capacidadede ligaçãocom o protocolo.Bastaidentificar o arquivo .MDB e atribuir um nomequeseráutilizado paraligar o programa àquela fonte de dados.

Uma das partes interessantesdeste tipo de configuraçãoé que não é necessáriaainstalaçãodo Accesspara que as coisasfuncionem.Bastao arquivo .MDB. Além disso, aidentificação da fonte de dados com um nome permite ao programador fazer um programa que seconectea maisdeumafontededadose permiteumaflexibilidadegrandepoiso arquivodafonte

1

Page 2: Apostila: Curso de java III

de dadospodeter seunomealteradoe mesmoser movido de local; desdeque a definiçãodafonte de dados continue disponível, o programa Java funciona.

Estabelecendo a conexão

Depois de iniciar o programae importar os pacotesnecessários(import java.sql.*;),devemosseguircertospassosparaquesejapossívelo acessoao SGBD.Devemosinicialmentecarregar o driver e depois criar a conexão propriamente dita.

A carga do(s) driver(s) é muito simples. Basta invocar o método estático

Class.forName("jdbc.DriverXYZ");

A classeClass tem como função instanciara classeidentificada entre parênteseseregistrá-lacoma JVM, queirá utilizá-la paraacessaro SGBD.Em nossoexemplo,utilizaremosa “ponte” ODBC – JDBC:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

O segundopassoé abrir a conexão.Para isso, normalmenteteremosque entrar emcontatocom o SGBD. No nossoexemplo,estamosconectandocom um arquivo estático,masnormalmenteestabelecemosconexãocom um banco real e existemrestriçõesde segurança.Devemospassarnomesde tabela,e credenciais.A linha mostradaabaixodá a idéia geral decomo é feita a conexão:

Connection con = DriverManager.getConnection(url, "usuario", "senha");

Não é muito complexa.A parte mais “desafiadora”é montar a url . Essaparte dainformaçãosemprese inicia com jdbc: , mas o resto dependedo fabricantedo banco. Naseqüêncianormalmentetemos o nome do fabricante(então temos jdbc:db2, jdbc:oracle,jdbc:psql, etc.) e por último o nome da fonte de dados (então teremos jdbc:db2:db,jdbc:oracle:server.unicamp.br:1234/meubanco,jdbc:psql:meubanco). Notemquea fontededados, para a maioria dos SGBD, representa uma tabela (com as visões dentro dela).

Seeu defini minhafonte de dadosno Windowscomobd, entãominha url de conexãoserájdbc:odbc:bd. Obviamente,no lugar de usuário e senha, devemosutilizar dadosválidosconstantes nos grants do SGBD para o acesso àquela tabela.

Finalmente, a nossa conexão ficaria definida assim:

String url = "jdbc:odbc:bd";Connection con = DriverManager.getConnection(url, "", "");

2

Page 3: Apostila: Curso de java III

Toda a parte envolvida com a conexão propriamentedita acontecede maneiratransparente.O programadornãotemnecessidadenenhumadesabero quesepassae, a nãoserqueele um dia resolvaescreverseuprópriodriver paraconexãoa algumSGBD,temquesedarpor satisfeito da coisa acontecer assim

A partir deagora,o objetocom representaumaconexãoativae abertaaobancodedadose o programador pode utiliza-lo para enviar statements SQL para o banco.

Criando statements

É necessáriocriar um objeto da classeStatement para armazenaro pedido que seráenviadoao SGBD. O programadordevesimplesmentecriar um objeto destetipo, informar acadeia de strings que representaseu comandoSQL e depois executá-lo,usandométodosespeciaisdependendodo tipo de comandodesejado.Paraum SELECT,usa-seexecuteQuery,Para INSERT, UPDATE e DELETE, executeUpdate. Por exemplo:

Statement stmt = con.createStatement();

Neste ponto, um statement foi criado. Mas não existe nenhumcomandoSQL nele.Podemos executar um comando como no exemplo abaixo:

stmt.executeUpdate("CREATE TABLE COFFEES " +"(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " +"SALES INTEGER, TOTAL INTEGER)");

Notequeexisteumaestruturadeparênteses,sinaisdeconcatenaçãoa aspas.Essessinaissãoimportantes,e muitasvezescausade confusõestremendasem programas.Muito cuidadocom eles, principalmente quando houver variáveis do programa Java misturadas ao SQL.

O métodomais comumde ser utilizado é o executeQuery. Mas ele tem um detalhe:retornadados.Assim, devemoster outro tipo de classequeserveexclusivamenteparareceberesses dados, de maneira que possamos fazer uso deles no processamento.

Essaclasseé chamadade ResultSet. É necessárioinstanciarum objetodestaclassequereceba o resultado do executeQuery. Veja o exemplo:

ResultSet rs = stmt.executeQuery("SELECT COF_NAME, PRICE FROM COFFEES");

A partir de agora,tenhoum objetochamadors quearmazenatodosos dadosrecebidos.Em linhas gerais, os programadoresestabelecemum loop onde fazem a leitura dos dadosbaseadosem métodospresentesna classeResultSet. Essesmétodospermitem“andar” pelosresultados e copiar os valores lidos para outros objetos. Veja o exemplo na próxima página.

3

Page 4: Apostila: Curso de java III

...String query = "SELECT COF_NAME, PRICE FROM COFFEES";ResultSet rs = stmt.executeQuery(query);while (rs.next()) {

String s = rs.getString("COF_NAME");float n = rs.getFloat("PRICE");

...

Paraacessarosnomese preços,corremoscadaregistroe acessamososvaloresdeacordocom o tipo. O métodonext() movimentao cursor para o próximo registro, tornandoaqueleregistroo corrente.Podemosentãoexecutaroutrosmétodos.Note queo cursorinicialmente(econvenientemente)fica posicionadoacimadoprimeiroregistro,exigindoumaprimeiraexecuçãodo next() para que possamos processar o primeiro registro.

Utilizamos métodoscujo nomese iniciam com get paraobter dadosdascolunas.Elesdevemserobtidosdeacordocomo tipo (o castpodeserefetuado,quandohouverpossibilidade),e essesmétodospermitemqueapontemosascolunaspelonomeou pelo índice(seunúmero,naordemem quefoi recebidae nãona ordemda tabelaoriginal). Assim, o códigoacimapoderiaser:

String s = rs.getString(1);float n = rs.getFloat(2);

Essa última abordagem tem uma performance melhor.

As primeirasclassesResultSetnormalmenteimplementavamacessodo primeiroregistroparao último, e nãosepodevoltar atrásnaleitura.A partir daversão1.2daJDK, o programadorpode usar instruções do tipo:

rs.absolute(5); // move o cursor para o quinto registrors.updateString("NAME", "teste"); // altera o valor da coluna NAME do

// quinto registro para “teste”rs.updateRow(); // atualiza a coluna na tabela

Usando Transações

Existemsituaçõesondenãosedesejaqueumainstruçãotenhaefeitoa nãoserqueoutrastambémtenham.Algumas situaçõesnecessitamque dadossejamincluídos em mais de umatabelaparaquesejamconsideradosconsistentes.Ou osdadosestãopresentesemtodasastabelasou não devem estar presentes em nenhuma.

A técnicautilizada paragarantiressetipo de consistênciaé o uso de transações.Umatransaçãonadamais é do que uma sériede statements que sãoexecutadosjuntos, como umacoisa única: ou todos falham, ou todos são executados.

4

Page 5: Apostila: Curso de java III

A primeira providênciaé desabilitaro auto-commit. Quandouma conexãoé criada,opadrãoé queelatratecadaexecuteUpdate comoumatransaçãoseparada,queé validada(comit)assim que é completada. Assim, devemos utilizar o código

con.setAutoCommit(false);

A partir daqui,nenhumstatement serávalidadoaté queo programadorpermita.Todoselesserãoagrupadose validadoscomoum só.Ao final do processo(casotudotenhatranscorridode acordo com o esperado), executa-se:

con.commit();

Caso algo não tenha dado certo, podemos executar:

con.rollback();

E todo statement executado será descartado.

É importante lembrar algumascoisas quando lidamos com a transaçãode maneiramanual. Os recursos de banco normalmente ficam presos, esperando um commit() ou rollback().Assim,seum programatratarou entraremloop (ou mesmodemorarmuito) o acessoao bancofica prejudicado.Existeaindaa possibilidadedeum “dirty read”,ondeoutroprogramarecuperadadosdo disco que você estáalterando,masaindanão validou. Essetipo de comportamentopode ser evitado aumentandoo nível de isolamentoentre transações.Verifique o métodosetTransactionIsolation() da classe Connection.

MetaDados

Ocasionalmente,vocêirá sentirnecessidadedeobtermaisinformaçõessobreo resultadodeum SELECTou mesmosobrea tabelaem questão.Vocêpodeobteressesdadosutilizandoaclasse ResultSetMetaData, que pode ser criada segundo o exemplo:

ResultSet rs = stmt.executeQuery(query);ResultSetMetaData meta = rs.getMetaData();

A classeResultSetMetaData lhe fornece informaçõesacercado número de colunasrecebidas,o nomee tipo dascolunas,sealgumacolunaaceitadadosnulos,camposde data,seelaé autoincrementável,sepodesernula,sepermitea escrita,etc.Além dissofornecetambéminformações sobre a tabela com que estamos trabalhando.

5

Page 6: Apostila: Curso de java III

Dicas e novidades (JDBC 2.0 e 3.0)

A versão1.4 da JDK já inclui a versão3.0 do JDBC.Não é a versãoemproduçãohojeem dia (muitos SGBD ainda não tem conformidadecom ela). Mas existemas extensõesdoJDBC 2.0 (representados por javax.sql) e esse pacote possui uma série de serviços interessantes.

Dentreessesserviços,temosa classeRowSet. Elaspermitemque o programadorabraumaconexão,recebaos resultadode um SELECT,e a seguirencerreessaconexão,enquantoprocessaosdadosrecebidos.Por incrível quepareça,o ResultSet nãopodefazerisso;eleexigequesemantenhaa conexãoabertaenquantoosdadossãolidos. O RowSet permitequeselibereo recursorapidamente,permitindoum melhor aproveitamentodos recursosdo SGBD, o quepossibilita atender mais usuários.

Outro recursoé a possibilidadede obter conexãoao bancoutilizando um serviço dediretório (baseadonasclassesJNDI – JavaNamingDirectory Interface).Nãoé maisnecessáriomontara url (com dadosde servidorese portasque podemmudar)ou mesmotrabalharcomusernamese senhasdentrodo programa(quesãovoláteise temquesertrocadaspor questãodesegurança).O programaidentificaum nomelógico, e a redeprovêinformaçãosobrea fontededados. Veja um exemplo:

import java.sql.*;import javax.sql.*;import javax.naming.*;...public Conexao() throws Exception { Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/DataSource"); java.sql.Connection c = ds.getConnection(); ... }...

Um dosrecursosmais interessantesé a capacidadede trabalharcom poolsde conexão.Essas“entidades”nadamaissãodoquevetoresdeconexõesqueficam permanentementeabertascom o SGBD, diminuindo o “overhead” de abrir e fechar uma conexão (operaçãoquenormalmenteé custosa).Ao necessitarde conexão,uma conexãojá abertaé fornecida aoprograma.Quandoo programadorvai fechá-la,elaé devolvidaaopool,pareserreutilizadamaistarde.

E por último, o suportea transaçãodistribuída.A Sun tem uma API especialpara otratamentode transaçõesentreprogramas.Essepacote(chamadoJavaTransactionAPI – JTA)permitea realizaçãodeum commit em duasfases,ondea transaçãocomeçaemum programaetermina em outro. Esse tipo de serviço é essencialem ambientesdistribuídos (onde oscomponentes nem sempre estão na mesma máquina).

Para essas e outras maravilhosas invenções, veja o endereço http://java.sun.com/products/jdbc/ .

6

Page 7: Apostila: Curso de java III

Apêndice A – Programa de Exemplo

import java.sql.*;

public class Principal { public static void main(String[] args) throws Exception { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection con = DriverManager.getConnection("jdbc:odbc:bd"); Statement stmt = con.createStatement();

ResultSet rs = stmt.executeQuery("SELECT LOGIN,NOME FROM ATENDENTE");

while (rs.next()) { String login = rs.getString("LOGIN"); String nome = rs.getString("NOME"); System.out.println("LOGIN:" + login); System.out.println("NOME:" + nome); } }}

Bibliografia

The Java Tutorial – http://www.sun.com/docsJDBC Home Page – http://java.sun.com/products/jdbc

Proibida a alteração, reprodução e cópia de parte deste material para qualquer finalidade sem apermissão do Centro de Computação da Unicamp.

A utilização deste material é permitida desde que conste a autoria do mesmo.

© 2002 Centro de Computação da Unicamp.

7