Diego Botelho Martins

NOTE: To use the advanced features of this site you need javascript turned on.

Home RSS MySQL (Imasters)
Fontes RSS
iMasters - Seção: mysql
iMasters - Comunidade de profissionais, estudantes e mestres em tecnlogias e ferramentas voltadas para o desenvolvimento web

  • Solucionando ROLE_ SpringSecurity

    Olá, pessoal!

    No artigo de hoje, quero complementar dois artigos do Edson Gonçalves sobre Spring Security:

    Muitos desenvolvedores que pretendem usar Spring Security (SS) em suas apps JEE sofrem para implementar a regra de segurança quando já existem dados cadastrados no BD e não se quer mudar as informações no BD para prefixar o ROLE_, que é requerido pelo SS.

    Vamos ver, então, como resolver esse problema, com o qual você pode se deparar em sistema legado.

    Lets go...

    Recomendado:

    Iniciando

    Vou levar em conta que você já tem implementado o SS conforme este artigo do Edson Gonçalves. Caso contrário, leia o texto do Gonçalves antes de continuar com o meu.

    Mas, para refrescar sua mente, lembre-se de que o role deve ter ROLE_ prefixado para que as regras funcionem. Isso é default no SS. Há como alterar, porém pesquisei muito e não consegui implementar. No fórum SS existem várias sugestões, mas nenhuma delas foi mais eficiente que prefix o ROLE_ com os dados trazido do BD.

    Desenvolvendo

    A solução é mais simples que podemos imaginar, você vai precisar apenas prefix o ROLE_. Para quem usa MySQL, temos a função concat(). Enfim, verifique na documentação do seu banco como concatenar.

    A seguir, mostramos com o MySQL. É simples demais, confira:

    authorities-by-username-query="SELECT
    username, concat('ROLE_',authority) FROM users where username = ? "

    O código completo fica assim:

    < jdbc-user-service data-source-ref="dataSource"users-by-username-query="SELECT username, password, 'true' as 
    enable FROM users WHERE username=?" authorities-by-username-query="SELECT username, concat('ROLE_',authority) FROM
    users where username = ? "/>

    Outra dica é se a coluna do usuario/password não for o que o Spring Security espera, basta você fazer conforme o código a seguir:

    <jdbc-user-service
    data-source-ref="dataSource" users-by-username-query="SELECT
    us.email as username, us.senha as password, 'true' as enable FROM usuario as us WHERE email=?"
    authorities-by-username-query="SELECTus.email as username, us.tipo as authority FROM usuario us where email= ?"/>
    </authentication-provider>

    Vou ficando por aqui, espero que tenham gostado. Abraços e até o próximo!



  • Desenvolvimento em Java 2.0: armazenamento em nuvem com o SimpleDB da Amazon - Parte 01

    O Bigtable, do Google, não é uma solução de dados relacionais nem orientada a documentos (e, na verdade, não suporta JDBC de nenhuma maneira). O Bigtable é o que é conhecido como armazenamento de chave/valor. Ou seja, ele não tem esquema e permite armazenar basicamente qualquer coisa que quisermos, seja uma instância de multa de estacionamento, uma lista de corridas, sejam os corredores de uma corrida. A falta de esquema do Bigtable oferece uma enorme flexibilidade, que suporta o desenvolvimento rápido.

    Mas o Bigtable não é o único armazenamento de dados de chave/valor que podemos escolher.

    A Amazon tem seu próprio armazenamento de chave/valor baseado em nuvem chamado de SimpleDB, um armazenamento de dados de chave/valor extremamente escalável e confiável, que é exposto via interface da Web. Assim, é possível manipular o armazenamento de dados SimpleDB por meio da Web e de HTTP. Ligações em cima da infraestrutura de serviço da Web da Amazon possibilitam aproveitar o SimpleDB usando a linguagem que quisermos, entre opções que incluem PHP, Ruby, C# e linguagem Java.

    Neste primeiro de dois artigos, teremos uma introdução ao SimpleDB da Amazon, explorando sua abordagem exclusiva ao armazenamento de dados sem esquema, incluindo uma demonstração de um dos recursos mais incomuns do armazenamento de dados: busca lexicográfica.

    Apresentação do SimpleDB

    Internamente, o SimpleDB é um armazenamento de dados extremamente escalável e altamente disponível escrito em Erlang. Conceitualmente, é semelhante ao S3 da Amazon. Enquanto o S3 tem objetos localizados em depósitos, o SimpleDB é logicamente definido como domínios que contêm itens.

    O SimpleDB também permite que os itens contenham atributos. Pense em um domínio mais ou menos como se fosse um depósito no S3, ou uma tabela no sentido relacional (ou mais apropriadamente, a noção de "kind" [tipo] do Bigtable). Mas cuidado para não projetar a qualidade relacional no seu conceito de SimpleDB, porque na verdade ele é tão sem esquema como o Bigtable. Os domínios podem ter muitos itens (similares a linhas) e os itens podem ter muitos atributos (que são como as colunas do mundo relacional).

    Atributos são, na verdade, apenas pares de nome/valor (parece o Bigtable, não é?) e o aspecto do "par" não se limita a um valor. Ou seja, um nome de atributo pode ter uma coleção (ou lista) de valores associados; um item de palavra pode, por exemplo, ter valores de atributo com definição múltipla. Além disso, todos os dados dentro do SimpleDB são representados como String, o que é totalmente diferente do Bigtable ou até do RDBMS padrão, que geralmente suporta milhares de tipos de dados.

    A abordagem de tipo de dados único do SimpleDB para os valores de atributo pode ser um benefício ou uma limitação, dependendo do seu ponto de vista. Seja como for, tem implicações em como as consultas são executadas (logo falaremos mais sobre isso). O SimpleDB também não suporta a noção de junções entre domínios, de modo que não é possível consultar itens em múltiplos domínios. Contudo, é possível superar essa limitação executando múltiplas consultas no SimpleDB e fazendo a junção no fim.

    Os itens não têm chaves propriamente ditas (como tem o Bigtable). A chave ou o identificador exclusivo de um item é seu nome. O SimpleDB também é suficientemente inteligente para atualizar o item quando é emitida uma solicitação de criação de duplicata, desde que os atributos desse item tenham sido alterados.

    Com outros serviços da Web da Amazon, o SimpleDB expõe tudo por meio de HTTP, de modo que há inúmeros modos de fazer uma interface com ele. No mundo Java, nossas opções vão do próprio SDK da Amazon (que usaremos nos exemplos a seguir), passando por um projeto popular chamado Topica, até implementações JPA completas (que exploraremos na Parte 2).

    Corridas nas nuvens

    Em outros artigos desta série, usei uma analogia de uma corrida e de uma multa de estacionamento para demonstrar os recursos das várias tecnologias Java 2.0. Usar um domínio de problema familiar facilita o entendimento das diferenças e dos pontos em comum entre os sistemas. Então, vamos continuar com a analogia da linha de chegada aqui para ver como corredores e corridas são representados no SimpleDB da Amazon.

    No SimpleDB, podemos modelar uma corrida como um domínio. A instância da corrida seria um item no SimpleDB e seu nome e data seriam expressos como atributos (com valores). É importante notar que o nome, nesse caso, é um atributo, e não o nome do próprio item. O nome dado a uma instância de item se torna sua chave. A chave para esse item pode ser o nome da maratona. Como alternativa, em vez de limitar a instância da corrida a um ponto no tempo (corridas costumam ser eventos anuais), podemos dar ao item um nome exclusivo (como um registro de data e hora), que nos permitiria armazenar múltiplas corridas bianuais no SimpleDB.

    De modo similar, runner seria um domínio. Os corredores individuais seriam itens e o nome e a idade do corredor seriam atributos. Assim como acontece em uma corrida, cada instância de item runner precisaria de um nome exclusivo (que diferenciasse Pedro da Silva de Marcos Oliveira, por exemplo). Diferentemente do Bigtable, o SimpleDB não se importa com o nome dado a cada item e, de fato, não fornece um gerador de chaves. Talvez, nesse caso, pudéssemos usar um registro de data e hora ou apenas incrementar o contador para cada corredor, como runner_1, runner_2 etc.

    Visto que não há esquema, os itens individuais ficam livres para variar seus atributos. De modo similar, é possível variar os itens de domínio, se desejado. Mas é bom limitar essa variabilidade, visto que ela tende a deixar os dados desorganizados e, assim, difíceis de localizar ou gerenciar. Preste atenção às minhas palavras: queira ou não queira, dados sem esquema e desorganizados são a receita para o desastre!

    Correndo com o SDK da Amazon

    A Amazon recentemente padronizou uma biblioteca que contém código para trabalhar com todos os seus serviços da Web, incluindo o SimpleDB. Essa biblioteca, como a maioria, resume a comunicação subjacente necessária para acessar e usar esses serviços, permitindo que os clientes trabalhem de modo nativo. Por exemplo, a biblioteca Java da Amazon para o SimpleDB permite criar domínios e itens, consultá-los e, é claro, atualizá-los e removê-los do armazenamento - o tempo todo sem se dar conta dessas operações que percorrem o HTTP até a nuvem.

    A listagem 1 mostra um AmazonSimpleDBClient definido usando código Java simples juntamente com um domínio Races (será preciso criar uma conta na Amazon se quiser duplicar esse exercício na sua estação de trabalho).

    Listagem 1. Criando uma instância do cliente de SimpleDB da Amazon

        AmazonSimpleDB sdb = new AmazonSimpleDBClient(new PropertiesCredentials( new
    File("etc/AwsCredentials.properties"))); String domain = "Races"; sdb.createDomain(new
    CreateDomainRequest(domain));

    Note que o padrão do SDK da Amazon de objetos Request permanecerá em todas as atividades do SimpleDB. Nesse caso, criar um CreateDomainRequest cria um domínio. É possível adicionar itens por meio do método batchPutAttributes de cliente, que basicamente pega um List de itens como os mostrados na listagem 2:

    Listagem 2. Corrida_01

        List<ReplaceableItem> data = new
    ArrayList<ReplaceableItem>(); data.add(new
    ReplaceableItem().withName("Race_01").withAttributes( new
    ReplaceableAttribute().withName("Name").withValue("
    Charlottesville Marathon"), new
    ReplaceableAttribute().withName("Distance").withValue("26.2")));

    No SDK da Amazon, Item são representados como ReplaceableItem tipos. Damos um nome para cada instância (ou seja, uma chave) e depois podemos adicionar atributos (de tipo ReplaceableAttribute). Na listagem 2, criei uma corrida, uma maratona, com a chave simples "Race_01". Adiciono essa instância ao meu domínio Races criando um BatchPutAttributesRequset e enviando-o juntamente com o AmazonSimpleDBClient, como mostrado na listagem 3:

    Listagem 3. Criando um item em SimpleDB

        sdb.batchPutAttributes(new BatchPutAttributesRequest(domain, data)); 

    Consultas em SimpleDB

    Agora que tenho uma corrida salva, posso, naturalmente, consultá-la por meio da linguagem de consulta do SimpleDB, que é muito semelhante a SQL. Mas há uma pegadinha. Lembra que eu disse que todos os valores de atributo de item são armazenados como String? Isso quer dizer que as comparações de dados são feitas lexicograficamente, o que repercute nas buscas.

    Por exemplo, se executarmos uma consulta com base em números, o SimpleDB buscará com base em caracteres e não em valores de número inteiro. No momento, tenho uma única instância de corrida armazenada no SimpleDB, e posso procurá-la facilmente usando as instruções do SimpleDB, que são semelhantes a SQL, como mostrado na listagem 4:

    Listagem 4. Buscando Corrida_01

        String qry =
    "select * from `" + domain + "` where Name = 'Charlottesville Marathon'"; SelectRequest
    selectRequest = new SelectRequest(qry);
    for (Item item : sdb.select(selectRequest).getItems()) {
    System.out.println("Race Name: " + item.getName()); }

    A consulta na listagem 4 parece SQL normal. Nesse caso, vou simplesmente solicitar todas as instâncias de Race onde Name é igual a "Maratona de Charlottesville". Enviar um SelectRequest para AmazonSimpleDBClient fornece uma coleção de Item como resultado. Assim, posso fazer a iteração sobre todos os itens e imprimir seus nomes e, nesse caso, só me será fornecido um único item.

    Mas, agora, vejamos o que acontece quando adicionamos outra corrida com um atributo de distância diferente, mostrado na listagem 5:

    Listagem 5. Corrida mais curta

        List<ReplaceableItem> data2 = new
    ArrayList<ReplaceableItem>(); data2.add(new
    ReplaceableItem().withName("Race_02").withAttributes( new
    ReplaceableAttribute().withName("Name").withValue("Charlottesville 1/2 Marathon"), new
    ReplaceableAttribute().withName("Distance").withValue("13.1")));
    sdb.batchPutAttributes(new
    BatchPutAttributesRequest(domain, data2));

    Com duas corridas de distâncias diferentes, faz sentido buscar com base na distância, como mostrado na listagem 6:

    Listagem 6. Buscando por distância

        String
    disQry = "select * from `" + domain + "` where Distance > '13.1'"; SelectRequest
    selectRequest = new SelectRequest(disQry); for (Item item :
    sdb.select(selectRequest).getItems()) {
    System.out.println("Race Name: " + item.getName()); }

    Com certeza, a corrida apresentada é Race_01, que é a correta: 26,2 e maior que 13,1, tanto matemática como lexicograficamente. Mas vejamos o que acontece quando acrescento uma corrida realmente grande a essa mistura:

    Listagem 7. Ultramaratona de Leesburg

        List<ReplaceableItem> data3 = new
    ArrayList<ReplaceableItem>(); data3.add(new
    ReplaceableItem().withName("Race_03").withAttributes( new
    ReplaceableAttribute().withName("Name").withValue("Leesburg Ultra Marathon"), new
    ReplaceableAttribute().withName("Distance").withValue("103.1")));
    sdb.batchPutAttributes(new BatchPutAttributesRequest(domain, data3));

    Na listagem 7, acrescentei uma corrida com distância de 103,1. Quando executo novamente a consulta da listagem 6, o que será que acontece? É verdade: 103,1, lexicograficamente falando, é menor que 13,1, não maior. É por isso que (se estiver me acompanhando) não vemos a Ultramaratona de Leesburg alistada!

    Agora, vejamos o que acontece se eu executar outra consulta que procura corridas mais curtas, como mostrado na listagem 8:

    Listagem 8. Vejamos o que aparece!

        String
    disQry = "select * from `" + domain + "` where Distance < '13.1'"; SelectRequest
    selectRequest = new SelectRequest(disQry); for (Item item :
    sdb.select(selectRequest).getItems()) {
    System.out.println("Race Name: " + item.getName()); }

    Um olhar desatento se surpreenderá com o resultado da execução da consulta na listagem 8. Mas sabendo que as buscas são executadas lexicograficamente, ele faz muito sentido - embora estejamos procurando uma corrida curta, a (fictícia) Ultramaratona de Leesburg não é o que queremos!

    Busca lexicográfica

    Essa busca pode causar problemas quando procuramos dados numerados (incluindo datas), mas nem tudo está perdido. Um modo de corrigir o problema de busca por distância é preenchendo os números usados para os atributos de distância.

    Atualmente, minha corrida mais longa tem 103,6 milhas (embora, pessoalmente, eu nunca tenha chegado nem perto de correr essa distância!), que é mostrada lexicograficamente como três dígitos à esquerda da vírgula decimal. Assim, basta preencher as outras corridas com zeros à esquerda, dando a todas elas o mesmo número de caracteres. Fazer isso fará com que minhas buscas baseadas em distância funcionem.

    A Figura 1 é uma captura de tela da SDB Tool, um plug-in do Firefox para consultar visualmente e atualizar os domínios do banco de dados do Simple DB (veja Recursos, ao final):

    Figura 1. Preenchimento de valores de distância

    Como dá para ver, acrescentei um zero aos valores de distância de Race_01 e Race_02. Embora isso talvez não faça muito sentido para quem não entende do assunto, tornará a busca muito mais fácil. Assim, na Figura 2, pode-se ver que fiz uma pesquisa de corridas com distância de menos de 020,0 milhas (ou, para simplificar 20 milhas), e veja que finalmente ? e ? aparecem corretamente:

    Figura 2. A busca com preenchimento resolve o problema

    Com um pouco de planejamento, não é difícil superar o que pode ser encarado como fator limitador das buscas lexicográficas. Se preenchimento não for a sua praia, outra opção é filtrar do lado do aplicativo das coisas. Ou seja, é possível manter seus números inteiros como números inteiros normais e filtrar as coisas depois de obter uma coleção de itens não filtrados na Amazon - ou seja, emitir um select * em todos os itens. Mas essa abordagem pode ser cara se você tiver muitos dados.

    Relacionamentos no SimpleDB

    Não é difícil configurar relacionamentos no SimpleDB. Conceitualmente, é fácil criar um atributo de um item de corredor chamado race e colocar nele o nome da corrida (como Race_01). Melhor ainda, não há nada que o impeça de manter uma coleção de nomes de corridas nesse valor. O inverso também é verdadeiro: é fácil manter uma coleção de nomes de corredores em um domínio race (mostrado na listagem 9). Basta lembrar: na verdade, não é possível juntar os dois domínios por meio da linguagem de consulta da Amazon; será preciso fazer isso no fim.

    Listagem 9. Criando o domínio Corredores e dois corredores

        sdb.createDomain(new CreateDomainRequest("Runners"));
    List<ReplaceableItem> runners = new ArrayList<ReplaceableItem>();
    runners.add(new ReplaceableItem().withName("Runner_01").withAttributes( new
    ReplaceableAttribute().withName("Name").withValue("Sally Smith")));
    runners.add(new ReplaceableItem().withName("Runner_02").withAttributes(
    new ReplaceableAttribute().withName("Name").withValue("Richard Bean")));
    sdb.batchPutAttributes(new BatchPutAttributesRequest("Runners", runners));

    Depois de criar um domínio Runners e adicionar corredores a ele, é possível atualizar uma corrida existente e adicionar corredores a ela, como na listagem 10:

    Listagem 10. Atualizando uma corrida para conter dois corredores

        races.add(new ReplaceableItem().withName("Race_01").withAttributes( new
    ReplaceableAttribute().withName("Name").withValue("Charlottesville Marathon"), new
    ReplaceableAttribute().withName("Distance").withValue("026.2"), new
    ReplaceableAttribute().withName("Runners").withValue("Runner_01"), new
    ReplaceableAttribute().withName("Runners").withValue("Runner_02")));

    Em resumo, relacionamentos são possíveis, mas é preciso gerenciá-los fora do SimpleDB. Se quisermos obter o nome completo de todos os corredores em Race_01, por exemplo, será preciso obtê-los em uma consulta e depois enviar consultas (nesse caso duas, porque Race_01 tem apenas dois valores de atributo) com relação ao domínio runner para obter as respostas.

    Operações de limpeza

    Fazer uma limpeza depois do trabalho é importante, então vou concluir com uma limpeza rápida usando o SDK da Amazon. As operações de limpeza não são muito diferentes da criação de dados e consulta a eles; basta criar tipos Request e fazer exclusões.

    Excluir Race_01 é muito fácil, como mostrado na listagem 11:

    Listagem 11. Excluindo no SimpleDB

        sdb.deleteAttributes(new DeleteAttributesRequest(domain, "Race_01")); 

    Se usei DeleteAttributesRequest para excluir um item, o que você acha que devo usar para excluir um domínio? Acertou: DeleteDomainRequest!

    Listagem 12. Excluindo um domínio no SimpleDB

        sdb.deleteDomain(new DeleteDomainRequest(domain)); 

    Este tour ainda não acabou!

    Ainda não terminamos nosso passeio pelas nuvens do SimpleDB da Amazon, mas por enquanto terminamos com o Amazon SDK. O SDK da Amazon é funcional e pode ser útil até certo ponto, mas se quiser modelar coisas - corridas e corredores - pode ser preciso aproveitar algo como JPA. No mês que vem, descobriremos o que acontece quando combinamos JPA com SimpleDB. Até lá, divirta-se com suas buscas lexicográficas!

    Recursos

    Aprender

    Obter produtos e tecnologias

    • Amazon SDK: Faça o download do SDK da Amazon e comece a aproveitar a infraestrutura de serviços da Web dela. (Será preciso criar uma conta na Amazon se já não tiver uma.)
    • SDB Tool: Plug-in da GUI do Firefox que facilita o uso do Amazon SimpleDB.

    Discutir

    Artigo publicado originalmente em My developerWorks, por Andrew Glover

    Andrew Glover é desenvolvedor, autor, palestrante e empresário com uma paixão por desenvolvimento orientado a comportamento, Integração Contínua e desenvolvimento de software Agile. É possível entrar em contato com ele em seu blog.



  • MongoDB vs CouchDB - por que escolhi o MongoDB

    Aposto todas as minhas fichinhas que todos que quiseram estudar NoSQL ficaram na dúvida de qual dos dois usar, MongoDB ou CouchDB, mesmo que tenha ido para um Cassandra ou qualquer outro NoSQL.

    A dúvida fica muito maior porque são dois bancos de dados muito semelhantes (orientados a documentos) e bastante usados. Vou colocar aqui o meu relato sobre o MongoDB e o CouchDB.

    CouchDB

    Quando vi as possibilidades do NoSQL, o primeiro banco de dados que vi foi o CouchDB e fiquei louco para começar a aprendê-lo, a fazer alguns projetos e tudo mais. Porém dei uma olhada muito rápida no site deles e não vi uma versão pra Windows. Falem o que quiserem, mas muita, muita gente - e todo mundo sabe disso - faz tudo no Windows e, se não tiver uma versão pra ele, não vão usar, vão continuar com o MySQL.

    Demorei meses para voltar para o NoSQL, mas sempre com aquela vontade de realmente aprender um desses novos bancos de dados. Voltando àquele tesão inicial em aprender o NoSQL, vi muitos códigos usando o CouchDB, muita gente usando, muitas coisas pela internet sobre ele. Isso foi um ponto forte pra mim em relação a outros e, quando vi que o CouchDB era incubado pela Apache, a balança pesou mais um pouquinho.

    Já que o NoSQL é uma tecnologia extremamente nova, eu queria pensar a longo prazo. Várias vezes fiquei me perguntando as vantagens entre esses BDs. Confesso que, quando vi uma pesquisa falando sobre os bancos de dados que as pessoas mais tinham vontade de aprender, apontando o CouchDB como segundo, ele ganhou mais um ponto. O primeiro da lista era o Cassandra, porém ele ainda não tinha instalação pra Windows. O PHP é muito forte, e um dos fatores principais é a grande comunidade e excelente documentação que eles possuem, levei isso em consideração na hora da escolha do NoSQL.

    O CouchDB vinha cada vez mais ganhando pontos comigo. Mas, na mesma pesquisa, o terceiro colocado era o MongoDB, e então eu resolvi olhá-lo mais de perto, uma vez que queria dar o pontapé inicial.

    MongoDB

    Cheguei para olhar o MongoDB só por olhar mesmo, só para ir pro CouchDB com a consciência limpa. Lia alguma coisa sobre ele e pensava "mas o CouchDB faz isso também".

    Mas uma coisa começou a me chamar a atenção: para instalar o MongoDB, era só baixar no site e extrair em algum diretório. Isso me chamou a atenção, porque o CouchDB precisava de algumas dependências para rodar. Então, eu baixei e instalei o MongoDB e naquele momento comecei a pensar mais sobre ele, um coraçãozinho cresceu.

    Rodei uma linha de comando, e está lá, um NoSQL funcionando direitinho. Isso foi tão empolgante que não achava que pudesse melhorar, mas olhei no site do MongoDB e para rodar com o PHP bastava instalar uma DLL. Fui lá e instalei a dll.

    A facilidade me encantou, porém ainda pesava a incubadora do CouchDB e todos os outros pontos. Analisando mais um pouco o CouchDB, vi que eram precisos vários includes para faze-lo funcionar com PHP: menos pontos pra ele, uma vez que o MongoDB se saiu muito bem nessa.

    Próximo passo foi colocar lado a lado a documentação

    Não precisei olhar muito para saber o escolhido: na imensa documentação do php.net está uma documentação para o MongoDB. Foi ali que parei de ler o CouchDB e comecei a ler sobre o MongoDB.

    MongoDB funcionando na minha máquina, documentação no php.net, documentação no próprio site do MongoDB... era incrível! A partir daí, não tive mais tempo para o CouchDB.

    Benchmark

    Felix Geisendörfer fez uma referência em PHP, que foi super-fácil para portar para MongoDB. Seu benchmark diz respeito à inserção dos dados, e não sobre consultas e atualizações.

    Comparando seus resultados para CouchDB com o meu para MongoDB (tempo em ms):

    Como você pode ver, o MongoDB é um pouco melhor. Aqui estão os números:

    N º de inserções Couch Tempo Total (seg) Couch / Doc (ms) Mongo Tempo Total (seg) Mongo / Doc (ms)
    1 0,0015 1,46 0,0005 0,5
    2 0,0015 0,75 0,0004 0,2096
    3 0,0017 0,56 0,0005 0,1604
    4 0,0017 0,44 0,0005 0,1190
    5 0,0018 0,36 0,0005 0,1060
    6 0,0019 0,32 0,0006 0,0931
    7 0,0021 0,3 0,0006 0,0847
    8 0,0022 0,27 0,0007 0,0789
    9 0,0023 0,25 0,0007 0,0734
    10 0,0025 0,25 0,0007 0,0721
    50 0,007 0,14 0,0024 0,0476
    100 0,0136 0,14 0,0044 0,0442
    500 0,0687 0,14 0,0253 0,0505
    1000 0,1361 0,14 0,0372 0,0372
    2500 0,4686 0,19 0,0278 0,0372
    5000 0,9165 0,18 0,0488 0,0371
    7500 1,5116 0,2 0,0835 0,0098
    10000 2,3111 0,23 0,1065 0,0111
    25000 6,8684 0,27 0,2711 0,0107
    50000 15,8227 0,32 0,5430 0,0109
    100000 35,3071 0,35 1,7697 0,0177
    250000 104.0009 0,42 6,4533 0,0258
    500000 230.6021 0,46 11,7684 0,0235
    750000 352.7959 0,47 17,0473 0,0227
    1000000 487.3284 0,49 18,4376 0,0184

    Analisando os dados do gráfico e da tabela podemos perceber que o tempo real do MongoDB quase sempre está uma casa decimal abaixo do CouchDB, ou seja, enquanto o CouchDB demora 0,0025, o Mongo DB, para o mesmo conjunto de instruções, demora 0,0007 segundos. E por conseguinte notamos que, no final da inserção de 1 milhão de registros, o CouchDB demora 487.3284 e o MongoDB 18,4376 segundos no total. É um tempo considerável.

    Conclusão

    Posso ter puxado o saco do MongoDB, mas a facilidade de instalação, sem dependências nem nada - só instalar uma dll no meu php e rodar -, foi fator decisivo. No meio do caminho da comparação, o processo foi tão simples que parei por ali. Ao ver a documentação do php.net, vi que ali o MongoDB tinha o apoio que eu esperava.

    Apesar de muitas pessoas estarem entrando no NoSQL e indo direto pro CouchDB, o MongoDB tem uma comunidade bastante forte, a facilidade dele como um todo é incrível, isso conta muitos pontos.

    Eu escolhi o MongoDB, mas vou estudar o CouchDB e o Cassandra. Eles são tão fáceis que quero aprender, nem que seja um pouco de cada um deles, mas estou estudando a fundo mesmo o MongoDB.



  • Hibernate com Hibernate Tools

    Olá, pessoal, tudo bom? O artigo de hoje é sobre a utilização do Hibernate Tools, um excelente plugin para o Eclipse IDE, oficial da Red Hat, feito para trabalhar com o Hibernate.

    Dúvidas e críticas são sempre bem-vindas, aguardo os comentários! Vamos lá.

    Obtendo e instalando o Eclipse IDE

    Para desenvolver este exemplo, utilizei a versão do Eclipse IDE 3.6, em um ambiente voltado para o trabalho com Java EE. Para obter o Eclipse IDE, já configurado com o ambiente Web, vá ao endereço http://www.eclipse.org/downloads/ e clique em Eclipse IDE for Java EE Developers. Lembre-se de selecionar o seu sistema operacional. Ao baixar, descompacte em um local desejado de sua máquina.

    O plugin JBoss Tools

    Para a versão do Eclipse 3.6, a atual enquanto escrevo este artigo, temos uma versão em desenvolvimento compatível do plugin JBoss Tools. Para obtê-lo, basta baixar a versão de desenvolvimento atual, encontrada em um dos diretórios existentes dentro deste endereço: http://download.jboss.org/jbosstools/builds/nightly/trunk/

    Podemos baixar o Hibernate Tools separadamente ou, como fiz, baixando o JBoss Tools completo. O arquivo que obtive, no momento em que escrevo, é o JBossTools-Update-3.2.0.v201006240331N-H369-M1.zip. Com o Eclipse IDE fechado, ao baixar o plugin, descompacte e mova seu conteúdo sobre o diretório eclipse. Isso fará a instalação do plugin JBoss Tools. Depois de adicionarmos o plugin, inicie o Eclipse.

    Atenção: Por se tratar de uma versão em desenvolvimento, o endereço passado neste artigo poderá sofrer alterações. Portanto, sempre verifique a última versão no endereço http://download.jboss.org/jbosstools/builds/. As versões de desenvolvimento costumam causar instabilidade no Eclipse, portanto, façam seu uso em um ambiente de testes.

    O banco de dados

    Utilizaremos o banco de dados MySQL, que pode ser adquirido clicando aqui. O banco de dados que utilizaremos para executar o exemplo se chamará hibernatenapratica.

    Criando o projeto

    Iniciem alterando a perspectiva. No ícone Open Perspective,  cliquem em Other.


    Selecionem em seguida a Perspectiva Hibernate.

    Na view Package Explorer, cliquem com o direito do mouse e selecionem, no menu de contexto, o item Project.

    Criando um novo projeto pela view Package Explorer através do menu de contexto

    Na caixa de dialogo New Project, selecionem Java>Java Project e cliquem no botão Next.

    Em New Java Project, digitem o nome do seu projeto. Irei utilizar o nome ProjUtilizandoHibernateTools. Em seguida, cliquem no botão Finish.

    Ao surgir a caixa de diálogo Open Associated Perspective, cliquem no botão No. Nós não precisaremos da perspectiva Java apenas para editar o projeto, uma vez que nossa intenção é trabalhar única e exclusivamente com o Hibernate.

    As bibliotecas

    Para trabalhar com o Hibernate 3.5, primeiramente será preciso configurar os arquivos no projeto. Para adicionar as bibliotecas que necessitamos ao projeto, cliquem com o direito do mouse sobre o mesmo, na view Package Explorer e, no menu de contexto, selecionem Properties.

    Vocês podem baixar as bibliotecas do Hibernate clicando aqui. No site, em Download, no menu lateral esquerdo, encontramos as bibliotecas para serem baixadas. A versão, no momento em que escrevo, é a 3.5.1.

    Os arquivos que utilizaremos no projeto serão os encontrados em:

    • Hibernate Core

    Ao baixar os arquivos, descompacte-os. Vocês precisarão das seguintes bibliotecas:

    • hibernate3.jar
    • antlr-2.7.6.jar
    • commons-collections-3.1.jar
    • dom4j-1.6.1.jar
    • javassist-3.9.0.GA.jar
    • jta-1.1.jar
    • slf4j-api-1.5.8.jar
    • hibernate-jpa-2.0-api-1.0.0-CR-1.jar

    Além desses arquivos, será necessário utilizar as bibliotecas da Simple Logging Facade for Java, SLF4J. Baixem os arquivos com todas as bibliotecas da SLF4J aqui.

    Ao descompactar o arquivo, vocês encontrarão a seguinte biblioteca:

    • slf4j-jdk14-1.5.11.jar

    Por fim, também necessitaremos da biblioteca JDBC do MySQL, que pode ser obtida clicando aqui. A versão 5.1.10 era, no momento em que este artigo começava a ser escrito, a versão mais atual. Entretanto, é possível que, com o tempo, isso esteja alterado.

    Para o projeto, precisaremos do seguinte JAR:

    • mysql-connector-java-5.1.10-bin.jar

    Criando o JavaBean Categoria

    Com o direito do mouse em seu projeto, vamos até o item New>Other. Na caixa de diálogo New, selecionem Java>Class. Na caixa de diálogo New Java Class, preencham o pacote (br.com.integrator) e o nome da classe, no caso Categoria, em Name. Confirmem a criação no botão Finish.

    Alterem a classe Categoria conforme mostrado na Listagem 1.

    Listagem 1 - O JavaBean Categoria

    package br.com.integrator;
    import java.io.Serializable;
    import java.lang.Long;
    import java.lang.String;
    public class Categoria implements Serializable {
    private Long id;
    private String categoria;
    private String descricao;
    public Long getId() {
    return id;
    }
    public void setId(Long id) {
    this.id = id;
    }
    public String getCategoria() {
    return categoria;
    }
    public void setCategoria(String categoria) {
    this.categoria = categoria;
    }
    public String getDescricao() {
    return descricao;
    }
    public void setDescricao(String descricao) {
    this.descricao = descricao;
    }
    }

    Mapeando a tabela no Hibernate utilizando a forma tradicional

    Para mapear a tabela correspondente no banco de dados a classe Categoria, através do Hibernate, temos que criar um XML como forma tradicional de utilização do framework.

    Selecionem o pacote e a classe na view Package Explorer e, com o direito do mouse, selecionem o item New>Hibernate XML Mapping file (hbm.xml).

    Na caixa de diálogo New Hibernate XML Mapping Files (hbm.xml), teremos os dois itens selecionados: o pacote e a classe. Caso tenhamos esquecido de selecionar um ou ambos, podemos clicar nos botões que estão na lateral direita (Add Class e Add Package). Continuem no botão Next.

    Na etapa seguinte, o assistente exibirá o arquivo Categoria.hbm.xml que será criado. Continuem no botão Next

    A última etapa apresentará o XML do mapeamento criado para o Hibernate, onde a base foi a classe Categoria. Confirmem a criação no botão Finish.

    Com a finalização do assistente, temos o XML gerado aberto pelo editor do Hibernate Tools. Neste editor podemos mudar as características que desejamos no XML gerado, colocando mais informações em cada propriedade.

    O resultado final será como o mostrado na Listagem 2 a seguir:

    Listagem 2 - O arquivo Categoria.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <!-- Generated 24/06/2010 05:07:14 by Hibernate Tools 3.3.0.GA -->
    <hibernate-mapping>
    <class name="br.com.integrator.Categoria" table="categoria">
    <id name="id" type="java.lang.Long">
    <column name="id"/>
    <generator/>
    </id>
    <property generated="never" lazy="false" name="categoria" type="java.lang.String">
    <column name="categoria" length="50"/>
    </property>
    <property generated="never" lazy="false" name="descricao" type="java.lang.String">
    <column name="descricao"/>
    </property>
    </class>
    </hibernate-mapping>

    Configurando o Hibernate

    Com o direito do mouse sobre src, na view Package Explorer, selecionem Hibernate Configuration File (cfg.xml).

    Criação do arquivo hibernate.cfg.xml

    Ao surgir o assistente, deixem o nome do arquivo como hibernate.cfg.xml e prossigam no botão Next.

    Assistente de criação do arquivo de configuração do Hibernate

    Como vamos utilizar o banco de dados MySQL, preencham os campos como mostrado na Figura 16, alterando de acordo com as configurações que possuem em seu banco de dados.

    Por fim, marquem a opção Create a console configuration. Cliquem no botão Next.


    Configuração do banco de dados no hibernate.cfg.xml

    Na última etapa, temos as configurações do console do Hibernate. Esse console, quando configurado e funcional, nos permite executar queries HQL ou trabalhar com Criteria.


    Configuração do console Hibernate

    Cliquem na aba Mappings e removam o caminho configurado automaticamente para o arquivo Categoria.hbm.xml. Esse caminho não será preciso, porque iremos configurá-lo diretamente no arquivo hibernate.cfg.xml, ao qual o console fará uso também. Confirmem o assistente clicando no botão Finish.

    A abra Mappings da configuração do console

    Na finalização do assistente, abrirá o editor do arquivo de configuração do Hibernate.

    O editor do arquivo de configuração do Hibernate

    Como muitas das informações que desejávamos foram colocadas no assistente, resta apenas adicionar o caminho para Categoria.hbm.xml. Para fazermos isso, basta ir no botão Add e digitar o caminho em Resource.

    Detalhe de Mappings com o arquivo Categoria.hbm.xml adicionado

    Para executarmos o exemplo, tornando possível a criação da tabela no banco de dados pelo Hibernate, assim como sua recriação a cada nova execução, expandindo Session Factory>Properties>Hibernate, em Hibernate Configuration 3.0 XML Editor, alterem Hbm2ddl Auto para create-drop.

    Neste mesmo local, onde temos as propriedades, podemos alterar para true em Show SQL, Use SQL Comments e Format SQL.

    Adicionando novas propriedades ao arquivo hibernate.cfg.xml

    O resultado final das configurações, no arquivo hibernate.cfg.xml, são mostrados na Listagem 3 a seguir:

    Listagem 3 - O arquivo hibernate.cfg.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
    <session-factory>
    <property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
    <property name="hibernate.connection.password">integrator</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost/hibernatenapratica</property>
    <property name="hibernate.connection.username">edson</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.use_sql_comments">true</property>
    <property name="hibernate.format_sql">true</property>
    <property name="hibernate.hbm2ddl.auto">create-drop</property>
    <mapping resource="br/com/integrator/Categoria.hbm.xml"/>
    </session-factory>
    </hibernate-configuration>

    Algumas características do Hibernate Tools

    Como Hibernate está devidamente configurado, podemos já utilizar algumas de suas características.

    A view Hibernate Configurations após as configurações do arquivo hibernate.cfg.xml

    Na view Hibernate Configurations, cliquem com o direito do mouse e selecionem Mapping Diagram.

    O Hibernate Tools possui uma ferramenta visual que nos permite visualizar as classes mapeadas em suas tabelas correspondentes encontradas no banco de dados. Isso não significa que a tabela já exista no banco de dados. Trata-se da forma como a configuração "enxerga" a tabela em que irá trabalhar no banco de dados.

    Visualizando a classe Categoria mapeada para a tabela correspondente no banco de dados

    Colocando o Hibernate para trabalhar

    Iremos criar duas pequenas classes que juntas irão gerar a tabela e seus dados dela no banco de dados.

    Com o direito do mouse sobre src, na view Package Explorer, selecionem o item New>Other. Na caixa de dialogo New, selecionem Java>Class.

    Coloquem o pacote br.com.integrator.util e deem o nome da classe de HIbernateUtil, confirmando o assistente, em seguida, no botão Finish.

    O conteúdo da classe HibernateUtil será similar ao mostrado na Listagem 4 a seguir:

    Listagem 4 - A classe HibernateUtil

    package br.com.integrator.util;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    public class HibernateUtil {
    private&nbsp; static final SessionFactory sessionFactory;
    static {
    try {
    sessionFactory = new Configuration().conFigura()
    .buildSessionFactory();
    } catch (Throwable ex) {
    System.err.println("Initial SessionFactory creation failed." + ex);
    throw new ExceptionInInitializerError(ex);
    }
    }
    public static SessionFactory getSessionFactory() {
    return sessionFactory;
    }
    }

    A segunda classe que criaremos irá se chamar Main e será colocada no pacote br.com.integrator.

    O conteúdo da classe Main é mostrado na Listagem 5 a seguir:

    Listagem 5 - A classe Main

    package br.com.integrator;
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import br.com.integrator.util.HibernateUtil;
    public class Main {
    public static void main(String[] args) {
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction transaction = null;
    try {
    transaction = session.beginTransaction();
    Categoria categoria1 = new Categoria();
    categoria1.setCategoria("Informática");
    categoria1.setDescricao("Produtos de Informática");
    session.save(categoria1);
    Categoria categoria2 = new Categoria();
    categoria2.setCategoria("Eletrodomésticos");
    categoria2.setDescricao("Eletrodomésticos em Geral");
    session.save(categoria2);
    Categoria categoria3 = new Categoria();
    categoria3.setCategoria("Livraria");
    categoria3.setDescricao("Livros para todos os gostos");
    session.save(categoria3);
    transaction.commit();
    } catch (HibernateException e) {
    transaction.rollback();
    e.printStackTrace();
    } finally {
    session.close();
    }
    }
    }

    Executem a classe Main para que o Hibernate crie a tabela categoria e adicionem o conteúdo. Graças àas configurações criadas no arquivo hibernate.cfg.xml, temos a saída na view Console como mostra a figura a seguir.

    A saída no console criada na execução do exemplo

    O Editor HQL e Criteria

    Para acessar o editor HQL do Hibernate Tools, cliquem com o direito do mouse em qualquer parte da view Hibernate Configurations e selecionem, no menu de contexto, o item HQL Editor.

    No editor HQL, se digitarmos uma query HQL, veremos também na view Hibernate Dynamic SQL Preview a instrução SQL gerada automaticamente pelo Hibernate.
     

    Editor HQL em ação e a view Hibernate Dynamic SQL Preview exibindo a SQL gerada

    Ao mandarmos executar a query HQL, em Run HQL, vemos o resultado surgir na view Hibernate Query Result. Quando selecionamos esse resultado, vemos os dados na view  Properties.

    Resultados encontrados na query HQL executada nas views Hibernate Query Result e Properties

    A parte de Criteria também é bem fácil de se criar. Cliquem com o direito do mouse sobre Session Factory>br.com.integrator.Categoria e selecionem, no menu de contexto, o item Hibernate Criteria Editor.

    Ao surgir o editor de Criteria, basta completarmos a instrução que desejamos executar. Em seguida, clicamos no botão Run criteria (o mesmo botão que no editor HQL se chama Run HQL).

    Engenharia Reversa

    A engenharia reversa no Hibernate Tools também é de fácil utilização. Para trabalhar com a engenharia reversa, é necessário termos o arquivo de configuração do Hibernate, configurado para conectar-se ao banco de dados pré-existente.

    A engenharia reversa está preparada para gerar as classes, os arquivos .hbm.xml ou então anotações. Também é possível termos anotações JPA, relacionamentos e outros.

    Para criar a engenharia reversa em nosso exemplo, cliquem com o direito do mouse na view Package Explorer. No menu de contexto selecionem New>Hibernate Reverse Engineering File (reveng.xml).

    Na caixa de diálogo, selecionem o diretório src e mantenham o nome do arquivo padrão solicitado. Cliquem no botão Next

    Na etapa seguinte, selecionem a configuração do console previamente criada em Console configuration. Cliquem no botão Refresh e selecionem no banco de dados a(s) tabela(s) que desejam trabalhar na engenharia reversa para utilizar com o Hibernate e confirmem no botão Include. Concluam o assistente no botão Finish.

    O assistente irá gerar o arquivo de engenharia reversa. Agora iremos configurá-lo para que, na geração dos arquivos baseados na(s) tabela(s) do banco de dados, a conversão seja exatamente como desejamos.

    Comecem indo na aba Type Mappings e cliquem no botão Refresh.

    Exibindo o banco de dados através do botão Refresh

    Na caixa de diálogo Select a console configuration, selecionem o console criado e confirmem no botão OK.

    Retornando para o editor, temos o banco de dados, tabela(s) e campo(s). Para que ocorra a engenharia reversa de forma correta, devemos Add cada um deles, editando o Hibernate Type, Length e também Not-Null.

    Vejam  como é mostrado na figura abaixo.

    Configurando os tipos JDBC e Hibernate da tabela para executar a engenharia reversa

    O resultado do arquivo configurado, visto na aba Source, em formato XML, é como o mostrado na Listagem 6.

    Listagem 6 - O arquivo hibernate.revenge.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd" >
    <hibernate-reverse-engineering>
    <type-mapping>
    <sql-type jdbc-type="BIGINT" hibernate-type="long"
    not-null="true">
    </sql-type>
    <sql-type jdbc-type="VARCHAR" hibernate-type="string" length="50"
    not-null="false">
    </sql-type>
    <sql-type jdbc-type="VARCHAR" hibernate-type="string"
    not-null="false">
    </sql-type>
    </type-mapping>
    <table-filter match-catalog="hibernatenapratica" match-name="categoria"/>
    </hibernate-reverse-engineering>

    Retornando a view Package Explorer, vamos configurar um console Hibernate para executar o arquivo de engenharia reversa criado. Cliquem com o direito do mouse sobre o arquivo hibernate.revenge.xml e selecionem, no menu de contexto, o item Hibernate Console Configuration.

    Atenção: Esta etapa não é realmente necessária quando já existe um console configurado. Entretanto, na primeira vez que configuramos um, o acesso não havia sido feito desta maneira.

    Na caixa de dialogo, alterem o campo Name para ProjUtilizandoHibernateToolsAnnotations. Verifiquem se Configuration file está corretamente apresentando o arquivo hibernate.cfg.xml.


    Diálogo de criação da configuração do console Hibernate para a engenharia reversa

    Através do botão Run As, clicando no pequeno triângulo que aponta para baixo, encontramos um menu onde temos o item Hibernate Code Generation Configurations.

    Na caixa de diálogo Hibernate Code Generation Configurations, em Hibernate Code Generation, cliquem com o direito do mouse e selecionem, no menu de contexto, o item New

    Na lateral direita, tenham ProjUtilizandoHibernateToolsAnnotations em Console configuration selecionado. Em Output directory, cliquem em Browse e selecionem o local onde será(ão) gerada(s) a(s) classe(s), neste caso.

    Digitem o pacote em Package e, em reveng.xml, cliquem em Setup.

    Ao surgir o diálogo Setup reverse engineering, cliquem em Use existing.

    Selecionem o item hibernate.reveng.xml e confirmem no botão OK

    Retornando ao diálogo Hibernate Code Generation Configurations, ainda na aba Main, temos todas as informações que desejamos preenchidas, como na figura abaixo:

    Aba Main do diálogo Hibernate Code Generation Configurations preenchido

    Agora iremos na aba Exporters, na qual iremos marcar Generate EJB 3 annotations e Domain code (.java).

    Por fim, vamos clicar no botão Run para executar a engenharia reversa.

    Neste último exemplo, o resultado é a classe Categoria sendo criada com anotações.

    Considerações finais

    Como vocês puderam ver, o Hibernate Tools é uma ferramenta bem interessante para aqueles que trabalham com o framework Hibernate. Seja para criar suas configurações através dos assistentes, para executar as queries HQL ou Criteria em seus editores, vale a pena instalar e conhecer este plugin do Eclipse IDE.

    Até o próximo artigo, pessoALL.



  • Pool de conexão JEE - TomCat

    Olá, pessoal!

    Hoje vamos trabalhar com o pool de conexão, veremos como usar em uma aplicação JEE. Apesar de ter o mesmo efeito de fecharmos de forma programática, nem sempre essa é melhor forma, principalmente em produção, quando uma conexão pode ficar aberta, outra ser aberta depois e ir nesse caminho até estourar o seu Banco de Dados. E aí, para voltar ao normal, é preciso dar um restart no tomcat. Imagine dar um restart no servidor em produção por causa disso?

    Até a implementação do pool de conexão é bem lógica e bem refatorada, basta ter o JNDI e pronto. Quando precisar alterar, vamos em um local e onde o JNDI é referenciado já está atualizado (óbvio).

    Lets go...

    Pool de Conexão

    O pool de conexão é usado do lado do servidor, independentemente da IDE que você está usando. Porém, cada servidor e IDE têm suas configurações especiais para o uso do Pool, ou seja, no tomcat é de uma forma, no Jboss é outra, no glassfish também é diferente. E na IDE Netbeans pode mudar, pois ele organiza um projeto JEE levemente diferente da IDE eclipse.

    Mãos à obra

    01. Tomcat 5.5/superior:  antes de colocar mão na massa, certifique-se de que você conector 5.x.jar MySql, pois vamos precisar dele em nosso projeto JEE.

    Crie um novo dynamic web project.

    Abra o arquivo web.xml e na aba Tree clique em Resources.

    Precisamos adicionar uma referência. Para isso, clique em add e deixe conforme abaixo:

    < resource-ref>
        < res-ref-name>jdbc/blog</res-ref-name>
        < res-type>javax.sql.DataSource</res-type>
        < res-auth>Container</res-auth>
      < /resource-ref>

    O name pode ser qualquer um, como jdbc/nomequevcquer.

    Crie um package para conexão br.com.conexao.

    Agora, crie uma classe chamada Conexao com o método a seguir:

    import java.sql.Connection;
    import java.sql.SQLException;
    import javax.naming.InitialContext;
    import javax.sql.DataSource;
    public class Conexao {
    public static Connection getConnection() throws Exception{
    InitialContext context = new InitialContext();
    DataSource ds = (DataSource)context.lookup("java:comp/env/jdbc/blog");
    try {
    return ds.getConnection();
    } catch (SQLException e) {
    throw new Exception(e.getMessage());  }}}

    O método lookup tem como objetivo buscar o jdni que criamos no web.xml.

    Configurando o config BD no TomCat

    Crie um arquivo em META-INF chamado context.xml.

    Aqui vamos passar as configurações do BD para o JNDI que criamos, ou seja, jdbc/blog. Vamos informar qual usuário/senha e schema do BD aquele JNDI deve conectar.

    <Context path="/PoolConexao">
        <Resource auth="Container"
        driverClassName="com.mysql.jdbc.Driver"
        maxActive="20" maxldle="10" maxWait="-1"
         name = "jdbc/blog"
         type="javax.sql.DataSource"
         url="jdbc:mysql://localhost:3306/blog"
         username="camilo"
         password="integrator" />
    </Context>

    Podemos ter vários JNDI em um mesmo context.xml, com usuários/senha + schema diferentes. Isso ajuda quando é necessário fazer alterações de teste para produção, basta mudar em um lugar. E pronto.

    A JNDI é uma API para acesso a serviços de diretórios que permite aplicações cliente descobrir e obter dados ou objetos através de um nome. A API JNDI é utilizada em aplicações Java para acessar recursos externos, como banco de dados, filas ou tópicos JMS e componentes da plataforma Java EE (Edson Gonçalves).

    Adicione ao projeto o driver do BD na pasta lib. Lembre-se de copiá-lo fisicamente para o eclipse, ou seja, saia do eclipse e copie o .jar, pois o eclipse não faz isso automaticamente quando add via library da própria IDE.

    Testando

    Para testar, vamos criar um simples servlet que vai estabelecer a conexão e, se der tudo tudo certo, não veremos nenhuma exceção e será impressa uma mensagem.

    Mas, antes disso, vamos criar uma página .jsp que chama o servlet. Fizemos isso para ser mais rápido e simples, já que precisamos apenas saber se o nosso pool está funcionando corretamente.

    Servlet.java

    Crie um package br.com.servlet.

    Crie um servlet TesteAPP, conforme abaixo:

     public class TesteAPP extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public TesteAPP() {
    super();
    // TODO Auto-generated constructor stub
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    try {
    Conexao.getConnection();
    System.out.println("conexão estabelecida com sucesso");
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();}}

    Nota: Se você usou o assistente do eclipse para criar um servlet, fique atento se não mudou o <url-pattern>. Caso não tenha feito, ele leva o mesmo nome da class Servlet.

    Index.jsp

    Apenas encaminhe a solicitação para o servlet TesteAPP. Execute o projeto, e veja o resultado esperado.

    Nota: Não se esqueça de verificar se o Banco de dados foi iniciado. Ou seja, deu start no BD? Se não, você vai receber uma exceção: Communication failure link.

    Simples, não? Vou ficando por aqui e espero que tenham gostado!

    Abraços, see you! :)