Sumário Conteúdo sobre Boas Práticas 06 - JDBC além do básico [ Luís Fernando Orleans ] Conteúdo sobre Boas Práticas 15 - Programando com estruturas de dados e padrões de projeto [ Miguel Diogenes Matrakas ] Artigo no estilo Solução Completa 24 - Persistência de dados com Hibernate 4 [ Carlos Alberto Silva e Eduardo Augusto Silvestre ] com. que artigo você mais gostou e qual pode tirar suas dúvidas sobre serviços.JP24185 Anúncios – Anunciando nas publicações e nos sites do Grupo DevMedia.com) Publicidade publicidade@devmedia. Solicite nossos Media Kits. informando o título e Eduardo Spínola (eduspinola@gmail. com detalhes sobre preços e formatos de anúncios. Easy Java Magazine. Fique a vontade para entrar em contato com os falar com um de nossos atendentes. Acesse www. consultar o status de assinaturas Se você estiver interessado em publicar um artigo na revista ou no site e conferir a data de envio de suas revistas.br/mvp Edição 49 • 2015 • ISSN 2173625-4 Fale com o Editor! Atendimento ao leitor EXPEDIENTE A DevMedia possui uma Central de Atendimento on-line. onde você É muito importante para a equipe saber o que você está achando da revista: que tipo de artigo você gostaria de ler. .devmedia.br/central. Através da nossa central também editores e dar a sua sugestão! Editor é possível alterar dados cadastrais. entre em contato com o editor.br – 21 3382-5038 Eduardo Oliveira Spínola Produção eduspinola.com) com.com Jornalista Responsável Kaline Dolabella . em mais de 200 cidades. Assine agora e tenha acesso a todo o conteúdo da DevMedia: www.wordpress. ou se preferir entre em contato conosco através do mini-resumo do tema que você gostaria de publicar: telefone 21 3382-5038. você divulga sua marca ou produto para mais de 100 mil desenvolvedores @eduspinola / @Java_Magazine Capa e Diagramação Romulo Araujo de todo o Brasil. Consultor Técnico Diogo Souza ([email protected]. enviar críticas e sugestões e artigo você menos gostou. . x. este é um assunto para outro artigo). diferenças entre Statement Gerenciadores de Bancos de Dados Relacionais (SGB. encontrar situações onde o JPA não se encaixa no seu projeto. No Java. EJB 2. é fácil perder o controle sobre esses artefatos conforme sub-consultas. tabela para cada classe da hierarquia. é de que elas usam a API da Java Database Connectivity muito comum ver desenvolvedores criando classes que herdam (JDBC) para realizar conexões com os SGBDs. linhas e colunas. composto primariamente de tabelas. 6 Copyright . etc.: vos XML. A melhor dica é estudar nos beans. ela tem como ponto negativo o fato de objeto-relacional (MOR) de forma transparente.) tem alta probabi.Proibido copiar ou distribuir. enviar de outras de forma não planejada. De todo modo. o similaridade entre estas tecnologias reside no fato que dificulta muito a manutenção de um sistema. JDO (agora sob responsabilidade da chaves compostas sempre representaram um problema para o Apache) e. os conhecidos getXXXX() e setXXXX(. diversas especificações foram criadas para facilitar a transformação de objetos em um formato relacional. outros quantidade de dados no SGBD não é aconselhável com são causados pela utilização da tecnologia para fins diferentes o JPA.. O JPA prevê alguns meios de contornar este problema. delimitar transações.x. introduzindo camadas nal: apesar de a herança ser uma característica muito poderosa intermediárias que fazem o chamado mapeamento da orientação a objetos. com ral. entretanto. reinícios e atualizações de hardware e alguns conceitos avançados desta tecnologia. Quando puder evitá-las. De um modo ge.) – OO o suficiente para fugir da herança. A vamente no problema de geração de consultas ineficientes. utilização de savepoints. uma vez que ela não foi projetada para essa daqueles para os quais ela foi projetada. Todos os direitos reservados para DevMedia . empobrecendo muito o projeto consultas. outros. utilização de cursores. destes recursos. Ainda assim. nenhum senvolvedores que desejam acessar SGBDs (apesar de deles consegue satisfazer totalmente os requisitos de orientação fomentar a criação dos indesejados métodos de acesso a objetos e de normalização de dados. mais recentemente. Sistemas de transações. o projeto cresce. uma realizam bons trabalhos. Dentre estes tipos de repositórios. JPA. Este passo é necessário. existem situações onde as ferramentas de em ferramentas OLAP (On-line Analytical Processing). são descritos apenas alguns dos problemas mais • Extenso número de artefatos de configuração a serem manti- comuns em projetos onde o JPA é utilizado: dos: apesar de existirem ferramentas que mantêm o sincronismo • Geração de consultas SQL que não utilizam índices: entre a especificação das tabelas no SGBD e as anotações ou arqui- qualquer SQL minimamente complexo a ser gerado (ex. têm em comum JPA. Outra aumentar consideravelmente o acoplamento entre as classes. tirar do programador a necessidade de aprender dois • Mapeamento do conceito de herança para o esquema relacio- mundos distintos (Java e SQL). faça-o. como gerenciamento software. a inserção de grande diferença dos mundos relacional e orientado a objetos. carregamento batch e DR) ainda se destacam como alternativa principal. caindo no- MOR não conseguem obter um bom desempenho. etc. sempre que pertinente. Ademais. • Carregamento batch: apesar de possuir mecanis. seguir. Repare que alguns destes problemas são ocasionados pela mos que atenuem este problema. desenvolvedores que resolveram ter maior controle sobre o código pois torna possível manter o estado do sistema entre que acessa o banco de dados utilizando JDBC.). lidade de ser ineficiente. é comum finalidade. final. simplificando a vida dos de. é apontado onde o desen- dada a maturidade da tecnologia e seu formalismo volvedor pode aumentar o desempenho de seu sistema com o uso matemático. etc.. Os documentos que definiram como utilizar • Mapeamento de tabelas que possuem chaves compostas: as EJB 1. e PreparedStatement. junções externas. as ferramentas de mapeamento objeto-relacional as técnicas de mapeamento (tabela única por hierarquia. Contudo. • Geração de relatórios: o JPA não foi projetado para utilização Contudo. No texto são analisados suas falhas.JDBC além do básico JDBC além do básico Entenda os aspectos importantes para otimizar o desempenho na persistência de dados JDBC P Fique por dentro raticamente todos os sistemas que são desenvol- vidos hoje em dia utilizam algum tipo de repo- sitório lógico para armazenar as informações Este artigo é útil por apresentar tópicos que facilitam a vida dos preenchidas pelos usuários. este contendo os dados lidos do disco. De forma abreviada. transação. é necessário revisar como um SGBDR processa os comandos SQL recebidos. que traz um método que deve recuperar. Para os leitores que quiserem se aprofundar 15 } sobre a arquitetura de SGBDRs modernos. o controle Listagem 1. A Figura 1 mostra os componentes principais da arquitetura 14 lista. e modelo de tratamento de requisições concorrentes.forName(“org. username.getString(“endereco”). passwd). Todos os direitos reservados para DevMedia 7 . 07 Statement stmt = conexao. indicado na seção Links. Para isso. Recebimento do comando SQL. O grande sucesso da JPA. passou a esconder um problema na formação dos desenvolvedores: a maioria deles desconhece algumas funções extremamente importantes do JDBC. os passos realizados pelo SGBDR são os seguintes: 1.next()){ responsabilidade de administradores de banco de dados (DBAs) 11 String nome = rs. 18 conexao. e do buffer. no qual os passos mais básicos na interação com um Analisando esse código. entretanto.getString(“telefone”). de partida. 09 List<Cliente> listaClientes = new ArrayList<>(). 19 return listaClientes.1/jdbc_alem_basico”. mais especificamente na definição da URL Listagem 1.Driver”). acesso aos dados será realizado. Execução da consulta.close(). são de responsabilidade deste módulo a manutenção do log de 05 Class. 3. Busca pelo plano de execução mais eficiente. bem como de algumas funcionalidades existentes nos SGBDRs que facilitam a construção de sistemas. o texto Architecture of 16 rs. Acessando um banco de dados com JDBC. nome. Ainda 04 String passwd = “123”. endereco).Proibido copiar ou distribuir. verificação 08 ResultSet rs = stmt.add(new Cliente(telefone. Reescrita do SQL. Database Systems. apesar de importantes.getString(“nome”). ao invés de perder um tempo precioso para aprender uma nova ferramenta. como característica principal.close(). protocolos de comunicação com o cliente " ORDER BY c. a rapidez para obtenção e 02 String url = “jdbc:postgresql://127. onde as alterações ainda não confirmadas são mantidas.getConnection(url. Ciclo de vida de uma consulta SQL Para compreender os conceitos avançados do JDBC.executeQuery(“SELECT c. liberação) são verificados e adquiridos quando necessários.* FROM CLIENTE c. todos os clientes que pediram um determi. iterar sobre o resultado e fechar a conexão. Tais conceitos. Figura 1. 5. transacional é executado como um módulo à parte.newInstance(). 20 } JDBC básico Neste tópico será mostrado um código simples de utilização da JDBC. é um excelente ponto 17 stmt. 03 String username = “java_magazine”.close(). onde locks e latches (tipos de locks específicos do sistema operacional e que 01 public Cliente recuperaClientes(String nomePizza) throws Exception{ possuem. 13 String endereco = rs. Ficaram de fora os passos como controle de admissão. nota-se que a partir da linha 02 iniciam banco de dados serão realizados. a seguinte forma: Copyright . 4. de forma proposital. pois aprenderam somente o básico: abrir conexão com o SGBD. PEDIDO p WHERE p. a utilização do bom e velho JDBC deve ser considerada. e pouco acrescentariam ao artigo. De um modo geral.0. Esse código é apresentado na os comandos da JDBC.postgresql. em ordem de acesso – uma String que contém as informações de como o alfabética de nome.telefone = “ + c. a URL possui nado sabor de pizza. executar uma consulta. para todos os comandos SQL que envolvam atualização de dados ou de esquema. Ciclo de vida de uma consulta SQL Além dos passos mencionados.0. por exemplo.nome”. 2.telefone AND p. 06 Connection conexao = DriverManager.nome_pizza = ‘“+nomePizza+” de permissões de acesso. os desenvolvedores Java devem ter conhecimentos mais aprofundados sobre os passos que um banco de dados realiza ao processar uma consulta SQL. são de 10 while(rs. com acesso aos dados.Nestas situações.createStatement(). de um SGBDR. Parsing do SQL. 12 String telefone = rs. De um modo geral. para cada comando recebido. o número de telefone. não caber na memória do cliente. seria preferível realizar os primeiros passos um efeito em cascata. Todos os direitos reservados para DevMedia .0 do JDBC ou posterior. com JDBC. devido ao risco de ataques Este tipo de cenário é extremamente comum e possui até um do tipo sql injection. o ótimo. que fornece o nome da pizza. o SGBDR será capaz de encontrar um Apesar de ser pequeno e relativamente simples. caso atinja. 17 e 18 fecham os objetos ResultSet. vamos refatorar o código da Listagem 1 para utilizar Clientes(). a 2. ao método iriam direto para a fase de execução da consulta.sql. recomenda-se checar na documentação do driver JDBC grande – tão grande que pode se tornar um problema para trans- como esta String deve ser formada. é criado e uma consulta SQL é enviada utilização desta classe força a realização de todos os passos do para ser executada. ao banco de dados que está tentando acessar. o passo onde o driver JDBC é carregado não é necessário. Concatenar strings ao comando SQL que vai ser executado é uma prática extremamente perigosa. Assim. o comportamento maioria dos vendedores de SGBDR preveem uma forma de manter padrão do JDBC é utilizar o gerenciamento de transações automá. mesma consulta. buscará o plano de consulta mais eficiente e. que pode ser entendido como uma “sessão de conversa” java. Na versão 4. Alguns fabricantes adotam URLs com formatos diferentes e. A linha 05 é necessária para carregar a classe que possui os Nos tópicos apresentados a seguir veremos como é possível métodos de comunicação com o SGBDR no ClassLoader. encon. uma vez que o fechamento de uma conexão provoca invocações. next().Statement para enviar comandos SQL para o SGBDR. o código da plano de execução quase ótimo.sql. planos de execução em cache – e a maneira do JDBC utilizar esse tico. permanece inalterado entre as redundantes. Seria melhor se fosse possível É importante ressaltar que o usuário deve ter permissão de acesso recuperar pequenas porções do resultado. sendo suficiente para a grande maioria dos casos. para cada chamada ao método recupera. respectivamente. Desta realizadas por um sistema sejam repetitivas.sql. onde todos os Statements abertos por ela do ciclo de vida da consulta até a geração do plano de execução são fechados. mitir os dados do SGBDR para o cliente ou. o método retorna o valor lógico false. Assim. Contudo. nas linhas 07 e 08. com um ponteiro que interno.sql. basta o cliente informar o novo parâmetro e o SGBDR apenas “insere” o parâmetro no plano em cache e o Nota: executa novamente. resolver estes problemas. é bastante comum que a grande maioria das consultas se o fim do resultado.sql. Statement é executada em uma transação isolada. bem como de metadados atualizados nas tabelas de sistema do SGBDR. o que significa que cada invocação de método de um objeto mecanismo é através da utilização de objetos do tipo java. ao ter seu método close() invocado. tendo seu resultado armazenado em um objeto ciclo de vida de uma consulta. Para encontrar o plano de execução ótimo. enquanto a linha 06 utiliza a classe java. a problemas de consistência e/ou desempenho. o Padrão de Projeto Command. Contudo. repare que sua representação em forma de objetos. reescrever o SQL em um formato representação em memória de uma tabela. Para melhor ilustrar a utilização de consultas parametrizadas 3.Sta. todos os passos do ciclo de vida da consulta. Ou seja.Driver e que esteja no classpath é Nota: automaticamente carregada. onde apenas parâme- forma é possível iterar sobre o resultado da consulta e construir tros são fornecidos. Ao abrir uma conexão com um SGBDR. um objeto do tipo java. Já as linhas 03 e 04 explicitam o usuário do SGBDR e a sua senha. O SGBDR vai realizar. Para realizar novamente a Statement fecha seu ResultSet caso este esteja aberto. Sta. trado após a etapa de otimização. aponta para antes da primeira linha. anda-se com o ponteiro para a próxima linha e. 4. as linhas 16. da independência estatística entre as colunas das tabelas.Proibido copiar ou distribuir. o SGBDR depende da distribuição estatística dos dados das tabelas envolvidas na consulta. As linhas 16 e 17 são as junções. infor- mando somente os parâmetros. nome próprio: Consulta parametrizada. Listagem 1 apresenta diversos problemas: 1. Por sua vez. O restante da consulta. se Problemas com o método recuperaClientes() as suas tabelas estão normalizadas até a 4ª Forma Normal. uma de cada vez. DriverManager para criar uma conexão com o banco de dados. O código de exemplo da Listagem 1 utiliza um objeto do tipo tement. finalmente.JDBC além do básico jdbc:[nome_vendedor]://[ip servidor]:[porta]/[nome do banco de dados]. chamadas subsequentes Isso permite que esta nova abordagem seja utilizada tanto em 8 Copyright . Olhando a Listagem 1 novamente. Considere que o resultado do SQL enviado é extremamente por isso. mado driver JDBC. Assim. Usando PreparedStatements Em seguida. pois toda classe que implemente a interface java. podendo levar PreparedStatement. ao chamar o método executará a consulta.sql. passada como parâmetro do construtor das classes de consulta. Este objeto pode ser visto como uma o SGBDR irá realizar o parsing. ordenações e seleções. que seria mantido em cache. onde a conexão é SGBDR manter em cache o plano de execução mais eficiente. incluindo tement e Connection. mudando somente uma classe própria (vide Listagem 2).ResultSet. A com o banco de dados. o que é ainda pior. a parte variável do SQL enviado ao banco de dados é o parâmetro Por fim. isto é. seria mais inteligente se mandássemos o Note a injeção de dependência na linha 09. Por ser tão frequente. o cha. teremos cada consulta em como o comando enviado é sempre o mesmo. do tipo java. suporte a transações distribuídas e portabilidade. onde Uma pergunta pertinente quando utiliza-se JDBC através de datasources é: se o servidor de as conexões são gerenciadas pelo servidor e disponibilizadas aplicações gerencia as conexões. p.nome_pizza = ? ORDER BY c.Proibido copiar ou distribuir. Datasources No código desta listagem. sível a mudanças após sua criação. possui inúmeras vantagens. andar para frente ou para trás e o objeto ResultSet não é sen- 16 List<Cliente> lista = new ArrayList<>(). objeto).} obterá nada além de um resultado vazio. veja o endereço indicado na seção Links. como fazer para evitar que os PreparedStatements sejam fechados para os clientes através de datasources (ver BOX 1). PEDIDO p WHERE Concurrency) e prepareStatement(String sql... BOX 1. 21 } . como utilização de pool de conexões. As linhas 13. Os parâme- 06 public ConsultaRecuperarClientes(Connection conexao. quando é solicitado a uma conexão adquirida de invocar a consulta abra a conexão e seja responsável pelo seu um datasource para “preparar” um Statement. java. 03 } trizadas – e possivelmente uma razão para sua adoção em larga 04 escala – é que elas tornam o código à prova de ataques do tipo 05 public class ConsultaRecuperarClientes implements Consulta<Cliente>{ sql injection.ResultSet e significam o seguinte: 08 this. String nomePizza){ tros adicionais neste método são constantes definidas na classe 07 this. onde as informações para abrir conexões são fornecidas. fechamento automático de conexões abertas “esquecidas” prepara-se o SQL que será executado (repare que o parâmetro pela aplicação. etc.conexao. se um registro tiver Copyright .. Quando este arquivo é evitando que outras consultas fiquem “presas” esperando a fi- lido pelo servidor de aplicações. uma IDE como Eclipse ou NetBeans para reproduzir o có- 01 public class ConsultaRecuperarClientes implementds Consulta<Cliente>{ digo das Listagem 3 vai reparar que o método Connection 02 . . 14 pstmt. um dos seguintes valores pode ser utilizado: 09 this. Nota: muito usada em sistemas desktop. int resultSetConcurrency. cuperarClientes utilizando PreparedStatements. 14 e 15 mostram como através de lookups.sql. Int. conexões devem ser fechadas primeiro e quais devem ser mantidas no pool de conexões. 04 private String nomePizza.. na linha 9. etapa. 10 11 public List<Cliente> executarConsulta() throws Exception {. nomePizza). é verificado antes se aquele PS já existe em cache. Utilizando Commands para as consultas.TYPE_FORWARD_ONLY (valor padrão): o cursor 11 somente anda para frente e o objeto ResultSet não é sensível a 12 public List<Cliente> executarConsulta() throws Exception{ mudanças realizadas por outros clientes após sua criação. Nesta datasources.next()){ 18 //cria e popula objetos do tipo Cliente seu valor alterado por outro cliente após a criação do objeto 19 } ResultSet. Como os parâmetros agora são apenas inseridos em 06 07 private Connection conexao. Ou seja. pode-se ver. O servidor de aplicações também pode utilizar o número de PS em cache para determinar quais A Listagem 3 mostra a implementação da classe ConsultaRe.telefone = c. Para mais informações sobre é representado por um ‘?’ no código enviado ao SGBDR). perdidos? A resposta é: praticamente todos os servidores de aplicação ressaltar que a injeção de dependência obriga que o método que fazem cache de PreparedStatements.TYPE_SCROLL_INSENSITIVE: o cursor pode 15 ResultSet rs = pstmt. os parâmetros para executar a consulta são informados através dos métodos setXXX(posição.cenários onde conexões são abertas diretamente pelo cliente.nomePizza = nomePizza • Em resultSetType.ResultSet..nome”. a con- sulta é executada. Por fim. não serão adquiridos locks/latches no acesso aos dados. int resultSetType. É importante e. Assim. Float.prepareStatement(String sql. consequentemente.TYPE_SCROLL_SENSITIVE: o cursor pode 22} andar para frente ou para trás e o objeto ResultSet é sensível a mudanças após sua criação. as consultas parametrizadas funcionam em JDBC: primeiro.executeQuery(). Por ser um objeto gerenciado pelo contêiner. fechamento ao final. se um registro tiver 17 while(rs. int resultSetType. int resultSetHoldability). dependendo do caso. o datasource é armazenado na estrutura JNDI e se torna acessível nalização do processamento. String nomePizza){. ser String.conexao = conexao. Por fim.ResultSet.prepareStatement(sql). o comando é validado. De forma breve. que o co- Datasource é a forma mais recomendada para adquirir conexões com SGBDRs quando a aplicação mando a ser enviado para o SGBDR é apenas para leitura. Exemplo de utilização de PreparedStatements. 10 } . 13 PreparedStatement pstmt = conexao. como em sistemas web. int resultSet- 05 private String sql = “SELECT * FROM CLIENTE c. otimizado e pré-compilado. 20 return lista. Ou seja. descritor XML. um datasource é especificado em um forma. 01 public interface Consulta<E>{ Um efeito colateral positivo da utilização de consultas parame- 02 List<E> executarConsulta() throws Exception. um plano de execução pré-compilado. se um usuário espertinho 08 tentar inserir trechos de SQL em um campo do formulário não 09 public ConsultaRecuperarClientes(Connection conexao.telefone AND “ + “p. onde XXX pode Listagem 2.setString(1.} 12 } Aprofundando a interação com o SGBDR através de ResultSets Um olhar mais atento do leitor que estiver utilizando Listagem 3.ResultSet. .setReadOnly(true).prepareStatement(sql) possui duas variantes: Connection 03 private Connection conexao. este não irá refletir a alteração. Todos os direitos reservados para DevMedia 9 . Desta é executada em um contêiner Java EE. ResultSet.CONCUR_READ_ONLY (valor padrão): cria um lado.CONCUR_UPDATABLE: cria um objeto Result. para cada pizza. Todos os direitos reservados para DevMedia . Seja por erros de ortografia. preco). Caso contrário. caso não tenha ocorrido erro na Por fim. Listagem 4.executeQuery().getString(“preco”). seja por utilizar uma abreviação para Scanner scanner = new Scanner(System. é possível inserir o pedido sem problemas. resultado é tão grande que pode não caber inteiramente na me- lidade dos acessos. um dos seguintes valores pode ser cenário para o sistema de exemplo deste artigo: com o sistema em utilizado: manutenção. atualiza o valor dentro do próprio ResultSet e confirma a tectar um problema no cadastramento do pedido. as famosas propriedades ACID. rs.out. • Em resultSetConcurrency. anteriormente.updateString(“preco”. } A Listagem 5 mostra a implementação do cenário descrito con. Contudo.prepareStatement(“SELECT * FROM PIZZA ORB- DER BY NOME”. as transações têm a função de garantir as chamadas de tuplas). anotados de forma offline.commit()). Este é o cenário típico para utilização dos chamados savepoints: rs. isolamento e durabi.CONCUR_UPDATABLE.updateRow() deve ser invocado. Como os pedidos foram realizados de maneira offline. consistência.JDBC além do básico seu valor alterado por outro cliente após a criação do objeto única unidade de trabalho.updateRow(). o cliente é antigo e nada deve ser feito. Repare que. linhas 24-35). evitando que a inclusão do ResultSet. Em seguida.close(). ResultSet.next()){ pedido deste cliente. um dos seguintes valores pode ser É sabido que para confirmar uma transação e tornar suas modi- utilizado: ficações duráveis.commit(). que o atendente tenha escrito o nome da pizza de forma errada. A rotina para importação destes pedidos realizados offline pode verificar se o cliente é novo através de seu número de telefone. onde deseja-se importar pedidos que foram scanner. é possível PreparedStatement pstmt = con. while(rs.ResultSet.out. inclusão do cliente e do pedido. . ResultSet.ResultSet. ao de- preço. podem existir situações onde o propriedades de atomicidade. comandos enviados por outros clientes. este irá refletir a alteração. o COMMIT da linha 48 confirma a o comando de atualização para o SGBDR. con. um nome de pizza grande. String preco = scanner. Deste modo.out. inclusive a inclusão do novo cliente. Uma vez garantido que o cliente consta na base de dados. das as alterações realizadas pela transação. um ROLLBACK transação. e outra . a resposta esperada é um conjunto de linhas (também Em bancos de dados. Por blocos de comandos SQL de um usuário são tratados como uma exemplo. Existem duas possíveis inserções neste da (através da chamada ao método Connection. uma vez que haverá uma violação de chave System. deve-se abortar a transação utilizando o comando ROLLBACK. as alterações realizadas apenas a partir deles. para que esse código funcione.out. caso: uma na tabela de clientes. deve-se incluir o novo cliente na tabela antes de realizar a inserção na tabela de pedidos.Proibido copiar ou distribuir. Contudo. Obtendo resultados de consultas baseados em cursores Quando uma consulta é enviada para ser executada em um Utilização de SavePoints em transações SGBDR.println(“Nome da pizza: “+rs. cujos dados estão corretos. caso algum erro tenha ocorrido durante o processamento. Por fim. mória do cliente ou mesmo causar congestionamento na rede. A Listagem 4 ilustra uma situação onde estes parâmetros podem Caso já exista na tabela. devendo ser realizadas nesta ordem devido ResultSet são mantidos abertos mesmo quando a transação é à restrição de chave estrangeira. linhas 16-22) e outro para cadastrar o pedido O código deste exemplo exibe. o ResultSet criado deve inserção deste último.HOLD_CURSORS_OVER_COMMIT: os objetos na tabela de pedidos. o fato é que não será possível inserir o ResultSet rs = pstmt. Após realizar a inserção do preço atual.ResultSet.getString(“nome”). Criando ResultSets mais avançados. ser atualizável e não deve ser fechado quando o SGBDR receber o comando para confirmar a transação. pois é ele que dispara cliente seja desfeita. após atualizar o valor do campo. o seu nome e (cadastrarPedido(). protegida de possível interferência de ResultSet. Considere o seguinte • Em resultSetHoldability. os pedidos passaram a ser anotados em uma planilha . um SAVEPOINT é criado na linha 21. caso o cliente seja novo. marcadores dentro de uma transação que permitem desfazer todas System.println(“Digite o novo preço:”).println(“Preço atualizado com sucesso!”). ResultSet. uma única transação. lançados posteriormente.TYPE_SCROLL_INSENSITIVE. o método é realizado até o SAVEPOINT criado. Desta forma. pede para que o usuário digite o novo cliente. confirmada. o SQL executado na Listagem 1 pode ter um resultado 10 Copyright . Se todos estes passos forem executados dentro de System. o comando ROLLBACK enviado vai desfazer System. objeto ResultSet que somente é capaz de ler dados. estrangeira.HOLD_CURSORS_OVER_COMMIT). existem casos onde pode não ser desejável abortar to- Set atualizável. O método realizarVenda() (linhas 37-52) realiza dois passos distintos: um para cadastrar o cliente (cadastrarCliente(). deve-se utilizar o comando COMMIT. ser utilizados para a criação de um ResultSet atualizável. Por outro .in).nextLine().println(“Preço: “+rs.CLOSE_CURSORS_OVER_COMMIT: todos os Excel (dados dos clientes e as pizzas que eles pediram) para serem objetos ResultSet são fechados quando a transação é confirma. certo? Nem sempre! Connection con = getConnection().close(). getTelefone()).: os 10 maiores salários). Integer quantidade){ 11 this. Em outras palavras. linhas por vez. tráfego da rede.setDate(2.000 cursores. 30 pstmtPedido. um novo bloco do resultado é solicitado ao servidor até que todas as tuplas tenham sido consumidas. 17 pstmtCliente. 38 cadastrarCliente(cliente).setString(1. Figura 2. (telefone. data_hora.prepareStatement(sqlInsereCliente). não Figura 3 ilustra como o sistema se comportaria recuperando 100 é possível “retroceder”. quando o método ResultSet.getTelefone()). cliente. para o cliente. 25 try { 51 } 26 pstmtPedido. 39 Pedido pedido = new Pedido(cliente. Neste caso. Pizza pizza. e do comando FETCH.muito grande para sabores de pizza populares e causar os pro.prepareStatement(sqlInserePedido). 34 } 08 private Savepoint cadastroClienteSP.printStackTrace(). “+ “quantidade) values(?. 05 private PreparedStatement pstmtCliente. A ONLY. ?. 14 } 40 15 41 try { 16 private void cadastrarCliente(Cliente cliente){ 42 cadastrarPedido(pedido).setInt(4. Neste cenário. Enquanto LIMIT <TAM> define o número de linhas total do resultado da consulta (ex.printStackTrace(). 47 try { 22 } 48 conexao. 13 pstmtPedido = conexao. nome. new Date(). Todos os direitos reservados para DevMedia 11 . 32 e. quantidade). 06 private PreparedStatement pstmtPedido. FETCH É comum haver confusão entre as semânticas da cláusula LIMIT <TAM>. Vale ressaltar que existem algumas restrições para a utilização de blemas citados anteriormente: se o resultado possuir 300. em média. um novo bloco de 100 linhas é enviado para o cliente. evitando as sobrecargas na memória do cliente e no fecha os cursores quando a transação é confirmada.Date(pedido.sql.setSavepoint(). pedido.executeUpdate(). 45 } 20 pstmtCliente. Na verdade.conexao = conexao.setString(3. que é o SGBDR adotado nos linhas e cada linha tiver. são conceitos bem distintos.setString(2. 01 public class RealizaVendas{ .next() (linha 18) tentar acessar a primeira linha que ainda não foi recuperada.next() A Listagem 6 exibe como utilizar cursores para receber o resul- tentar acessar a primeira tupla que ainda se encontra no servidor. 02 28 pstmtPedido.getTime())). a utilização ou não de cursores é transparente: quando o método rs. 44 e1. Por exemplo. pedido. é possível fazer • O ResultSet deve ser do tipo ResultSet. pois o servidor por vez. Com cursores Listagem 5.getDataHora() 53 } Copyright .getEndereco()). new java. endereco) “+ “values(?. que é o comportamento padrão.TYPE_FORWARD_ uso de cursores dos SGBDRs em conjunto com o comando fetch. pedido.setString(1. Sem cursores LIMIT vs.setString(3. no PostgreSQL. nome_pizza. pizza. 52 } 27 pstmtPedido.executeUpdate(). ?)”. tado da consulta enviada ao servidor. o resultado seria fatiado em pequenas • O comando enviado ao servidor deve conter uma única con- quantias com o tamanho de 100KB por vez. cliente.getNome().getNomePizza()).getTelefone(). ?)”. cliente. //desfaz somente a tentativa de inserir novo pedido 07 private Connection conexao.getQuantidade()). 43 } catch (SQLException e1) { 18 pstmtCliente. tocolo V3. ?. 1KB. o bloco de linhas retornado é armazenado em cache do lado do cliente e. 19 pstmtCliente. Para resolver estes problemas. Figura 3. 35 } 09 36 10 public RealizaVendas(Connection conexao)throws Exception{ 37 public void realizarVenda(Cliente cliente. utilizada para limitar o número total de linhas do resultado. ?.printStackTrace().rollback(cadastroClienteSP). aceitável. 04 private String sqlInserePedido = “insert into pedido 31 } catch (SQLException e) { (telefone.Proibido copiar ou distribuir.getNome()). algo perfeitamente sulta SQL. as seguintes condições são necessárias: rede e aumento de memória da máquina virtual do cliente será • A conexão com o servidor deve ser realizada utilizando o pro- de 300MB (Figura 2). 23 49 } catch (SQLException e) { 24 private void cadastrarPedido(Pedido pedido) throws SQLException{ 50 e.commit(). o total de tráfego de exemplos deste artigo. Como solução. Exemplo de utilização de SavePoints. Repare que. 46 21 cadastroClienteSP = conexao. 12 pstmtCliente = conexao. que é o protocolo padrão de conexão. 03 private String sqlInsereCliente = “insert into cliente 29 pstmtPedido. 33 conexao. o ideal é recuperar apenas um conjunto de linhas • A conexão não pode estar no modo autocommit. 1. Qual o problema nesta abordagem? Para saber essa resposta.conexao. fluenciar muito no tempo total de processamento. 2. Repare na Figura 4 que inclusive o SGBDR pode gerar planos sendo executada várias vezes. importação de dados para um SGBDR transacional (ver BOX 2). quantidade).add(pedido). nomePizza. para melhorar o desempenho. //indica o número de linhas a ser a forma como o carregamento dos dados é realizado pode in- recuperado por vez. ga). 18 String telefone = rs. Exemplo de resultado baseado em cursores. seja para importar dados que 01 public class ConsultaPedidosRecentes implements Consulta<Pedido> { 02 private String sql = “select * from pedido”.OFFSET ou cursores para realizar a paginação? Importação de grande volume de dados Apesar de ser uma tarefa comum durante a construção de Data Warehouses.): 26 } catch (SQLException e) { 27 System.OFFSET ou FETCH para realizar paginação? tempo de processamento).. relativos às pizzas e aos pedidos são inseridos de maneira análo- 21 Integer quantidade = rs. 30 } 3. Em situações como esta. deve-se utilizar LIMIT.executeUpdate(. o fato é que essa tarefa não chega a representar um problema 04 private Connection conexao. 06 public ConsultaPedidosRecentes(Connection conexao){ Conforme o tamanho dos dados aumenta. retornando subconjuntos do resultado. resultado sendo retornado ao cliente. Uma transação é aberta.getString(“nome_pizza”).OFFSET implicará na mesma consulta vez). somadas 12 try { 13 PreparedStatement stmt = conexao. Já o FETCH executa a con- sulta uma única vez (o que pode aumentar consideravelmente o LIMIT.getTimestamp(“data_hora”). problemas de desem- 07 this. 20 String nomePizza = rs.executeQuery(). Esta é outra dúvida que surge quando o desenvolvedor deseja Neste caso.println(“Erro ao recuperar os pedidos do banco de dados. penho na importação começam a aparecer e podem até inviabi- 08 this. 10 pedidos por vez na sua página..JDBC além do básico o comando FETCH define o número de linhas a ser buscado por Ambas funcionam. recuperando 10 por a utilização de LIMIT. 16 List<Pedido> lista = new ArrayList<>().”). com apenas um subconjunto do de execução diferentes para consultas com e sem LIMIT.. contendo 3. Para ilustrar essa situação. dataHora. 05 quando a quantidade de dados é pequena.. mas possuem uma diferença importante: vez do resultado total (ex. 03 private static final int FETCH_SIZE = 10.. ou seja. mostra uma implementação considerada ingênua para importação 17 while(rs. uma combinação dos paginar o resultado de uma consulta..setFetchSize(FETCH_SIZE). Todos os direitos reservados para DevMedia . cação do método Statement. Esse código exibe somente a importação dos clientes (os dados 19 Date dataHora = rs. 14 stmt. 09 } lizar a operação. A Listagem 7 15 ResultSet rs = stmt. as três tabelas e excluindo índices e outras estruturas auxiliares. Figura 4. deve-se ter em mente o que acontece quando uma única linha é 24 } inserida.conexao = conexao.setAutoCommit(false). o que é realizado pelo SGBDR para cada invo- 25 return lista. Os novos dados são escritos no log de transação. 28 throw new RuntimeException(e). Suponha que o sistema exiba dois pode ser utilizada. Seja para unificar bases de dados. foram coletados de forma offline durante uma queda do sistema.. de vez em quando é necessário criar rotinas para Listagem 6.8MB e 87772 linhas. 22 Pedido pedido = new Pedido(telefone.next()){ destes dados. Checagens de restrição são executadas para garantir que não 29 } há nenhuma violação de integridade.err. considere a base de 10 dados utilizada como exemplo neste artigo: apesar de poder ser 11 public List<Pedido> executarConsulta() { considerada pequena. Planos de execução com e sem a cláusula LIMIT 12 Copyright ..prepareStatement(sql).: todos os salários. 23 lista.Proibido copiar ou distribuir.getString(“telefone”).getInt(“quantidade”). Todos os direitos reservados para DevMedia 13 .createStatement(). O retorno deste método é um array de demorou 219452ms ou 3.003 ms para ser inse- Uma maneira de melhorar o desempenho nesta tarefa seria rido. Uma sugestão de ferramenta ETL gratuita é o conexao. que será acessado pelo sistema conexao.executeBatch(). pode levar muito tempo addBatch(sql). nome. Os dados são escritos no disco. Em um experimento rápido. ‘”+ tokens[1]+”’. Copyright . a importação levou 31727 ms. transformar.executeUpdate(sql). endereco) } values(‘”+tokens[0]+”’.1. inteiros. Dentre os exemplos no mun- ser inserido. seria mais Um projeto de criação de Data Warehouse (que é. o que significa uma sobrecarga na rede BOX 2. a a Java Database Connectivity API. Transformação e Carga no momento da transferência dos dados. de geração de relatórios. Contudo.close().addBatch(sql). apro. seria necessário esperar estratégia levou 14103 ms ou seja. A transação é confirmada.2 ms ou 17 horas! de minuto.4. Listagem 7.Extração. então.executeBatch(). rado overhead. Repare a diferença entre os passos 1.5 horas. ou seja. mesmo a importação de uma quantidade pequena que será executado no servidor através do método Statement. Nos testes realizados.createStatement(). arquivoClientes.5 horas. Quando possível. conexao. Importação de dados sem autocommit. a geração de relatórios para a alta diretoria de uma empresa) possui requisitos e etapas diferentes conforme a Listagem 9. deve-se considerar a utilização de alguma ferramenta ETL para esta tarefa. Connection conexao = getConexao(). ETL . endereco) String [] tokens = linha. nome. limpar e qualificar estes dados de forma a eliminar redundâncias. String [] tokens = linha. while((linha = arquivoClientes.008 ms para gia mas não dominam a base dela. Ou seja.split(“\t”). Desta forma.close(). Importação de dados sem autocommit. Sendo assim. onde tanto o programa os comandos são enviados de uma única vez para o servidor quanto o SGBDR rodavam na mesma máquina. acelerando muito esta etapa quando comparada às soluções String sql = “insert into cliente(telefone. disparando os seguintes processos: qualquer momento. qualquer erro ocorra durante a importação. 4. como utiliza ainda ocorre dentro de uma transação e o SGBDR pode decidir. stmt. 1 hora. aproxi. conexao. esta dados maior contendo. discrepâncias. Cada byte leva. é: caso possua uma quantidade muito. Um desempenho que levaria 4011520 ms (pouco mais de retirar a opção de autocommit da conexão aberta. de dados.Proibido copiar ou distribuir. String sql = “insert into cliente(telefone.split(“\t”). Definitivamente. ou.split(“\t”). ‘”+tokens[2]+”’)”.close().createStatement(). Connection conexao = getConexao(). values(‘”+tokens[0]+”’.close(). programáticas vistas aqui. Se fosse uma massa de afetadas pelo respectivo comando.setAutoCommit(false). conexao. 1GB.close().executeUpdate(sql). Esta etapa é tão importante que chega a consumir cerca de 70% do tempo Statement stmt = conexao. Todos os índices que contêm alguma das colunas da tabela escrita serão desfeitas (ROLLBACK). escrever os dados no disco (passo 4. gerando um novo e inespe- onde os dados foram inseridos são atualizados. endereco) values(‘”+tokens[0]+”’.commit().8 ms ou 2.2 seriam realizados somente uma vez para a tempos: 17 horas. planilhas Excel Listagem 8. O código para esta implementação é apresentado do método para realizar essa importação de dados realmente na Listagem 8. que possuem um conhecimento bem avançado de uma tecnolo- madamente 0. No caso de uma massa de dados de 1GB. um banco de dados voltado para interessante se os comandos fossem enviados em blocos (batch). todas as operações de 4.1) e. os 1 hora) para inserir 1GB de dados. while((linha = arquivoClientes. esta a Java Persistence API (JPA) mas pouco entendem sobre como projeção não é totalmente precisa. ‘”+tokens[2]+”’)”. como a contida no exemplo. neste caso. Importação de dados – forma 1. etc. Esta simples alteração permite um ganho de tempo enorme. faz diferença.readLine())!= null){ String sql = “insert into cliente(telefone. Para piorar. daqueles apresentados para a construção de um sistema transacional. arquivoClientes. para terminar. cada byte leva. ou seja. stmt. Statement stmt = conexao. JDBC. Nos É muito comum encontrarmos no mercado desenvolvedores testes realizados. o tempo do Java deste fenômeno estão aqueles que sabem muito sobre total de espera seria de 9024568. 4.05 ms para ser inserido. cada comando de inserção está sendo enviado separadamente. nome. 2. esta importação e lá são executados. as ferramentas ETL são capazes de String [] tokens = linha. 0. por exemplo.2. while((linha = arquivoClientes. pouco menos de um quarto 62421902. caso 4. } stmt. Uma destas etapas é a ETL. ‘”+tokens[2]+”’)”.5 minuto. e arquivos-texto. ‘”+tokens[1]+”’.stmt. 0. A dica. cada byte demorou 0. uma vez que a importação a JPA acessa de fato os bancos de dados.readLine())!= null){ Ao realizar a carga de dados para o banco de dados de destino.readLine())!= null){ Statement stmt = conexao. de forma simples. muito grande de } dados para carregar.close(). onde cada posição representa o número de linhas ximadamente. que consiste em extrair dados de várias fontes. Listagem 9. Pentaho Kettle (veja a seção Links). como é chamada. utilizar opções avançadas dos SGBDs. Ao chamar o método Statement. arquivoClientes. Connection conexao = getConexao(). e carregar estes dados no banco de dados final.6 minutos. de geração de um DW e existem ferramentas construídas especificamente para este propósito. a escolha operação inteira. Assim. recorra ao DBA da sua equipe.. Nesse código cada comando de inserção é adicionado ao bloco Desta forma.1 e 4. ‘”+tokens[1]+”’. entre elas bancos de dados relacionais. br/ Tutorial de JDBC da Oracle. 2000. 14 Copyright . é necessário tanto reconhecer e distinguir Livro: Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos. existem tarefas onde a utilização de JPA não é reco.Proibido copiar ou distribuir.oracle. como ter um bom entendimento de como acontece a interação programa-SGBDR. ter conhecimentos mais aprofundados de JDBC Architecture of a Database System.JDBC além do básico Contudo.com/javase/tutorial/jdbc/ Universidade Federal Rural do Rio de Janeiro (UFRRJ) e obteve o grau de Doutor em Engenharia de Sistemas e Computação em 2013.edu/papers/fntdb07-architecture. http://db. Editora Bookman. ufrrj. Datasources. café.com/javase/tutorial/jdbc/basics/sqldatasources. tendo acompanhado de perto todas as novidades da linguagem desde então.com.oracle.html Autor Pentaho Kettle. Para isso.cs. para realizar essas tarefas é fundamental para um bom desen.br} . os passos realizados pelo SGBDR ao processar uma consulta. É Professor Adjunto do curso de Ciências da Computação da http://docs. Assim. muitas vezes apresentando um desempenho bem ruim.berkeley. http://docs. Links: mendada.blogspot.pdf volvedor.http://lforleans. Desenvolve e coordena diversos projetos em Java desde 2001. Flamengo e bons papos.org. Todos os direitos reservados para DevMedia .com/ Luís Fernando Orleans lforleans@{ieee. por tecnologia. vinho.pentaho. http://community. Apaixonado pela família. Representação das ligações entre os elementos de uma lista encadeada lista encadeada. por ser bastante adaptável e simples. é a lista encadeada. como acontece nos buffers utilizados em processos de comunicação. Para implementar estas ligações se faz necessária a declaração Estes apontadores guardam a sequência dos elementos na de uma classe que contenha referências a objetos da própria lista e são utilizados para viabilizar a navegação e acesso classe. serão realizados até que se obtenha o resultado desejado. diz-se que a lista é duplamente encadeada. da lista encadeada. chamadas de estruturas de permitir o acesso aos dados sem que seja necessário expor caracte- dados. elementos de dados como ilustrado nas caixas da mesma figura. Esta atividade exige técnicas eficientes para organizar e aces. e para não ser necessário Copyright . limitação de tamanho e é conveniente apenas quando se conhece antecipadamente a quantidade máxima de ele- mentos que serão armazenados na mesma.Programando com estruturas de dados e padrões de projeto Aprenda a usar o padrão Iterator para implementar a estrutura de dados de lista duplamente encadeada U Fique por dentro ma das principais atividades da computação é o processamento de dados. também chamados de nós da lista. nas quais a ordem de inserção e remoção é determinada pelo algoritmo e não pela aplicação que o sentido. os dados podem ser inseridos e removidos funcional. porém Em uma lista. Para isso. A maioria das estruturas de dados podem ser imple. O exemplo construído mentadas utilizando-se vetores. Estas auto-referências representam as conexões entre os a cada um dos elementos presentes. a partir da qual pequenos incrementos em qualquer ordem e em qualquer posição. Esta análise será feita de forma crescente. é indicada a utilização de uma Figura 1. A classe que representa os As ligações entre os elementos da lista formam na me. Para os casos em que não se conhece a quantidade de elemen- tos que serão inseridos. de maneira das estruturas de dados mais utilizadas no desenvolvimento de apli- que operações como inclusão. diferen. e quando as está utilizando. uma das mais utilizadas. a lista encadeada. Dentre estas soluções. pesquisa e remoção de cações. como o caso das filas e das pilhas. Para resolver esta categoria de problemas as características descritas no Padrão Iterator. conforme a Figura 2. temente de outras estruturas. a lista é chamada de simplesmente encadeada. iniciaremos com o desenvolvimento de uma versão simples. que é utilizado para existem muitas soluções. elementos mostradas na Figura 1. Este artigo apresenta uma explicação do funcionamento de uma sar esses dados na memória das máquinas. ligações são estabelecidas nos dois sentidos. deve guardar os dados refe- Quando as ligações são estabelecidas em apenas um rentes à correspondente posição da lista. cujo princípio de funcionamento é a cria- ção de ligações ou apontadores entre os seus elementos. dados sejam facilitadas de acordo com as necessidades construindo ao final uma solução mais sofisticada e que contemple da aplicação.Proibido copiar ou distribuir. mória uma estrutura como a apresentada na Figura 1. porém isso impõe uma ao longo deste artigo é o de uma lista duplamente encadeada. Todos os direitos reservados para DevMedia 15 . rísticas de implementação da estrutura de dados utilizada. Nesta classe são declarados também os class No{ public No proximo. ou dado=obj. porém. diferentes métodos. } seja. Portanto. como está representado na Figura 2. No caso do método de consulta. Código da classe No. Representação de uma lista duplamente encadeada 16 Copyright . representar o primeiro e o último elemento armazenados na public Object dado. do tipo No. A classe que representa o nó de uma lista último. é declarado um atributo do seus nós inicial e final. Nesta classe também está implementado { proximo = prox. conforme a inicialização realizada no No(Object obj. Este valor pode ser utilizado para verificar se o elemento foi inserido Para a classe No mostrada na listagem foram definidos dois corretamente. ação bastante comum é a possibilidade de o método de inserção Figura 2. um para cada caso. No prox. Também é declarado um valor inteiro como atributo. e outro construtor para o à posição solicitada é fornecida como resposta. Em Listagem 2. as ligações com os seus vizinhos são inicializadas Inserção e remoção da lista com as respectivas referências passadas como parâmetros ao Para completar as funcionalidades da classe apresentada na construtor e armazenadas nos atributos correspondentes). pondentes aos métodos de inserção. como nos casos de elementos a serem inseridos no meio da lista (portanto. remoção e busca. consultar e remover elementos da lista encadeada. para public No(Object obj){ armazenar o tamanho atual da lista. um método de acesso para o valor do tamanho da lista. como no correspondente à posição da lista que foi removida. que retorna o novo tamanho da lista como resultado. início. permitindo ao caso de se estar instanciando o primeiro nó da lista (portanto os objeto que manipula a lista realizar qualquer cálculo necessário atributos que representam as conexões ao próximo nó e ao nó com o mesmo. sem as implementações corres- Listagem 1. do tipo ListaDupEncadeada. os métodos de inserção e remoção para listas podem ambos os casos. Deste modo. conectados entre si em Java. Resumindo. na qual estes métodos serão implementados. que é a superclasse para todas as classes definidas cadeada é constituída de elementos ou nós. ao criar uma lista. o que será assunto em os elementos armazenados na lista qual é o primeiro e qual é o um próximo artigo). Além zada com qualquer tipo de dado que por ventura venha a ser disso. uma referência anterior são inicializados como null. associada não está ligado a outros nós da lista). a mesma se encontrará vazia.Java 3D: Criando e movimentando formas geométricas em Java alterar o código dela a cada novo tipo de dado a ser armazenado. Para representar a lista também se faz necessária a declaração de recomenda-se adotar um tipo de referência que possa ser utili. a referência ao objeto que representa o dado a ser implementados para permitir executar estas operações no ser armazenado no nó é recebida como parâmetro. o que é possível realizar com A lista encadeada é definida não apenas pelos nós que represen. mas nenhuma caso em que já se sabe a quais elementos o novo nó estará ligado. que é anterior = ant. atualizado nos métodos de inserção e remoção. são necessários métodos deve ser executada pela diferenciação dos parâmetros. que indicam dentre deste tipo é a parametrização de classes. Todos os direitos reservados para DevMedia . proximo = null. uma lista duplamente en- tipo Object. comparando-o com o tamanho da lista antes da construtores: um para o caso no qual ainda não se sabe quais são solicitação de inserção. permitindo com isso que qualquer objeto seja tratado em uma determinada sequência (definida pela aplicação que faz como sendo do tipo Object (uma alternativa ao uso do atributo uso da lista) e também de duas referências. ou também é possível tam os seus elementos. que servem para public No anterior. uma classe. A classe que representa a lista duplamente encadeada é apre- sentada na Listagem 2.Proibido copiar ou distribuir. com a instanciação de um objeto anterior=null. indicando que este elemento para o objeto que representa o dado. alteração é realizada na lista ou em seus nós. sobrecarregar estes métodos. informando qual das três situações lizadas nestes elementos/nós. dado = obj. Já o método de remoção retorna o dado os elementos aos quais o novo nó da lista estará ligado. No ant) construtor da classe. ou informação. tem-se a declaração de um método de in- serção. Continuando com as funcionalidades disponíveis na classe } } ListaDupEncadeada. mas também pelas operações que são rea. Deste modo. no final ou no meio da lista. que serão detalhados mais adiante. a implementação da classe também precisa conhecer os armazenado na lista. Outra situ- para inserir. atributos descritos anteriormente. duplamente encadeada é apresentada na Listagem 1. lista. as referências ao primeiro e último elementos serão nulas e seu tamanho será zero. if(pos == 1)//inserir no inicio da lista .anterior destes tamanho = 0. e o nó que antes estava como início da lista passa return tamanho. public int getTamanho(){ return tamanho. } inicio = fim = no.proximo = no.. null).Proibido copiar ou distribuir. então é necessário percorrer as conexões entre os elementos até que se encontre a posição in- public ListaDupEncadeada() { inicio = null. também se já existe algum elemento na lista ou se a mesma ainda pos--. novo elemento. ListaDupEncadeada. atualizando-se então as referências do atributo Listagem 2. para que este agora indique o tamanho++. { Para realizar a operação de inserção. Para isto é fim = null. { return obj. novo elemento deve ser inserido. } buto ListaDupEncadeada. por exemplo. } public Object consulta(int pos) else // já existem elementos na lista { { No aux = inicio. Se for solicitado que o aux. em primeiro lugar é neces. int pos) public int insere(Object obj. { return aux. .ou (tamanho == 0) tamanho--. estiver entre 1 e o tamanho da lista. } public int insere(Object obj. Todos os direitos reservados para DevMedia 17 . aux... . int pos){ { No no. null. Copyright . } else if(pos == tamanho + 1)//inserir no final da lista De uma maneira geral. ou qual a posição que deve ser fim. aux. se a posição de inserção do novo elemento int tamanho. verificar { aux = aux. Listagem 3. O método de inserção que recebe a posição do novo fim = no. dicada e então inserir o novo elemento entre dois nós.dado. elemento é apresentado na Listagem 3 e o método que remove uma } else// inserir no meio da lista determinada posição da lista é implementado na Listagem 4.. se for solicitado que o novo elemento de se desejar criar uma lista ordenada. Código de uma classe para uma lista duplamente encadeada. novo elemento ocupe a posição de índice 1.anterior).inicio.proximo = no. entre 1 e o tamanho da lista mais 1. return tamanho. No fim. é possível realizar as operações de { inserção e remoção informando-se em qual posição da lista o no = new No(obj. nós e informar quais são estes nós para o novo elemento da lista. } no = new No(obj. aux. no = new No(obj). ocupe a posição de índice igual ao tamanho da lista mais 1. sário verificar se a posição de inserção está no intervalo válido. ou while(pos > 1) seja. Código do método de inserção. está vazia. // inserir na posição de aux mento na lista. fim). if(inicio == null)//primeiro elemento .. } if(pos < 1 || pos > tamanho + 1) // posição solicitada fora do intervalo public Object remove(int pos) return tamanho. if(obj == null) return tamanho. ele será colocado no final. Caso já exista pelo menos um ele. tamanho++. No inicio. com a posição passada como parâmetro..buscar na lista o local correto do elemento.anterior. no caso Seguindo a mesma lógica. No aux = inicio. e em caso positivo o novo elemento passa a ser tanto } o início quanto o final da lista.proximo. { Object obj = null. necessário alterar as ligações de No.anterior = no. atualizando-se em seguida as referências do atri. removida.lista vazia . } inicio. inicio. Como último caso.anterior = no. } então a ser o segundo. } conforme o código da Listagem 3.proximo e No. e da mesma forma que no início. o novo elemento passa a ser o último da lista e o que antes era o último public class ListaDupEncadeada { passa a ser o penúltimo. então a operação de inserção é realizada de acordo no = new No(obj. na sequência.fim. inicio = no. ele será colocado no } início da lista. é necessário navegar pelos en. tanto na inserção quanto // remover o elemento aux na remoção. isto é. esta referência é retornada como resultado. Todos os direitos reservados para DevMedia . uma referência para o objeto que represen. ou seja. considerando o que estiver mais nós no encadeamento da lista não é afetada. while(pos > 1){ No caso de a solicitação não poder ser realizada. ao realizar a navegação por todos elemento da lista e. são realizados para determinar se a consulta é válida. para então iniciar a navegação aos de inserção e remoção. apenas com o cuidado de se manipu. Com um laço controlado por um rência nula é retornada (esta também é uma situação que pode contador é fácil realizar esta tarefa. Para os casos especiais de se desejar consultar o DupEncadeada. Em todos os casos.ant. a partir do início ou do final da lista. uma referência aux = aux. este método de busca irá visitar cada nó para as condições de lista vazia e índice fora do intervalo válido diversas vezes até que todos os nós da lista sejam acessados. a nova 18 Copyright . é apresentado o código correspondente à remoção de um elemento } da lista encadeada. o primeiro e do início ou do final da lista.prox.dado. porém é necessário também poder consultar o seu O código apresentado na Listagem 5 sempre realiza a consulta a conteúdo. para então retornar a referência do objeto armazenado de imediato. cada nó da lista para obter os dados neles armazenados. o que será visto em um próximo artigo). da lista devem ser consultados.prox. desejar remover um nó do meio da lista.consulta() é chamado com o parâmetro “2”. com a ressalva de que a ordem dos a partir do início ou do final. Nos dois primeiros casos } o procedimento é similar. remover um elemento do meio da lista. } else if(pos == tamanho)//remover o último elemento da lista mero de nós visitados até chegar ao índice solicitado. nula é retornada. para então { realizar a remoção. algumas verificações.ant. basta acessar a referência conforme o código apresentado na Listagem 5. exceções. e caso não Para entender melhor esta situação. conforme o caso. e o procedimento antes de iniciar a navegação se a posição solicitada está na primeira de consulta.ant. Na Listagem 5 é próximo do elemento solicitado. novamente os testes os elementos da lista. o seu conteúdo é retornado desejada. indicando que não há nós na lista. todos os nós posição fora da lista. deste valor é realizado de forma similar ou na segunda metade da lista. No aux = inicio. if(pos == 1)//remover o primeiro elemento da lista { lar a referência do início ou do final da lista. três casos podem ocor. Em Object obj. e ao final do processo else //remover um elemento no meio da lista de remoção do nó. e if(pos < 1 || pos > tamanho) // posição solicitada fora do intervalo tanto a referência do início quanto a do final devem ser alteradas return null.dado. indicando que nenhum objeto foi removido (o pos--. apresentado o método de consulta baseado em um índice de um É importante perceber que. primeiro é necessário inicio = inicio. fim = fim. ou ainda se a lista estiver vazia. obj = fim. if(inicio == fim)//se existe apenas um elemento na lista . tamanho--. aux. ou seja. A partir disso. Na Listagem 4 aux. entre 1 e o tamanho da lista. considere uma lista cujo seja um índice válido. tamanho--.prox. passado como parâmetro. bastando chamar o método ser tratada com o lançamento de uma exceção). e primeiro ou o último elemento da lista.dado.prox = aux. return obj. elemento seja retornado. Na terceira iteração do laço. } ta o dado armazenado na lista é criada. um índice indicando qual é a posição a ser removida é obj = inicio.Java 3D: Criando e movimentando formas geométricas em Java A remoção de elementos da lista também precisa passar por Listagem 4. seguida é necessário saber se existe apenas um elemento.Proibido copiar ou distribuir. o método Lista- no nó solicitado. ou busca. uma refe. o que pode ser aprimorado verificando-se na lista a partir de algum parâmetro de busca. já na segunda iteração do laço. ou return obj. cadeamentos. } tratamento destas condições de erro. rer: remover o primeiro elemento. pode ser aprimorado utilizando-se o lançamento de obj = aux. contando-se o nú. ListaDupEncadeada.ant = aux. Código do método de remoção. remover o último elemento. A primeira delas é para saber se existe al- public Object remove(int pos) gum elemento ou se a lista está vazia e se a posição a ser removida { está no intervalo válido. deve ser possível solicitar um objeto armazenado partir do início da lista. { indicando que o elemento foi corretamente removido da lista.ou (tamanho == 1) para null. até a posição ao consultar o primeiro nó da lista.prox. especial no qual depois da remoção a lista passar a estar vazia. inicio = fim = null. Para tanto. caso if(inicio == null)//se a lista está vazia return null. como pode ser verificado. a solicitação de busca pede uma conteúdo deva ser exibido ao usuário. Assim. } Consultando a lista Com os métodos de inserção e remoção já é possível trabalhar com a lista. para retornar o o segundo nós são visitados para que o conteúdo do segundo dado correto. Já para o caso de se obj = inicio. Como no caso da { inserção.consulta() com os índices sequenciais de Para os casos de índices válidos.dado. encontrá-lo na sequência de encadeamentos. até encontrar a posição desejada. 2 e 3”.proximo. ou seja. que os atributos de uma classe devem ou seja. por exemplo. Assim.consulta(). public Object removeFim() { if(pos < 1 || pos > tamanho) // posição solicitada fora do intervalo return remove(tamanho). quando alguém ler um método que faz uso de sendo utilizada por uma aplicação que. Como pode ser verificado. while(pos > 1){ juntamente com a String que foi adicionada. de funcionar quando tentar acessar os elementos da lista e isso No exemplo são instanciadas seis Strings de teste para serem não for possível devido a uma ligação errada entre os nós. Lista. Permitir que outras classes façam isso pode tada na Listagem 7 uma classe que realiza algumas inserções em levar a situações em que as referências entre os nós da lista sejam uma lista. que é a variável de controle do laço. orientação a objetos. em seguida mostra o seu conteúdo e por fim remove os modificadas incorretamente. remoção de elementos que estão no meio da lista.insereFim(). como mostra a Listagem 6. mantendo o encapsu- insere(). basta chamar o método Listagem 8. facilitando assim a leitura do código que na lista que está sendo removido. o tamanho da lista é mostrado no console No aux = inicio. no final ou no elemento a elemento para cada operação de consulta. Casos especiais de inserção e remoção. que será utilizado por outras classes para auxiliar na ser conhecidos e manipulados apenas pela própria classe. inseridas na lista. if(inicio == null)//se a lista está vazia } return null. o que é feito utilizando-se um laço com um contador } // consulta o elemento aux variando de 1 até o tamanho da lista. o que Listagem 6. else //consulta um elemento no meio da lista o que pode ser utilizado para verificar se a inserção realmente { ocorreu. da O código apresentado até o momento é de uma classe utilitária. seguido do tamanho da lista após a remoção do elemento soli- Para tratar cada um dos casos. } public int insereFim(Object obj){ return insere(obj. quisado. As saídas produzidas por este teste são apresentadas na mente o código de inserção ou remoção. Este comportamento existe devido à return insere(obj. Lista. } if(pos==1)//consulta o primeiro elemento da lista return inicio.dado. Todos os direitos reservados para DevMedia 19 . Este problema seria solucionado facilmente se a classe que está utilizando a lista tivesse uma referência direta ao nó da lista com o Testando a lista qual está interagindo. acesse os seus dados.insereInicio() e Lista. Neste laço. os métodos Nestes casos não cabe o uso de versões sobrecarregadas dos mé. cada um dos return aux. necessita um objeto do tipo ListaDupEnceada.dado.Proibido copiar ou distribuir. para só então public int insereInicio(Object obj){ retornar o seu conteúdo. return null. else if(pos == tamanho)//consulta o último elemento da lista return fim. Lista. mas se uma lista com muitos elementos estiver no código. tamanho + 1). Uma opção para solucionar esta situação. Código do método de consulta. lamento e permitindo o acesso a elementos específicos da lista por Copyright . pois a funcionalidade de cada um é ligeiramente diferente. Casos especiais de inserção e remoção Depois de mostrar o conteúdo. aux = aux.removeFim(). será fácil entender quando realizar a ordenação dos dados. } public Object consulta(int pos) public Object removeInicio() { { return remove(1). Para verificar o seu funcionamento é apresen.remove(). Para listas de pequeno porte isso e também se deseja distinguir esta funcionalidade textualmente não é um problema. então o fato de se percorrer a lista um novo elemento está sendo inserido no início.chamada do método de consulta recebe o parâmetro “3”. No exemplo. elementos da lista. que realiza a inserção para qualquer um dos casos com os parâ. O valor de cada elemento é obtido da lista com uma chamada ao método Lista.dado. citado. Neste solução de problemas que envolvem a guarda e organização de caso a ideia é que apenas a classe que implementa a lista conheça e dados em memória. fazendo com que a aplicação deixe elementos na ordem inversa à qual foram inseridos. faz com que o método visite os nós “1. Listagem 5. o qual é mostrado no console utiliza a implementação da lista encadeada em questão. os nós da lista são removidos Como as operações de inserção e remoção na primeira e últimas chamando-se os métodos Lista. Mas isso fere a ideia de encapsulamento. Para a inserção são chamados os métodos Lista. o conteúdo da lista pode ser pes- pos--. não é necessário escrever nova. é comum existir um método espe. definição da estrutura da lista encadeada. implementados necessitam percorrer todo o encadeamento de nós todos.removeInicio() e posições são muito utilizadas. nos casos de consulta e inserção ou metros corretos. 1). elementos consultados é mostrado no console juntamente com o } } seu valor de índice. A cada chamada a estes métodos o tamanho da lista é retornado. e o mesmo vale para as operações de remoção de inserção torna o uso desta implementação muito custoso. Uma vez inseridos os dados. Estes métodos retornam o dado armazenado cífico para cada uma. remoção ou meio da lista. out.consulta() lida com os acessos aos elementos da lista não é eficiente.println(lista. Como a solução anterior propõe a criação de uma referência Listagem 7.println(lista. que seja necessário percorrer a lista. que é o fato de permitir mesma lista simultaneamente.println(“Tamanho: “ +lista.println(lista.getTamanho()). esta tarefa recebe o nome de iterador (o padrão de projeto Iterator) e é descrita de percorrer os nós da lista é facilmente realizável. Implementando um iterator Uma possível solução para melhorar o desempenho do método O iterador é um objeto que permite o acesso aos elementos em de consulta seria modificá-lo para utilizar um atributo protegido uma estrutura de dados sem que seja necessário conhecer como que armazene a posição atual. Esta solução tação do método de busca apresentado anteriormente.out.out. também a referência ao nó atual seja atualizada para o próximo nó.println(“Tamanho: “ +lista. Bastante promissor. pois isso permite que os valores de ligação entre String e=”str teste 05”. Listagem 8. senta uma grave falha ao fornecer uma referência do nó da lista String d=”str teste 04”. e a cada nova chamada ao método os dados estão organizados. já observado. System. um segundo método apenas uma referência para o nó atual no processo de iterar pelos elementos da lista. Inserindo: str teste 02 -> Tamanho: 5 Inserindo: str teste 01 -> Tamanho: 6 for(int i = 1.println(“Inserindo: “ + b + “ -> Tamanho: “ + val). Tamanho: 5 System.out.out.println(“Posição “ + i + “: ->” + lista.println(“Tamanho: “ +lista.insereInicio(f ). Outro motivo para utilizar um iterator para acessar os elementos ou o nó anterior.insere(c.remove(2)). Código da classe de teste para a lista duplamente encadeada. porém esta ideia também apre- String c=”str teste 03”.removeInicio()). os elementos da lista sejam alterados por métodos que não são os da classe ListaDupEncadeada. Inserindo: str teste 06 -> Tamanho: 1 val = lista.println(“Inserindo: “ + d + “ -> Tamanho: “ + val).println(lista.println(“Tamanho: “ +lista.getTamanho()). str teste 01 System.println(“Tamanho: “ +lista. esta referência poderia ser fornecida à classe que public static void main(String[] args) { irá utilizar a lista encadeada.out. Posição 6: ->str teste 01 System.out. abordagens de maneira a permitir o acesso aos elementos da System. Saída do teste da lista duplamente encadeada. Tamanho: 0 System. Por exemplo: enquanto um método apenas um laço de busca ocorra de cada vez.getTamanho()).println(“Inserindo: “ + f + “ -> Tamanho: “ + val). System. eliminando a restrição de poder existir apenas um laço String a=”str teste 01”. é a utilização de uma classe interna que fornece pode enviar os mesmos elementos pela rede. str teste 04 System.println(“Inserindo: “ + e + “ -> Tamanho: “ + val). str teste 02 System. devido a utilizar salva o conteúdo da lista em um arquivo.out.out. de acordo com a direção da busca. da classe.out.insereFim(a).println(“Inserindo: “ + c + “ -> Tamanho: “ + val).insereFim(b). val = lista.println(“Inserindo: “ + a + “ -> Tamanho: “ + val). Posição 3: ->str teste 04 Posição 4: ->str teste 06 Posição 5: ->str teste 02 System.out. str teste 05 System.out. o que também não é satisfatório. à classe cliente. de cada vez.getTamanho()). Tamanho: 4 System.getTamanho().println(“Tamanho: “ +lista.out.out.out. Todos os direitos reservados para DevMedia . Com a implemen- acesso aos elementos da lista de forma controlada. str teste 03 System. permitindo assim que cada vez ListaDupEncadeada lista = new ListaDupEncadeada(). ou seja.println(“Tamanho: “ +lista.println(“Tamanho: “ +lista.getTamanho()). como em detalhes a seguir. 2).out. a maneira como o ListaDupEncadeada.println(lista. Esta solução da estrutura de dados é que mais de um cliente pode utilizar a também possui uma grande desvantagem.out. String b=”str teste 02”. Inserindo: str teste 04 -> Tamanho: 3 Inserindo: str teste 03 -> Tamanho: 4 System.remove(2)).getTamanho()).getTamanho()).out.out. uma nova referência seja criada. System. ou seja.consulta(i)). int val.removeFim()). sem expor a representação a referência ao dado correspondente ao nó atual seja retornada e interna da classe que implementa a estrutura de dados em questão. Posição 1: ->str teste 05 Posição 2: ->str teste 03 System. 2).out. auxiliar a ser utilizada no laço que implementa a iteração com public class TesteLista_01 { os nós da lista. rompe o encapsulamento System. val = lista. Inserindo: str teste 05 -> Tamanho: 2 System.Java 3D: Criando e movimentando formas geométricas em Java outras classes.insere(d. i++) Tamanho: 6 System.println(lista. String f=”str teste 06”.removeFim()). val = lista. porém. Tamanho: 1 } str teste 06 } Tamanho: 0 20 Copyright .getTamanho()).println(“”).out. i<=lista.removeInicio()).Proibido copiar ou distribuir. Tamanho: 3 System. O padrão Iterator aproveita os conceitos descritos nestas duas val = lista. Tamanho: 2 System. System.out. lista por mais de um laço simultaneamente e também sem ferir o val = lista.insereInicio(e). Os métodos de navegação ImpIteradorLista. que será retornado após atualizar a // Retorna o dado associado ao nó atual public Object dado(). e remoção do nó atual. Com a implementação desta classe pronta. o valor a ser atribuído ao atributo não corresponde a um elemento da lista. de acordo com o solicitado. sendo realizados dois testes: um para saber se o iterador é // associado ao nó atual válido e outro para descobrir se o próximo ou o elemento anterior public Object anterior(). que corresponde ao primeiro nó da lista. Este fato pode ocorrer quando em um laço se utiliza um itera- Nesta interface devem ser declaradas todas as operações que tor. quando IteradorLista. a segunda chamada a IteradorLista.noAtual. possam solicitar os iteradores. Neste processo. utilizando a interface definida para isso. que per- Copyright . ficam claros os relacionamentos da classe Cliente com a interface Este nó é utilizado para acessar os elementos da lista sem que seja IteratorLista e com a classe ListaDupEncadeada. é necessário criar // Verifica se existe um nó antes do nó atual métodos de acesso para o iterator na classe ListaDupEncade- public boolean temAnterior(). O método ImpIteradorLista. Todos os direitos reservados para DevMedia 21 . podem ser declaradas operações de armazenado neste nó retornado. referência ao objeto que representa a informação guardada em public interface IteradorLista { ImpIteradorLista. portanto. e portanto passa a ser null. após verificarem que o iterador é válido. a navegação por seus nós será mais eficiente se realizada que o atributo ImpIteradorLista.noAtual para a primeira caixa. a referência de inserção antes ou após o nó atual. anterior(). acompanhando as atualizações no atributo a partir da referência Inicio. Logo após.noAtual como uma classe interna de ListaDupEncadeada. Apesar de a preciso navegar por todos os seus antecessores. sendo atribuído a ImpIteradorLista.proximo() coloca IteradorLista. mesmos. ao utilizarem um objeto do tipo } ListaDupEncadeada. e após percorrer todos os elementos armazenados na lista. ada para que outras classes. situação em que assume o um iterator que define operações de navegação e consulta aos valor null.noAtual estiver refe- renciando o terceiro elemento. A primeira chamada a IteradorLista.noAtual será atualizada para o próximo nó. proximo() atualiza o valor da referência IteradorLista. mentação de um novo meio de realizar as operações. // Coloca o iterador no próximo elemento da lista e retorna o dado dependendo do caso. Os relacionamentos entre esta nova interface e as classes que Para implementar o iterador é necessária uma referência a um fazem parte do padrão Iterator são apresentados na Figura 3. e ao se realizar a quarta chamada ao método.noAtual seja atualizado e o valor de navegação e consulta. da lista encadeada. que será utilizada para manipular instanciar e manipular objetos do tipo ImpIteradorLista. Diagrama de classes do Padrão Iterator noAtual depois de verificar se o iterador é válido.anterior() é chamado.proximo() é invocado para que o valor elementos armazenados na lista.dado() simplesmente retorna o objeto correspondente ao dado armazenado em ImpIteradorLista. o objetivo é // associado ao nó atual saber se o iterador está ou não na primeira ou na última posição public Object proximo(). ela é declarada como private. preciso garantir em todos os métodos da classe ImpIteradorLista deada.proximo() e ImpIteradorLista. sejam criadas de forma inadequada. ao realizar a navegação na lista em sentido contrário.noAtual. mas para isso é classe Cliente poder acessar diretamente a classe ListaDupEnca. Nesta interface tipo de declaração garante o encapsulamento dos dados e também devem ser declaradas todas as operações que serão executadas possibilita que outras classes consigam um acesso controlado aos para manipular os dados. Por exemplo: além das operações do atributo ImpIteradorLista. declarado como o atributo ImpIteradorLista.encapsulamento dos atributos desta. Esta situação pode ser melhor compreendida anali- a Listagem 10. Esta solução envolve a imple. referência de noAtual para o próximo elemento ou o anterior. Figura 3. // Coloca o iterador no elemento anterior da lista e retorna o dado da lista.noAtual é uma referência válida pela interface IteratorLista. a classe que implementa a interface IteradorLista é criada da lista. Este os dados armazenados na estrutura de dados. ImpIteradorLista. Já nos métodos de verificação. O mesmo ocorre quando o iterator está na primeira posição e o método IteradorLista. é válido. criam uma Listagem 9. porque o nó atual corresponde ao último elemento lista.noAtual no segundo nó. Isto porque a referência Na Listagem 9 é apresentada a declaração da interface para do iterator pode estar fora da lista. o que significa que apenas a classe ListaDupEncadeada pode se necessita de uma interface. neste caso.Proibido copiar ou distribuir. Para viabilizar a manipulação dos elementos armazenados na que não existe. elementos de uma lista duplamente encadeada. de acordo com o valor null. Interface de um iterador simples para uma lista duplamente encadeada. antes de executar a operação solicitada. onde nó da lista. são permitidas a outros objetos (Clientes) de realizarem com os o método IteradorLista. e para isso. De maneira a evitar que instâncias desta classe sando-se a Figura 2. // Verifica se existe um nó após o nó atual public boolean temProximo(). proximo().. que pode ser inicializado com a primeira ou a última } posição.dado. Depois de ser instanciado um objeto } do tipo ListaDupEncadeada e o mesmo já contiver elementos in- // Coloca o iterador no próximo elemento da lista e retorna o dado seridos.proximo() retorna o objeto correspondente à informação armazenada no // Verifica se existe um nó após o nó atual nó associado ao iterador ou. Como o método de navegação IteradorLista. 22 Copyright . recebido como resul- return obj. while controlado pelo conteúdo do iterador. ou seja. à mesma. Object obj = noAtual. return iterador.dado. laço de navegação pela lista encadeada.dado. Assim. Código da classe que implementa um iterador para uma lista dupla. Na Listagem 11 são mostrados dois métodos: um para solicitar public class ListaDupEncadeada { um iterador para o primeiro nó da lista e outro para o último . o laço for do primeiro teste (presente na Listagem 7) por um laço noAtual = noAtual.Proibido copiar ou distribuir. o nó atual será nulo e nenhuma iteração será possível iterador. diferindo // Coloca o iterador no elemento anterior da lista e retorna o dado // associado ao nó atual apenas na manipulação da lista. realizar cada uma das consultas solicitadas.noAtual = fim..proximo() // Verifica se existe um nó antes do nó atual public boolean temAnterior() { retornará null. return obj. a referência interna do iterador passará a ser null e a chamada seguinte ao método IteradorLista.. . como é o caso da implementação do método ListaDupEncadeada. sem que seja necessário um contador para in- public Object proximo() formar qual a posição desejada. Diferente da versão anterior da classe ListaDupEncadeada. Todos os direitos reservados para DevMedia . nó. correr toda a lista acessando cada nó apenas uma vez.anterior != null ? true : false.. primeiro é necessário solicitar um iterador noAtual = noAtual. { // Instanciar o novo iterador respondente à solicitação.anterior. o nó atual será nulo e nenhuma iteração será possível mente encadeada. O resultado desse teste é exatamente o mesmo do apresentado pelo código da Listagem 7. private class ImpIteradorLista implements IteradorLista { } public No noAtual. o que é realizado substituindo-se if(noAtual == null) return null. permitindo então a navegação pela ImpIteradorLista iterador = new ImpIteradorLista().. return noAtual. return iterador.proximo != null ? true : false. quando o iterador não é válido. // Retorna o dado associado ao nó atual Testando o iterator da lista public Object dado() { Como o iterator implementado é apenas uma nova opção de con- if(noAtual == null) return null. as consultas utilizando o iterator podem ser realizadas de // associado ao nó atual maneira sequencial. lista de forma linear. Métodos para solicitar iteradores para a lista encadeada. Esta condição é utilizada para controlar o return noAtual. public Object anterior() { e o número de vezes que cada elemento da lista é acessado para if(noAtual == null) return null. conforme } mostrado na Listagem 12. que para encontrar o // Caso a lista esteja vazia. // Instanciar o novo iterador ImpIteradorLista iterador = new ImpIteradorLista(). quando o último } nó for consultado.consulta(). iterador. Listagem 11. uma vez que a lista será percorrida { do início ao final pelo iterador. realizada da mesma maneira. evitando chamadas sucessivas ao // Inicializar o atributo noAtual com o primeiro elemento da lista método ListaDupEncadeada.. Object obj = noAtual. o que interrompe o laço após todos os elementos if(noAtual == null) return false. Para percorrer a lista. tado da chamada ao método IteradorLista.noAtual = inicio.proximo.consulta(). a } que faz uso do padrão iterator é mais eficiente por permitir per- } .. e não per- } correndo todo o encadeamento para cada consulta. um objeto do tipo ImpIteradorLista public IteradorLista iteradorInicio() é criado e o seu atributo noAtual é inicializado com o nó cor. public class ListaDupEncadeada { } . // Caso a lista esteja vazia. o public boolean temProximo() { if(noAtual == null) return false.Java 3D: Criando e movimentando formas geométricas em Java mitem interagir com a lista de maneira mais fácil e eficiente. elemento solicitado passa por todos os nós da lista. sulta aos elementos da lista. a inserção e a remoção de elementos é return noAtual. valor null é retornado. que é feita através do iterador. da lista serem mostrados. // Inicializar o atributo noAtual com o último elemento da lista Listagem 10. Em ambos os métodos.. aprimorando assim as suas opções public IteradorLista iteradorFim() { e melhorando o desempenho no uso da lista encadeada. O mesmo conceito pode ser utilizado para incluir no iterador os } métodos de inserção e remoção. html } } Apresentação sobre Estruturas de Dados.fee. Uma segunda maneira de utilizar o iterador na lista encadeada. Novamente.println(“Posição “ + i++ + “: ->” + iterador. { // Mostrar o valor armazenado em cada posição da lista http://www..com/iterator-pattern. } A utilização de uma classe própria como a apresentada deve ser considerada apenas para situações muito específicas. seja com relação à quantidade de memória uti..ufsc. pois já existem muitas APIs System. // Variável para receber o elemento armazenado na lista String str. presente em praticamente todos // Contador de posições os ambientes computacionais. isso O iterator da lista também pode ser utilizado de outra forma.unicamp.das.com/article/2073390/core-java/datastructures-and-algorithms- . Listagem 13.br/~jlopez/transp_ho4_2011.proximo(). o resultado do teste é exatamente o mesmo.html mais importantes para o desenvolvimento de aplicações de qua- lidade.br/~pf/algoritmos/aulas/lista. a implemen- // Mostra o valor armazenado em cada posição da lista tação deve ser muito bem avaliada. Copyright . Ao se deparar com situações como estas. dos dados na memória e assim possa aproveitar os recursos da http://www.javaworld.ic. solicitar o dado.iteradorInicio().oodesign. } pelos desenvolvedores e analistas. http://www. Este grande volume de dados. exigindo cada vez mais tanto dos // Iterador utilizado para percorrer a lista encadeada IteradorLista iterador = lista. No entanto. Listagem 12. juntamente com encadeada. Modificação no método de teste para utilizar o iterador na lista Com o grande poder dos processadores atuais.br É Mestre em Informática pela PUC-PR e doutorando em proximo() para o último elemento da lista e o método Iterador- Métodos Numéricos em Engenharia.usp. Todos os direitos reservados para DevMedia 23 .pdf lizada ou otimizando o tempo necessário para o processamento dos dados.temProximo()) Programação Orientada a Objetos.out.lca.dado()).. } http://www. part-1. duplamente-encadeada. http://www. public class TesteLista_03 { public static void main(String[] args) { Links: ..ime. mdmatrakas@yahoo. é fácil esquecer-se destes detalhes. porém public static void main(String[] args) { o volume de dados criados e manipulados pelos usuários está .. como mostrado na Listagem 13. para as quais as APIs não apresentem uma solução satisfatória. pela UFPR (Universidade Lista. aumentando rapidamente.pdf System.pdf A compreensão das estruturas de dados é um dos requisitos Conteúdo sobre Listas Encadeadas. http://www. iterador.anterior() para o primeiro elemento da lista. // Iterador utilizado para percorrer a lista encadeada Artigo sobre o padrão de projeto Iterator. não só na linguagem Java.br/cursos/PooJava/Aulas/poojava. disponíveis com códigos já testados que podem ser utilizados . Federal do Paraná). não é permitido chamar o método IteradorLista. ou seja.println(“Posição “ + i++ + “: ->” + str).com/design_pattern/ // Laço para percorrer a lista utilizando o iterador while(iterador. http://www. Esta segunda forma de acesso deve ser adotada quando não se pode permitir que o iterador se torne Miguel Diogenes Matrakas inválido. int i = 1.br/~romulo/discipli/cad-fei/Aula-EstruturasDados-04f-Lista- melhor maneira. Trabalha como professor de Java há quatro anos nas Faculdades Anglo-Americano de Foz do Iguaçu. organizá-los.dca.html // Contador de posições Tutorial sobre Padrões de projeto em Java..out.com. IteradorLista iterador = lista. Artigo sobre Estruturas de Dados..Proibido copiar ou distribuir.. pois permite que o programador entenda a organização Algoritmos e Estruturas de Dados. equipamentos quanto dos profissionais envolvidos das diversas áreas de TI. apenas alterando-se a Autor maneira de utilizar o iterador. exige também novas técnicas para int i = 1.iteradorInicio(). levando ao desenvolvimento de novas estruturas // Laço para percorrer a lista utilizando o iterador while((str = (String) iterador.unicamp.tutorialspoint. o grande volume de memória disponível nos diversos dispositi- public class TesteLista_02 { vos computacionais.proximo()) != null) de dados. não exclui a necessidade e importância de conhecer a teoria e os verificando-se a existência de um próximo elemento antes de conceitos adotados por estas bibliotecas. Mapeamento objeto relacional O framework ORM mais difundido atualmente é o Segundo Bauer e King (2005. e por serem largamente utilizados os objetos relacionados com as tabelas alteradas necessitarão de em projetos de software orientados a objetos. análise geral sobre seu funcionamento. objetos. com a necessidade de desenvolver sistemas cada vez mais complexos e que levem em conta fatores como facilidade de manuten.Proibido copiar ou distribuir. têm optado pelo uso do paradigma de pro. durante o processo de análise e desenvolvimento e simples os principais conceitos relativos ao framework. Todos os direitos reservados para DevMedia . Suas principais vantagens são simplificar a cional significa “persistir de maneira automática e transparente persistência dos dados. muitos desenvolve. frameworks de mapeamento objeto relacional (Object assim como uma visão geral sobre seu funcionamento e como Relational Mapping – ORM). orientado a objetos e objeto-relacional). faz-se mudanças. o ambiente de desenvolvimento NetBeans e sabem que um banco de dados puramente orientado a o sistema de gerenciamento de banco de dados (SGBD) MySQL. e que também programação Java. seus principais recursos. de informação que mostre de forma prática como desenvolver ternativa para os desenvolvedores de sistemas que não uma aplicação orientada a objetos com acesso a um banco de querem abrir mão dos benefícios que a linguagem de dados relacional. relacional há muito tempo vem sendo o modelo mais visando preencher a lacuna semântica existente entre as estruturas aceito e utilizado quando se deseja armazenar dados. p. Aprenderemos de forma básica dores. apresentando suas características. os bancos de dados com que possíveis mudanças na base de dados impliquem em relacionais estão fortemente presentes no núcleo da um menor impacto sobre a aplicação. ficam evidentes as vantagens da ado- necessário um mapeamento entre as tabelas do banco de ção do Hibernate no desenvolvimento de sistemas orientados a dados e os objetos da aplicação. objetos está longe de conseguir uma boa aceitação no O Hibernate será usado como a camada de persistência que deverá mercado. Neste artigo mostraremos como desenvolver uma aplicação Java uti- ção e reaproveitamento de código. de tabelas e sua representação através de classes. MySQL e NetBeans.11). A ideia por trás do ORM é ter um mecanismo fazer a interface entre a aplicação e o MySQL. transformar dados de uma representação 24 Copyright . mapeamento objeto rela- Hibernate. que faça a conversão entre os objetos do sistema e as tabelas do banco de dados relacional. permitir que a aplicação per. Para tanto. tível o paradigma da orientação a objetos e o paradigma Com base nisso.Hibernate 4: Aprenda a persistir os dados de sua aplicação Hibernate 4: Aprenda a persistir os dados de sua aplicação Este artigo demonstra na prática como armazenar dados utilizando a versão mais recente do Hibernate H Fique por dentro oje em dia. este artigo visa fazer um estudo sobre o Hiber- de entidade e relacionamento. se comparado a outros modelos (rede. faremos uma de software. hierárquico. A fim de tornar compa. utilizá-lo em meio à construção de um exemplo simples de sistema O mapeamento objeto relacional surge como uma al. os objetos de um aplicativo para tabelas em um banco de dados maneça totalmente orientada a objetos e também fazer relacional. como configurar um ambiente gramação orientada a objetos. p. foram desenvolvidos nate. Por outro lado. tendo em vista que apenas empresa moderna. o modelo de desenvolvimento e como realizar o mapeamento objeto-relacional. Em essência. lizando Hibernate. Sendo assim.23). serão empregados à linguagem de programação orientada a objetos possui. Segundo Bauer e King (2005. outros projetos Hibernate. herança. Além de realizar o mapeamento objeto relacional. persistência em bancos de dados do tipo NoSQL. por implementar a especificação Java Pedido. Em outras pala. o ideal seria tirar a lógica de negócio de podemos invocar o Hibernate através de uma aplicação Swing. O Hibernate OGM. Hibernate. principal fonte. publicado na Easy Java Magazine 25. Após como um banco de dados ou um arquivo. por sua vez. que é o pro- será menor. Java para tabelas de dados (e dos tipos de dados Java para os da dor dedica uma parte considerável do seu tempo construindo SQL). Se o banco de dados possui uma tabela chamada composições e coleções. por Gavin King em 2001. o Hibernate disponibiliza outras é desenvolvido em um tempo menor. provavelmente. ou mesmo a partir de um framework como Spring Hibernate MVC. JSF. de uma camada intermediária de mapeamento objeto relacional A partir da versão 5 do Java a configuração do Hibernate passou facilita muito a vida do programador. de anotações responsáveis por implementar a validação nas en- gramador pode mudar de SGBD sem ter que realizar alterações tidades da aplicação. muitas vezes o programa. pois ela é responsável por a ser realizada através de anotações do JPA. O Hibernate gera as chamadas SQL e libera o desenvolvedor comandos em linguagem de banco de dados para realizar o arma. código do sistema diminui. Persistense API (JPA). entre outras 95% das tarefas mais comuns de persistência de dados”. Hibernate utiliza Reflection. por não restringir a arquitetura da aplicação minada Pedido. parte da mesma brand. O Hibernate Validator consiste em um conjunto de banco de dados e oferece maior portabilidade. Trata-se de uma poderosa linguagem de consulta os desenvolvedores. do trabalho manual de transformação. foi criado que se parece com o SQL. além de oficial: “o Hibernate pretende retirar do desenvolvedor cerca de métodos para calcular os juros. O Hibernate é uma ferramenta open source de mapeamento O HQL (Hibernate Query Language) é um dialeto SQL próprio objeto relacional para aplicações Java de grande aceitação entre do Hibernate. como a memória RAM. o projeto embrião. simplesmente as adicionamos vras. Por fim. ou qualquer outra aplicação Java que mantenha acesso a um banco de dados. de memória secundária. para dispositivos enxuto. Nesse caso. sobre os atributos/métodos de acordo com o que projetamos. o mapeamento objeto relacional proporciona: “Entendendo Anotações”. disponibilizadas através de cinco projetos. o desenvolver tem a possibilidade de trabalhar a classes desenvolvidas com agregações (aquelas classes que diretamente com objetos persistentes e suas propriedades. funcionalidades. Anotações são metadados que são para a estrutura existente no banco de dados relacional. Para mais informações. jeto original. Distribuído com a licença LGPL. adicionados ao código-fonte para descrever características dele A persistência diz respeito ao armazenamento de dados que e como vantagens possibilitou um código mais intuitivo e mais estão em meio volátil. Assim. Sendo assim. que serão usados e por ser amplamente documentado. de modo a garantir a isso. do sistema. sendo dedicado à persistência de • Desempenho: o tempo economizado no desenvolvimento pode objetos em bancos de dados relacionais. assim como do mapeamento objeto relacional. valor total do pedido. Segundo a documentação para receber e alterar os dados dos campos das tabelas. leia o artigo Como vantagens. com extensivo de stored procedures e triggers não irão se beneficiar do maior popularidade. ao invés usam outras classes em suas operações). deixando de lado traduzir as estruturas e operações do sistema orientado a objetos os complexos arquivos XML. sistemas em que a maior parte da lógica da aplica. as classes passam a ser mais simples e com isso o sistema característica do framework. • Manutenibilidade: tendo em vista que o número de linhas de A seguir veremos cada um e suas respectivas funções. sem dúvida. trabalha a no software. Quando utilizamos anotações. dentro do banco e transferir para a aplicação. o framework de incluindo os conceitos de herança. mantendo o programa zenamento dos dados no banco de dados relacional. Essa classe definirá atributos. O Hibernate Search é o ser dedicado a implementar melhorias no sistema. Sua principal característica é a transformação das classes em No desenvolvimento de um sistema. A presença portável para quaisquer bancos de dados SQL. o trabalho de manutenção também O primeiro e mais conhecido é o Hibernate ORM. polimorfismo. sendo. como o disco rígido. responsável por implementar buscas textuais no modelo de dados • Independência de fornecedor: Abstrai do aplicativo o sistema das aplicações. uma classe deno. sobretudo por dar suporte to.para a outra”. mas é totalmente orientada a objetos. • Produtividade: com a eliminação dos códigos SQL no código. pois não O Hibernate pode ser utilizado por uma aplicação Java direta- há necessidade de um modelo de objetos para trabalhar a lógica mente ou podemos acessá-lo através de outro framework.Proibido copiar ou distribuir. o objeto lógico. core do Hibernate. Apesar de todos esses projetos fazerem Dessa forma. etc. o pro. o Hi- bernate Tools disponibiliza uma série de ferramentas em linhas O objetivo do ORM é construir um código mais uniforme e que de comando que automatizam diversas tarefas referentes aos utilize de fato as características da linguagem orientada a objetos. permanência das informações de um determinado estado de um Para ler as anotações e aplicar as informações de mapeamento. a referência ção encontra-se dentro do banco de dados ou mesmo fazem uso é sempre relacionada ao Hibernate ORM. a aplicação possuirá. Todos os direitos reservados para DevMedia 25 . o Java Runtime Environment (JRE) analisa essas anotações. Isto é. polimorfismo e encapsulamen- persistência de dados mais utilizado. quando se fala em Hibernate. operações relacionadas à tabela. de realizar as operações diretamente nas tabelas e colunas da base Copyright . consiste em manter os dados em meio físico recuperável. e o a lista de tecnologias da plataforma Java EE 7. Hibernate e EhCache.) e os outros frameworks que utilizam a JPA. Para este artigo optamos pela segunda opção. e a segunda é de forma a pasta lib conterá todas as bibliotecas visualizadas na Figura 1. A primeira é através de uma configuração automati.jar que estão dentro da /lib/required/. framework com a introdução de Multi-Tenancy. cação. A URL do site oficial se encontra na seção Links. Ademais. desen. os jars (as bibliotecas). obter as bibliotecas necessárias para a utilização do Hibernate. ou pode ser as bibliotecas do hibernate-ehcache. Após o lançamento da especifi. a Sun reconheceu que o mapeamento objeto. Finalizado o download. possa ser que está disponível em dois tipos de arquivos compactados: zip compartilhada entre diversos inquilinos ou tenants. um cache de segundo nível. por trás dos panos ele faz uso de chamadas JDBC. que vamos cha- Após conhecermos os principais conceitos relacionados ao Hi. Todos os direitos reservados para DevMedia . manual. a documentação em inglês. ma- Algum tempo depois do Hibernate fazer sucesso entre os nuais em várias línguas (inclusive português). ou banco de dados. zada. opcional que fornece o histórico de auditoria de alterações sobre sar do Hibernate ter surgido antes da JPA e ter sido utilizado como as entidades. também utilizada para prover recursos solicitados pela comunidade. de connection pooling. mar de lib. utilizando o Maven. com a garantia e tar. que provêm integração entre usado como uma implementação da JPA. Neste artigo utilizaremos a versão 4.1.3. sendo executada em um servidor. hibernate-c3p0. o código-fonte e desenvolvedores. (EJB. aplicação interaja com o banco de dados.34-bin. etc. todos os arquivos .Proibido copiar ou distribuir. lançada em maio a integração entre o Hibernate e o C3P0 connection pool library. que provê Atualmente. ele também a implementa. módulo Uma situação que gera dúvidas nos desenvolvedores é que ape. São elas: o Hibernate já disponibilizava. do Hibernate e que devem ser incluídos no classpath do projeto. Hibernate. Para empregar o Hiber. • /lib/required/ – contém todos os jars obrigatórios para utilização Como a Sun tinha maior alcance e influência sobre os desenvol. Sendo assim. o Maven. visto que Com essas bibliotecas é possível construir nossa aplicação. dados.persistence. vedores do que os criadores do Hibernate. Na seção Links encontra-se o endereço para download do dri- Download e instalação das bibliotecas ver. artefato principal do tornasse conhecida rapidamente. Apesar de utilizarmos lar os softwares que nos auxiliarão no desenvolvimento e também o Hibernate. Trata-se de um arquivo zip. bernate. Esta nova especificação. incorporando melhorias e novos recursos connection pool library. é preciso ter o driver JDBC do banco de o framework funciona. mantém o foco na hibernate-proxool.Hibernate 4: Aprenda a persistir os dados de sua aplicação de dados. aumentando assim a distância entre o desenvolvimento para a utilização da primeira opção é preciso conhecer e dominar das regras de negócio e o banco de dados. JSF. do site oficial do framework as bibliotecas obrigatórias e todas Entre as novidades podemos citar a introdução do ServiceRegistry. por exemplo. que fornece o framework compatível com as outras especificações da Java EE a implementação do JPA ao Hibernate. Dentro desse diretório podemos citar levando em conta tão somente suas características. A pasta gerada Hibernate e JPA contém. que compõe biblioteca usada para prover recursos de connection pooling. assim como alguns dos seus recursos. que provê integração entre o Hibernate e o Infinispan. realize o download da versão 4.gz. sendo assim necessária a adição do driver. as suas dependências. de 2013 através da JSR 338.8 que é uma nova forma do Hibernate gerenciar os seus serviços. que Antes de começar a utilizar o Hibernate é necessário baixar trouxe várias melhorias e facilidades para os desenvolvedores. Final. foi natural que a JPA se Dentro dessa pasta está o hibernate-core. • /lib/optional/ – contém as bibliotecas necessárias para recursos ou seja. e criou a especificação JPA baseando-se nas funcionalidades que Dentro da pasta lib existem algumas subpastas. O driver é um componente de software que permite que a No entanto. pode ser utilizado como um framework independente. antes de começarmos a codificar. deve-se utilizar as anotações e nispan. referência para a sua especificação. busque pela seção de downloads e localize o tetural Multi-Tenancy permite que uma instância da aplicação Hibernate ORM. a JPA se encontra na versão 2. vamos partir para a apresentação da parte prática. 26 Copyright . colocando-o junto com os arquivos da pasta lib. O modelo arqui. jar. Após acessar o site. é importante insta. entre outros arquivos.8. opcionais do Hibernate. Configuração O primeiro passo é copiar em uma nova pasta. • /lib/envers/ – nessa pasta encontra-se o hibernate-envers. que se encontram dentro da pasta lib e é o relacional era algo necessário no desenvolvimento de aplicações que nos interessa nesse momento. Em seguida. Feito o download. Ao todo são 10 arquivos.1. volvendo uma aplicação que possibilitará ao leitor visualizar como Além dessas bibliotecas. que provê a integração entre Hibernate e Proxool atualização da API. Faça o download do arquivo de acordo com o formato de isolamento dos dados. hibernate-infi- nate como implementação da JPA. de sua preferência. descompacte Existem duas maneiras de configurar o ambiente para usar o o pacote e extraia dele o arquivo mysql-connector-java-5. os criadores do Hibernate a implementaram para manter • /lib/jpa/ – contém a biblioteca hibernate-entitymanager. também é um cache de segundo nível.3. que no momento da elaboração desse material era a última Outra novidade diz respeito a melhorias na performance do versão lançada. recentemente foi lançada a versão 4 do Hibernate. descompacte o arquivo. que classes que se encontram no pacote javax. Hibernate que possui toda a parte central do framework.*. uma nova 5. O próximo passo é escolher o tipo de instalação. etc. Neste artigo foi utilizada a versão 8. Como o instalador já está em português. O usuário deve Copyright . Todos os direitos reservados para DevMedia 27 . uma tela deve O banco de dados que utilizaremos será o MySQL. Como está tudo certo. O processo de instalação do NetBeans é bastante simples. Na seção Links você encontrará Figura 2. No passo seguinte. Essa tela exibe os termos gratuita. que é um ambiente de desenvolvimento integrado (IDE) gratuito e de código aberto. Na seção Links também está disponível o endereço onde pode ser obtido o JDK. tipo existe uma breve explicação sobre cada um. Entre suas características podemos citar: a facilidade Next. O NetBeans oferece aos desenvolvedores as ferramentas necessá- rias para criar aplicativos profissionais para desktop. plo. Os passos para instalação do IDE são os que seguem: 1. Na seção Links você encontrará o endereço para download e 4. Tela de boas-vindas do NetBeans o endereço para download do software. excelente desempenho e estabilidade. execute-o clicando duas vezes com o botão esquerdo do mouse e espere descompactar os arqui- vos. Clique no vem ser executados para instalar o banco de dados no sistema: botão Instalar e espere o processo terminar. solicitando que o usuário aguarde enquanto o Sistema Operacional configura o instalador do SGBD. neste mesmo tópico foi disponi- bilizado o endereço de um material que mostra o passo a passo de como instalar o NetBeans. Bibliotecas obrigatórias Ambiente de desenvolvimento Neste artigo optamos por utilizar o NetBeans. Se você ainda não o instalou. Na próxima tela. de código aberto. por exem.6. como mostra a Figura 2.Proibido copiar ou distribuir. 1. clique no botão Próximo para continuar.1. uma opção ser mostrada (conforme a Figura 4). sendo necessário apenas ter o Java SE Development Kit (JDK) 6 ou superior instalado no sistema. 3. notará que o caminho do JDK automaticamente será preenchido e aparecerá na tela. A versão adotada neste artigo software e algumas informações adicionais como. 2. portabilidade.Figura 1.0. Após o Sistema Operacional iniciar a instalação. Escolha da pasta de instalação da IDE e do JDK clique no botão Próximo para continuar a instalação. a instalação do IDE não poderá continuar. A etapa seguinte é dependente da instalação do JDK. O sistema gerenciador de banco de dados 2. o tamanho total da instalação e a opção que permite ao Após descarregar o instalador do MySQL os seguintes passos de- NetBeans verificar atualizações de forma automática. Caso o leitor tenha dificuldade em instalá-lo. será mostrada a pasta de instalação do mais informações sobre o software.22 Community Server. Aceite os termos e clique em volvedores. empresariais. foi a 5. Mas se já instalou. Abaixo de cada interface gráfica de fácil utilização. conforme a Figura 3. Clique no instalador e depois em executar. simples e muito utilizado pelos desen. Concluída a instalação. do contrato de licença do produto. apenas Figura 3. 3. marque a opção Eu aceito os termos no contrato de licença e clique no botão Próximo. Feito isso. janela será exibida. basta clicar no botão Finalizar. Após baixar o instalador. no manuseio. web e para dispositivos móveis. mudança da mensagem presente na coluna Status. como pode ser MySQL Server. Feito a escolha. Todos os direitos reservados para DevMedia . clique em Next. Clique então em Execute. conforme a Figura 6. 12. Figura 7. Neste passo vamos manter os valores 4. Após todas as configurações serem aplicadas. Em seguida. 9. ção para o MySQL Server. 8. clique em Next. A tela seguinte (Figura 8) pede para definir a senha do admi- 5. MySQL como um serviço do Sistema Operacional Windows. como sugere a Figura 5. Finalizada a instalação.Hibernate 4: Aprenda a persistir os dados de sua aplicação escolher a opção que melhor atenda aos seus propósitos. Termos do contrato de licença. Confirmadas estas informações. que passará de 11. Figura 6. clique mais uma vez Next (ver visto na Figura 9. para dar 10. a próxima tela permite ao usuário configurar o sequência à instalação. o que pode ser visto através da Mantenha os valores default e clique em Next. Figura 7).Proibido copiar ou distribuir. anterior. clique em 7. Figura 5. que serão aplicados. Configuração do MySQL Server. Feito isso. Produtos que serão instalados. padrão e clicar em Next. Após a instalação ser concluída. é possível ver os produtos escolhidos no passo nistrador. o próximo passo é configurar o Execute para que a configuração seja realizada. A janela que aparecerá detalha todos os passos de configuração Ready to Download para Complete. Nesse momento o usuário deve escolher o tipo de configura- clique em Next. Portanto. A próxima tela oferece ao usuário a opção de escolher os pro. uma tela Figura 4. 28 Copyright . Escolhendo o tipo de instalação. Por fim. Sendo assim. dutos que deseja instalar. 6. informe uma senha e clique em Next. listar funcionários e excluir. Figura 8. Todos os direitos reservados para DevMedia 29 . Com o intuito de manter um aspecto didático e propiciar o fácil entendimento desse material. Configuração do MySQL completada. Criação do projeto no NetBeans Com o banco de dados pronto. Com o MySQL instalado. clique em Arquivo > Novo Projeto (Ctrl- Shift-N) e na tela que aparecer. como salvar. Por fim. abra-o e crie o banco empresa conforme o script SQL indicado na Listagem 1. Como utilizaremos annotations. vamos partir para o Java. USE EMPRESA. 10. basta clicar em Next. Clique então em Finish. vamos partir para a elaboração de uma apli- cação desktop. permite que o usuário cancele todas as configurações realizadas antes de serem aplicadas. Logo após. clique em Próximo. apresentada na Figura 10. conforme a Figura 11. SALARIO DOUBLE. Definindo a senha do administrador. Listagem 1. é importante que o projeto utilize o Java 1. 01. Desenvolvendo o cadastro de funcionários Agora que temos o banco de dados instalado. Caso o usuário não queira cancelar e deseje aplicar as configurações. CARGO VARCHAR(30). CODIGO_INT NOT NULL AUTO-INCREMENT. 03. As informações que cada funcionário carregará são: código. 06.5 ou superior. cargo. CREATE database empresa. Esse banco contém apenas uma tabela. 11. Neste momento. nome. ENDERECO VARCHAR (100). Logo após. Script para criação do banco de dados. NOME VARCHAR(100). Figura 9. selecione Java na coluna Categorias e Aplicação Java na coluna Projetos. 07. Figura 10. uma nova janela informa que a configuração do MySQL Server foi realizada. 08.Proibido copiar ou distribuir. Copyright . 02. com o NetBeans aberto. ). Funcionario. aparecerá uma janela explicitando que a instalação foi concluída.mostrando o fim do processo de configuração aparecerá. CREATE TABLE FUNCIONARIO ( 05. endereço e salário. criando um novo projeto no NetBeans. atualizar. Aplicando configuração no MySQL Server. CPF. chamada Funcionario. assim como o ambiente de desenvolvimento e as bibliotecas necessárias para rodar o Hibernate. o sistema que construiremos conterá apenas uma classe. A partir dela serão construídas as principais operações realizadas sobre um cadastro. apenas clique em Finish. 09. CPF VARCHAR(20). O objetivo dessa aplicação é gerenciar o cadastro de funcionários de uma companhia. PRIMARY KEY (ID) 12. Criando o banco de dados O primeiro passo é criar o banco de dados. Dito isso. 13. Essa janela. 04. 14. Essa é a nossa classe de negócio da aplicação e será Já a anotação @id. vista na linha 11. haverá uma tabela relacionada a essa classe no banco de dados e lançando mão de annotations.Proibido copiar ou distribuir. Com o pacote criado. Essas bibliotecas encontram-se na pasta lib criada anteriormente. Todos os direitos reservados para DevMedia . selecione Bibliotecas na coluna Categorias e. Ela aparece antes do nome da classe e sinaliza que Nosso próximo passo é criar e mapear a entidade Funcionario. clique com o botão direito do mouse sobre ele. e na tela que aparecer dê o nome Funcionario à classe. endereco e cargo). a próxima etapa consiste em adicionar ao classpath deste as bibliotecas do Hibernate. selecione Novo > Pacote Java e informe seu nome. encapsulados através dos métodos de acesso get e set. e também disponibilizam o construtor padrão. Logo Note que o POJO mostrado na Listagem 2 possui seis atributos após. assim como a biblioteca referente ao driver do MySQL. Adicionando as bibliotecas ao projeto Figura 12. Na linha 5 podemos verificar a anotação @Entity. assim como seus ao projeto. como mostra a Figura 13. clique com o botão Figura 14. A classe de negócio ficará dentro do pacote com. conforme a Figura 14. Para adicionar as bibliotecas ao classpath. Classes desse tipo são classes Java simples. clique em Adicionar JAR/Pasta. Funcionario. devemos criar a classe que os objetos desta serão persistidos. Figura 11. cpf. Para criá-lo.jm. é utilizada para indicar qual mapeada pelo Hibernate como uma tabela no banco de dados. nome. escolha a opção Novo > Classe Java. Por fim. principal ano- Construindo a entidade tação do JPA. assim como mostra a Figura 12.entidade. clique em Ok. com a aba Compilar selecionada. definidas como No nosso caso. clique com o botão direito do mouse sobre o projeto HibernateJM. Para isso. Criando a classe Funcionario direito do mouse sobre o projeto e escolha a opção Propriedades. POJOs (Plain Old Java Object). Na tela que aparecer. Escolha do tipo de projeto Figura 13. respectivos métodos get e set e também o construtor padrão. salario. Por fim. Criando um novo projeto Concluída a criação do projeto. Elas contêm todos os seus atributos clique em Finalizar. selecione todas as bibliotecas e as adicione (codigo.Hibernate 4: Aprenda a persistir os dados de sua aplicação Na tela seguinte é necessário informar o nome do projeto. atributo de uma classe anotada com @Entity será mapeado como 30 Copyright . localize a pasta lib. nomeie o projeto como “HibernateJM”. No nosso caso. pois é o modo mais simples e o mais possível conseguir uma representação textual de um objeto do tipo difundido pelos desenvolvedores. utilizaremos o arquivo XML para Por fim. 55. o método toString() foi criado na linha 85 para que seja configurar o Hibernate. public void setCargo(String cargo) { 21. this. Nesse artigo.cargo = cargo. 77.codigo = id. 43. 26. 80. } 85.nome = nome. this. package com. } 19. @Column 63. 33. 01. double salario. 46. public int getId() { 83. @Column 67. 60. public void setId(int id) { endereco=” + endereco 42. public void setSalario(double salario) { 29.xml). 18. } 30. fica considerado que o nome as suas configurações e indicando os arquivos de mapeamento das tabelas e colunas será exatamente igual ao nome das classes programaticamente. @Column 69.properties com não adicionamos essa informação.jm. 28. 64. 20. @Table 51. 73. return “Funcionario [codigo=” + codigo + “. 08. } 11. return cargo. 12. salario=” + salario+”]”. Uma anotação que geralmente acompanha @id é a anotação Configurando a aplicação @GeneratedValue.hibernate. 74. 87. nome=” + nome + “. private String cpf. 16. 39. Listagem 2. public Funcionario(String nome. private String cargo. public String getEndereco() { 09. 86.entidade. 04. 31. para cada um dos funcionários cadastrados. 71. } 81. 02. } 03. 66.cpf = cpf. this. como ticamente. 06. return cpf. return nome. Configuration) e inserindo as suas propriedades programa- bastando colocar o nome entre parênteses. } 88. Existem três pelo banco no momento em que um novo registro for inserido. 14. this.AUTO) 58. } 27. 41. public String getNome() { Copyright . String cpf.endereco = endereco. Todos os direitos reservados para DevMedia 31 . public void setEndereco(String endereco) { 13.nome = nome. Funcionario. + “. } 15. public class Funcionario implements Serializable { 52. 78. Esta serve para indicar que Nesse momento precisamos dizer ao Hibernate onde está o valor do atributo que compõe a chave primária deve ser gerado nosso banco de dados e como se conectar a ele. private String endereco. private static final long serialVersionUID = 1L. Perceba que todas as informações de um funcionário a propriedade codigo manterá um único valor de identificação podem ser obtidas em forma de texto invocando esse método. que instanciando um objeto de configuração (org. 54. } 34. this. 35. 70. String cargo. return codigo. public void setCpf(String cpf ) { 36. private double salario. 24. 59. return endereco. 79. ou mesmo usando um arquivo XML (hi- e suas propriedades. return salario. 82. private int codigo. @Column 57. } 44. @GeneratedValue(strategy = GenerationType. modos diferentes para configurar a engine do Hibernate. a saber: Ainda podemos utilizar as anotações @Column e @Table. 89. String endereco) { 75.cpf = cpf. } 07.cargo = cargo.cfg. cargo=” + cargo + “. 62.salario = salario. 76. } 23. utilizando um arquivo de extensão . public void setNome(String nome) { 05. this. this. 47. são usadas para personalizar o nome das tabelas e das colunas.cfg. } 38. this.salario = salario. this. } 45. Código da classe Funcionario.endereco = endereco. 22.Proibido copiar ou distribuir. 84. @Id 56. Sendo assim. public double getSalario() { 25. 37. public Funcionario() {} 72. this. bernate. public String getCargo() { 17. 10. public String toString() { 40. private String nome. public String getCpf() { 32.a chave primária da tabela correspondente à classe. this. 49. @Column 61. //imports omitidos 48. @Entity 50. presente na linha 13. 68. @Column 65. cpf=” + cpf + “. 53. Seu conteúdo deve ser gerar problemas.mysql. Para a maioria dos bancos de dados recebem suporte por parte do isso.dialect. e também a referência de do driver JDBC utilizado. <property name=”hibernate.driver_class”> sionFactory ao contexto da aplicação. Portanto. Para tanto.dialect”>org. <session-factory> 05.acessobd. serão disponibilizadas pela aplicação exemplo. <mapping class=”com. auxiliar foram implementadas.Proibido copiar ou distribuir.cfg. atualizando ape- Listagem 3. Além disso. instâncias de objetos do tipo org. informa ao Hibernate um estado interno imutável.cfg.connection.url.cfg. quais comandos SQL gerar diante de um banco de dados relacional os seus atributos internos não serão modificados. configuração do Hibernate.jm. Por esse o MySQL.net/ driver do banco. <property name=”hibernate. clique com o botão direito sobre o projeto. a classe Hi- empresa?zeroDateTimeBehavior=convertToNull</property> bernateUtil será criada dentro do pacote com. interno inclui o metadata referente ao mapeamento Objeto • connection. 12. </hibernate-configuration> Feito isso. Para criar 08.sourceforge.MySQL Configurada a aplicação.jm.hibernate.acessobd” como terísticas do Hibernate é a independência de fornecedor com nome. O código dessa classe pode ser visto na Definition) e na linha 3 temos o elemento raiz <hibernate-configu. com. clique com o botão direito do mouse sobre o projeto HibernateJM. clique com o botão direito do mouse sobre o pacote recém-criado. não sendo necessária qualquer alteração 01.Session. devemos criar o arquivo hibernate.Funcionario”/> como nome. agora vamos criar a classe auxiliar Dialect</property> HibernateUtil. local A SessionFactory é uma classe de infraestrutura do Hibernate onde se inicia a configuração da conexão com o banco de dados e que implementa o design pattern Abstract Factory para construir também são adicionadas as informações de mapeamento. <!DOCTYPE hibernate-configuration PUBLIC “-//Hibernate/Hibernate Configuration DTD 3.connection.Driver</property> 07. Essas ins- As propriedades configuradas são analisadas a seguir: tâncias são usadas para realizar as tarefas de persistência do • dialect (linha 5): especifica o dialeto com o qual o Hibernate framework. <hibernate-configuration> Criando a conexão com o banco de dados 04. Para isso.driver_class (linha 6): especifica o nome da classe Relacional das entidades do sistema. basta modificar os atributos connection .password (linha 9): especifica a senha do usuário SessionFactory.connection. connection. uma vez que ela é criada.hibernate. Nesse caso. <property name=”hibernate. o arquivo de configuração e a classe está tudo conforme o esperado. No nosso projeto. semelhante ao da Listagem 3. Como mencionado anteriormente. Para alterar o SGBD. sionFactory(). criaremos uma classe que será • mapping (linha 11): informa as classes que estão mapeadas responsável por viabilizar todas as operações de persistência que para realizar operações no banco. a classe HibernateUtil utiliza-se do método estático • connection. seguido pelo elemento <session-factory>. 32 Copyright . <property name=”hibernate.url”>jdbc:mysql://localhost:3306/ Com o intuito de manter a organização do projeto. motivo. Assim.show_sql”>true</property> HibernateJM.Hibernate 4: Aprenda a persistir os dados de sua aplicação Sendo assim. Primeiramente. Este estado em particular. Listagem 4. isto é. selecione Novo > framework e por isso poderiam substituir a nossa opção sem Documento XML e o chame de hibernate. <?xml version=”1.jdbc.url (linha 7): especifica a URL de conexão com o getSessionFactory().xml. Conteúdo do arquivo hibernate. <property name=”hibernate. mesmo nome. escolha a opção Novo > Classe Java e insira “HibernateUtil” no campo Este arquivo começa com a definição do DTD (Document Type relacionado ao nome.0” encoding=”UTF-8”?> no código da aplicação. utilizamos o MySQL. <property name=”hibernate. que é responsável por construir a instância de • connection. visto na linha 12.xml.password”>1234</property> 10. • show_sql (linha 10): flag que permite tornar visível no console o SQL que o Hibernate está gerando. clique com o botão direito do mouse sobre o projeto 09.0//EN” “http://hibernate.entidade.dtd”> 03. Todos os direitos reservados para DevMedia .driver_class e dialect. não se esqueça de trocar o 02.jm. mas deve ficar fora de qualquer pacote existente na aplicação. No nosso caso. nas três linhas do arquivo de configuração é possível trocar o SGBD utilizado por outro.jm. para oferecer sempre a banco de dados. • connection.connection. </session-factory> 13. trata-se do driver para quem irá fornecer as conexões com o banco de dados. Assim. a classe Funcio. mesma instância de um SessionFactory no contexto da aplicação.username (linha 8): refere-se ao nome de usuário Por fim. o desenvolvedor pode Persistindo dados no banco copiar e colar os comandos no banco de dados para verificar se Agora que a classe mapeada.util. uma das principais carac.0.username”>root</property> esse pacote. escolha Novo > Pacote Java e informe “com. ration>. que relação ao SGBD.jm.util” 11. hibernate-configuration-3. na linha 21. temos o método privado estático buildSes- com o qual o Hibernate deve se conectar ao banco de dados. na linha 4. no entanto. ou seja. escolha Novo > Pacote Java e informe “com. devemos nario está mapeada para realizar operações sobre a tabela de criar uma classe dentro do pacote com. responsável por entregar uma instância de Ses- 06. Essa construção é feita com base no arquivo de com o qual o Hibernate deve se conectar ao banco. devemos criar o pacote. sendo que cada instância de SessionFactory possui se comunicará com a base de dados. crie a classe HibernateUtil. return sessionFactory. . semelhante ao apresentado na Listagem 5. Copyright . Com isso. considerado como uma sessão de comunicação com o banco 19. dentro do construtor da classe FuncionarioDAO. o método adicionarFuncionario() recebe como 13. O código fonte dessa classe deve ficar 02.hibernate.registry. 22. presente na linha 17. clique sobre ele com o botão di- reito do mouse. Depois de criado o pacote.Proibido copiar ou distribuir. sessionFactory = configuration. Todos os direitos reservados para DevMedia 33 . de dados através de uma conexão JDBC. = new StandardServiceRegistryBuilder() 18. pesados e lentos de se criar. if (sessionFactory == null) { 14. } Por fim. 12.build(). invocado na linha 18. } 26. um registro é adicionado na 24. 07.ServiceRegistry. Objetos desse tipo armazenam 09. import org.boot.cfg.buildSessionFactory(serviceRegistry). 05. Transaction(). na linha 19. import org. Código da classe HibernateUtil.SessionFactory. 11.configure(). escolha Novo > Classe Java e dê o nome à classe 01.service. ServiceRegistry serviceRegistry a partir de um SessionFactory. realiza a 23.hibernate.applySettings(configuration. o commit finaliza a transação e a sessão é fechada na linha 26. o método save(). de FuncionarioDAO. tabela funcionario de acordo com os valores definidos no objeto. package util.Configuration. 25. no banco de dados. Esse objeto deve ser criado uma única vez 08. 21. 04. Configuration configuration = new Configuration(). Um objeto Session pode ser 17. public class HibernateUtil { durante a execução da aplicação. import org.StandardServiceRegistryBuilder. A operação begin- 20. import org.hibernate. Para isso. } Em seguida. Na linha 9. um SessionFactory. os mapeamentos e configurações do Hibernate e são muito 10. o método getSessionFactory() é invocado para a criação de 06.hibernate. na linha 13 é obtida uma sessão 16. private static SessionFactory sessionFactory. inicia uma transação. 03. persistência do objeto. parâmetro os dados do funcionário e realiza a inserção deste 15.getProperties()).Listagem 4. public static SessionFactory getSessionFactory() { Já na linha 12. session. try { double salario.Proibido copiar ou distribuir. return cod_func. e. Para tal. } 08. 57.Hibernate 4: Aprenda a persistir os dados de sua aplicação Além deste. Session session = factory. esses métodos possuem a mesma estrutura com Primeiramente. 09.rollback(). atualizarFuncionario() e ListarFuncionarios(). tx = session. o método createCriteria(). 11. devemos criar o pacote que arma- relação ao método que já foi explicado. public FuncionarioDAO() { 53. } 21. codigoFuncionario). package com. podemos Em nosso teste. 68.openSession(). int salario) { 10.getSessionFactory(). Feito isso.setSalario(salario). tx. if (tx != null) { 38. } 55.close(). try { 31.close().beginTransaction(). Session session = factory. e. //inicia a transacao 62. tx.commit(). public void apagarFuncionario(Integer codigoFuncionario) { 28. } finally { 23. private static SessionFactory factory. //salva na sessao o objeto 64.teste” como nome.out. 20.openSession(). } finally { 05. cod_func = (Integer) session. a saber: apagar. cria informe “com. zenará essa classe. classe de teste.commit(). uma query passando como parâmetro a classe que vai ser pesquisa.printStackTrace(). factory = HibernateUtil. vamos criar apenas mais uma Funcionario(). 61 e 79. salario. 49. 36.rollback().class.openSession().class). 47. 76.save(new Funcionario 63. Por sua vez. 32. tx. 82. } 73.//executa o commit 65. da classe FuncionarioDAO. funcionario = (Funcionario) obj.beginTransaction().rollback(). session. estão todas as operações de persistência que iremos Testando a aplicação realizar sobre o banco.commit(). try { 80.println(funcionario. try { 61.beginTransaction(). Transaction tx = null. public void atualizarFuncionario(Integer codigoFuncionario. outros três métodos foram criados. 04. 43. Todos os direitos reservados para DevMedia . escolha Novo > Pacote Java e Na linha 37. linha 61. Nesse momento. na escolha Novo > Classe Java e dê o nome à classe de TesteHibernate. } 44.get 33.toString()). remove o Na linha 7 a variável funcionarioDao armazena uma instância funcionário passado como parâmetro da base de dados. tx. tx = session. List funcionarios = session. 51. Session session = factory. 02. Transaction tx = null. 70. 79. 18. 74. 83. 60.rollback(). public class FuncionarioDAO { 50. } catch (HibernateException e) { 89. 86. que realiza a inserção de um funcionário no banco Listagem 5.printStackTrace().delete(funcionario). 17. } 69. 30.update(funcionario). for (Object obj : funcionarios) { 84. public void listarFuncionarios() { 77. da. 24.get 14. mouse sobre o projeto HibernateJM.list(). Sendo assim. 15. } catch (HibernateException e) { (nome. 35. session. Integer cod_func = null. } 25.createCriteria(Funcionario. Funcionario. 46. 16.printStackTrace(). (Funcionario. session. String cpf. 13.printStackTrace(). String cargo. O código fonte dessa classe deve ficar igual ao da Listagem 6. } 40. Funcionario funcionario = (Funcionario) session. } 03. endereco)). Funcionario funcionario = (Funcionario) session. Basicamente. System. funcionario.beginTransaction(). conforme o esperado. } 07. Transaction tx = null.jm. if (tx != null) { 67. 22. cpf. Funcionario funcionario = null. String endereco) { 58. 54. 72. no nosso caso. chamado na linha 79. 01. //imports omitidos 48. 34. a primeira operação chamada foi a adicionar- realizar alguns testes para avaliar se tudo está funcionando Funcionario().close().commit(). 59.openSession(). no entanto. clique com o botão direito do mouse sobre esse pacote. session.close(). 06.class. if (tx != null) { 19. } 87. } 75. conforme demonstrado na Listagem 5.acessobd. clique com o botão direito do se nas linhas 37. assim como o método delete(). com toda a aplicação finalizada. } 45. tx. Nessa classe. 41. tx = session. } 26. session. (Funcionario. } catch (HibernateException e) { 37. da classe Session. } finally { 42. } catch (HibernateException e) { 66. } finally { 71. 12. 39. public Integer adicionarFuncionario(String nome. o método update(). 29. } 34 Copyright . 85. e. As diferenças encontram. 78. codigoFuncionario). tx. tx = session. cargo. tx. if (tx != null) { 90. 52. Classe DAO que contém todas as operações que serão realizadas no banco de dados. Transaction tx = null. 81. 56. Session session = factory. realiza a atualização do objeto passado como parâmetro. tx. 27. 88.jm. e. values (?. cargo as cargo2_0_0_. nome. “Esteticista”. Hibernate: select this_. cpf=02637848867.adicionarFuncionario 06. Copyright . dourados. o console da IDE mostrará os comandos SQL exe. caso nenhum erro ocorra.Proibido copiar ou distribuir. 01. ?) 02. endereco=Rua Abadia dos (“Carlos Martins”.0] (“Yujo Rodrigues”. cargo as cargo2_0_0_. salario) Listagem 6. Código da classe de teste.nome as cado.codigo as codigo1_0_0_. ?. endereco=Rua do passado como parâmetro. (“Camila Rodrigues”. ?. quanto pela portabilidade oferecida pelos update. salario=3000. Na linha 5. nome. o comando delete sinaliza que um dialetos de banco de dados. salario=5600. Essa operação foi repetida quatro vezes. teremos quatro funcionários inseridos no banco de dados. salario=3000. Funcionario [codigo=58. Todos os direitos reservados para DevMedia 35 . ?. tanto por dar mais legibilida- rios) cadastrados. é realizada uma atualização através do comando do banco de dados. (“Clenio Rocha”.cpf as cpf3_0_0_. nome=Clenio Rocha. this_. ?.nome as nome5_0_0_. da linha 9 à seguintes.0] “Rua Abadia dos dourados”). o método apagarFuncionario(). cpf=?. Hibernate: delete from Funcionario where codigo=? 14. Funcionario [codigo=60. endereco=Rua Araxa.de dados. 5000).0] 15. “Analista de TI”. this_. 11. funcionari0_.cargo as cargo2_0_0_.salario as salario6_0_0_ from Funcionario this_ 09. cargo=Gerente de Projeto. “Gerente de Projeto”. cargo=Analista de TI.cargo as cargo2_0_0_. Hibernate: insert into Funcionario (cargo. ?. vamos realizar mais um select. funcionari0_. as endereco4_0_0_. salario=70000.0] 12. funcionari0_. 12.listarFuncionarios(). salario) 05. Integer funcionario3 = funcionarioDao.listarFuncionarios(). “02637848867”.endereco 18. todos esses registros são listados. ao final da execução desse trecho de código e todos os funcionários presentes na base. nome=Camila Rodrigues. 04.codigo=? 13. ?.endereco as endereco4_0_0_. funcionarioDao. A estabilidade em que se encontra o cutados pelo Hibernate. Já o método atualizarFuncionario(). o Hibernate também é a solução configurações. funcionari0_. 70000. this_. endereco. funcionarioDao. nome=Yujo Rodrigues. this_. Hibernate: insert into Funcionario (cargo. cargo=Analista de TI. cargo=Analista de TI. Assim.adicionarFuncionario cpf=07898378863.salario 13. 15. endereco. Note que nas quatro primeiras linhas são projeto e as facilidades que ele oferece ao programador estão entre exibidos os inserts referentes à adição dos funcionários no banco suas principais características. Funcionario [codigo=60.codigo as codigo1_0_0_. temos um select para retornar e apresentar novamente linha 12. exposto na Listagem 7 no console da IDE NetBeans. ?. public class TesteHibernate { values (?. ?. cpf.adicionarFuncionario 07. Funcionario [codigo=61. Para confirmar todos esses passos. cpf=06493084765. cpf.cpf as cpf3_0_0_. “05855578533”.jm. cpf.nome as nome5_0_0_. funcionari0_.adicionarFuncionario 10. cpf. salario=5000. nas linhas de cada SGBD. Hibernate: insert into Funcionario (cargo. nome5_0_0_. 05. o Hibernate faz com que a camada de persistência seja cláusula where. endereco. funcionari0_. salario=? where codigo=? 16. this_. ?) 02. } as salario6_0_0_ from Funcionario funcionari0_ where funcionari0_. remove da base de dados o funcionário 17. salario) 03. funcionari0_.endereco as endereco4_0_0_. “Analista de TI”. chamado na linha cpf=06493084765.codigo as codigo1_0_0_.salario as salario6_0_0_ from Funcionario this_ 15. } as endereco4_0_0_. chamamos novamente o Garimpeiro. cpf=05855578533. nome=?. 17. Integer funcionario4 = funcionarioDao.salario 19. funcionarioDao. FuncionarioDAO funcionarioDao = new FuncionarioDAO(). endereco=Rua do “Rua Araxa”). funcionari0_. o método listarFuncionarios() é invo. as salario6_0_0_ from Funcionario funcionari0_ where funcionari0_. nome. Funcionario [codigo=61. 09.0] método listarFuncionarios(). 5600. this_. funcionari0_. endereco. package com. 11. Funcionario [codigo=58. cargo=Esteticista. Logo após. cujo objetivo é obter todos os registros (funcioná. values (?. 07. endereco=Rua Rio Paranaiba. nome=Clenio Rocha. Saída da execução da classe TesteHibernate. Hibernate: select funcionari0_.teste. mas dessa vez diretamente no terminal do MySQL. Hibernate: select this_. encontramos um select. endereco=Rua Araxa. cargo=Esteticista. como parâmetro. this_. para verificar o estado dos objetos persistidos no banco. atualiza o valor referente ao salário do funcionário passado 16. Por fim. na linha 14.codigo=? 14. ?. this_. 5600. Hibernate: select funcionari0_. Além de ser um ótimo framework open source para realização Como a flag show_log está definida como true no arquivo de do mapeamento objeto relacional.0] chamado na linha 16. “Rua Rio Paranaiba”). Hibernate: insert into Funcionario (cargo. this_. mais adotada atualmente.cpf as cpf3_0_0_. cargo=Gerente de Projeto. Funcionario [codigo=59. ?) 04.cpf as cpf3_0_0_. salario=70000. Integer funcionario2 = funcionarioDao.endereco “Rua do Garimpeiro”). O resultado Resultado da execução dessa execução deverá ser semelhante ao conteúdo exposto na A execução da classe TesteHibernate apresentará o resultado Figura 15. Listagem 7. 08. nome. Por fim. cpf=07898378863. de ao código. funcionari0_. de dados. this_. Em seguida. na linha 13. salario) 01. pois o desenvolvedor abstrai o conceito de tabelas Já na linha 11. ?. endereco=?. “07898378863”. nome=Yujo Rodrigues.codigo as codigo1_0_0_. Em seguida. Esse método recupera e lista todos os funcionários cadas. salario=5600. desenvolvida com muita liberdade. ?. Garimpeiro. “06493084765”. funcionarioDao. 03. que abstraem as particularidades funcionário foi removido da base de dados. 3000. public static void main(String[] args) { values (?.apagarFuncionario(funcionario1).nome as 08. nome=Camila Rodrigues. Integer funcionario1 = funcionarioDao. Em seguida.atualizarFuncionario(funcionario1.0] 10. cpf=05855578533. ?. sem a Assim. trados. por sua vez. endereco=Rua Rio Paranaiba. Hibernate: update Funcionario set cargo=?. ?) 06. nome5_0_0_. nome=Carlos Martins. que é viabilizar a persistência de Site Oficial do Hibernate.html no Instituto Federal do Triângulo Mineiro (IFTM). Visão do banco de dados após a execução da classe de teste Links: Enfim. mestre em Ciência da Compu- tação pela Universidade Federal de Uberlândia (UFU) e doutorando em Computação pela Universidade Federal Fluminense (UFF). e preenche com sobras a http://hibernate.com/technetwork/java/javase/downloads/jdk-7-netbeans-install-pt- br-433855. Tem experiência na área de Ciência da Computação.br É formado em Ciência da Computação pela Universidade Federal de Uberlândia (UFU).oracle.edu.com/ Site driver do MySQL. Gavin King. Livro Java Persistence com Hibernate.org/ lacuna existente entre as estruturas relacionais e a programação Site Oficial do MySQL. Processo de instalação do JDK. Todos os direitos reservados para DevMedia . 2005. OCWCD e ITIL. especialização em Análise e Desenvolvimento de Sistemas Aplicados a Gestão Empresarial https://netbeans.mysql.com/downloads/connector/j/ Carlos Alberto Silva Site Oficial do NetBeans. 36 Copyright .html Christian Bauer. http://www. de Uberlândia (UFU). http://www. Trabalha na empresa Algar Telecom como Analista de TI e atualmente é aluno do curso de Processo de instalação do NetBeans. com especialização em Desenvolvimento http://www.oracle. com ênfase em Engenharia de Software.org É formado em Ciência da Computação pela Universidade Federal Site para download do JDK.com https://netbeans. Possui as seguintes certificações: OCJP. podemos afirmar que o framework desempenha muito bem o que lhe é incumbido. casilvamg@hotmail. Desenvolvimento de Aplicações para Internet e Sistemas Multiagentes. orientada a objetos.Proibido copiar ou distribuir. Figura 15. Autor http://dev. Atualmente é professor do Instituto Federal do Triângulo Mineiro (IFTM). objetos em bases de dados relacionais.org/community/releases/80/install_pt_BR.Hibernate 4: Aprenda a persistir os dados de sua aplicação Autor Eduardo Augusto Silvestre eduardosilvestre@iftm. especialista em Governança de TI pela Universidade Federal de Lavras (UFLA).com/technetwork/java/javase/downloads Java pelo Centro Universitário do Triângulo (UNITRI).mysql. Todos os direitos reservados para DevMedia 37 .Proibido copiar ou distribuir.Copyright .