-
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
-
Java development 2.0
: Esta série do developerWorks explora tecnologias e ferramentas que estão redefinindo o
cenário de desenvolvimento Java, incluindo CouchDB
(novembro de 2009) e Bigtable
(maio de 2010).
- "
Cloud computing with Amazon Web Services, Part 5: Dataset processing in the cloud with
SimpleDB
" (Prabhakar Chaganti, developerWorks, fevereiro de 2009): Aprenda conceitos
básicos do Amazon SimpleDB (SDB) e explore algumas das funções fornecidas pela boto, uma
biblioteca Python de software livre para interagir com o SDB.
- "Eventually
Consistent - Revisited" (Werner Vogels, All Things Distributed, dezembro de 2008):
O CTO da Amazon explica o Teorema CAP de Eric Brewer e seu impacto na infraestrutura de
serviços da Web da Amazon.
- "NoSQL Patterns"
(Ricky Ho, Pragmatic Programming Techniques, novembro de 2009): Uma visão geral e listagens de
bancos de dados NoSQL, seguida por um olhar aprofundado sobre a arquitetura comum de bancos de
dados NoSQL.
- "Bigtable: A Distributed Storage System for
Structured Data" (Fay Chang et al., Google, novembro de 2006): Bigtable é um
sistema de armazenamento distribuído para gerenciar dados estruturados que foi criado para ser
escalado para um tamanho muito grande: petabytes de dados em milhares de servidores de bens.
- Procure na livraria tecnológica
livros sobre esses e outros assuntos técnicos.
-
Zona de tecnologia Java do developerWorks:
Encontre centenas de artigos sobre cada aspecto da programação Java.
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:
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:
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 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! :)