Passo 4 – Repositórios com
MongoDB
Neste último passo, a
persistência em memória será trocada por uma solução NoSQL. Para
que esse passo funcione, deve-se instalar primeiramente o MongoDB.
Não foi necessária nenhuma configuração adicional, tais como
local de dados, journaling, logs, entre outros. Decida essas
configurações do modo que for melhor.
MongoDB é um banco de
dados baseado em documentos da geração NoSQL, que significa não
estar preso ao modelo relacional. No entanto, existem problemas que
nos bancos relacionais não existem, tais como atualizações não
garantidas ou a falta de um relacionamento mais forte, por exemplo.
Por outro lado, não se
está preso em um modelo pré-definido de uma tabela de dados, com
regras restritivas para trabalhar com eles. Cada registro de uma
entidade pode ter suas próprias regras existindo ou não alguns
campos preenchidos. Não há a necessidade de atribuir a um campo um
valor null, porém essas informações devem ser tratadas na
aplicação de alguma forma.
Especificamente o banco
de dados MongoDB, trabalha com documentos de dados BSON, um formato
derivado do JSON. Também chamado de binary JSON, esse formato foi
projeto para ser eficiente em armazenamento e leitura de informações.
Para lidar com MongoDB,
deve-se adicionar algumas dependências do Spring que lidam com banco
de dados e com o banco de dados em questão. Deve-se alterar o código
fonte em alguns pontos da aplicação para essa adaptação.
Deve-se, primeiramente,
adicionar as dependências do Spring-data e do MongoDB no pom.xml.
Note que no passo anterior não foi adicionado o Spring-data, pois os
dados foram gravados em memória.
(1)
groupId.....:
org.springframework.data
artifactId..:
spring-data-mongodb
version.....:
1.7.0.DATAMONGO-1118-SNAPSHOT
(2)
groupId.....:
org.mongodb
artifactId..:
mongo-java-driver
version.....:
2.12.4
O segundo passo é
alterar as configurações da classe AppConfig. Deve-se:
Habilitar os pacotes
de repositórios, onde se encontrarão as classes de repositório.
Configurar o MongoDB
para ser injetado, com configurações oriundas de um arquivo de
propriedades.
Retirar a
configuração do DAO persistente em memória e apagar as classes
A listagem a seguir
mostra os trechos de código a serem considerados:
@Configuration
@PropertySource("classpath:mongodb.properties")
@EnableMongoRepositories(basePackages
= "org.crudpeople.repositories")
@ComponentScan(basePackages={"org.crudpeople.controller", "org.crudpeople.service"})
public
class AppConfig extends WebMvcConfigurationSupport {
(…)
@Bean
public
Mongo mongo() throws UnknownHostException {
return
new
MongoClient(
environment.getProperty("database.host")
);
}
@Bean
public
MongoTemplate mongoTemplate() throws UnknownHostException {
return
new MongoTemplate(mongo(),
environment.getProperty("database.name"));
}
}
Desse modo, toda vez que
o servidor estiver no ar, uma conexão com o banco de dados será
realizada.
O próximo passo ainda é
alterar a entidade para que ela represente um documento no banco de
dados MongoDB. Temos que entender que o MongoDB possui um banco de
dados, que abriga coleções, que abriga documentos. Neste projeto
temos a estrutura descrita na imagem a seguir.
Na classe de configuração
foi descrito em qual banco conectar. Na entidade, deve-se anotar que
ela é um documento, com a anotação @Document, e a qual coleção
pertence esse documento. A listagem abaixo mostra a entidade Pessoa
anotada como documento.
@Document(collection
= "pessoas")
public
class Pessoa {
(…)
}
O que ainda deve ser
modificado nessa classe é o ID, cujo tipo deve ser mudado para
String. Será aproveitado o id que o MongoDB gera automaticamente
para cada documento BSON em uma forma alfanumérica lembando um UUID.
Existem formas de implementar um id numérico e sequencial, mas não
estamos lidando com bancos de dados sequenciais, e sim com um NOSQL.
O próximo passo é criar
a interface de repositório e criar ela no pacote onde foi
configurado. Um repositório é uma abstração que o Spring provê
para acesso a dados de uma entidade. Não é necessário
implementá-la, somente quando existir a necessidade de fazer alguma
operação não previstas pelo interface MongoRepository.
@RepositoryDefinition(
domainClass=org.crudpeople.entities.Pessoa.class,
idClass=java.lang.String.class)
public
interface PessoaRepository extends MongoRepository{
}
Pronto. Já temos nosso
repositório. Nossa camada de persistência está pronta e
configurada.
Algumas correções de
código devem ser feitas no próximo passo. As classes estarão com
algum problema de tipos ou membros do tipo PessoaDAO. Corrigindo
esses probleminhas fará com que a aplicação se torne compilável
novamente. Existem dois pontos que devem ser considerados nessa
migração.
O primeiro ponto é na
classe PessoaService no método find, que é responsável por
procurar por parte de um nome. Com o repositório não é tão
trivial. Deve-se criar um objeto Query e definir os parâmetros. A
listagem abaixo mostra a implementação da solução.
public
List find(String nome) {
LOGGER.log(Level.INFO,
"find");
Query
query = new Query();
query.addCriteria(Criteria.where("nome").regex(nome));
return
mongoTemplate.find(query, Pessoa.class);
}
Outra modificação é
uma alteração pequena na tela de alteração. Ao inicializar a
tela, busca-se um registro de pessoa pelo seu id. O problema é que o
id gerado pelo MongoDB é alfanumérico e isso atrapalha um pouco o
AngularJS. Para resolver esse problema foi colocado o parâmetro do
método findById em aspas simples. A listagem abaixo mostra a solução
encontrada.
findById('${param['id']}')
Para verificar os registros cadastrados
no console do mongo devemos usar a seguinte lista de comandos:
Inicia o console do mongodb
mongo
Usa o banco de dados PessoasDB
use
PessoasDB
Pesquisa por todos os documentos na
coleção pessoas
db.pessoas.find()
O resultado é:
{
"_id" : ObjectId("54b2ee7744ae7df913204e75"),
"_class" : "org.crudpeople.entities.Pessoa",
"nome" : "Homer Simpson", "endereco" :
"Rua Evergreen Terrace, 742", "telefone" :
"(11)12345-1234" }
{
"_id" : ObjectId("54b2ef1644ae7df913204e76"),
"_class" : "org.crudpeople.entities.Pessoa",
"nome" : "Sheldon Cooper", "endereco" :
"Rua Los Robles, 2311", "telefone" :
"(11)12345-1234" }
{
"_id" : ObjectId("54b2ef3a44ae7df913204e77"),
"_class" : "org.crudpeople.entities.Pessoa",
"nome" : "Sherlock Holmes", "endereco"
: "Rua Baker, 221B", "telefone" :
"(11)12345-1234" }
{
"_id" : ObjectId("54b2ef8144ae7df913204e78"),
"_class" : "org.crudpeople.entities.Pessoa",
"nome" : "Frd Flintstones", "endereco"
: "Rua Cobblestone, 301", "telefone" :
"(11)12345-1234" }
{
"_id" : ObjectId("54b2efcb44ae7df913204e79"),
"_class" : "org.crudpeople.entities.Pessoa",
"nome" : "Peter Griffin", "endereco" :
"Rua Spooner, 31", "telefone" : "(11)12345-1234"
}
{
"_id" : ObjectId("54b2f00244ae7df913204e7a"),
"_class" : "org.crudpeople.entities.Pessoa",
"nome" : "Stan Smith", "endereco" :
"Rua Cherry, 1024", "telefone" : "(11)12345-1234"
}
{
"_id" : ObjectId("54b2f05f44ae7df913204e7b"),
"_class" : "org.crudpeople.entities.Pessoa",
"nome" : "Charles Xavier", "endereco" :
"Pista Graymalkin, 1407", "telefone" :
"(11)12345-1234" }
Note que o id, chamado de
_id, é um objeto do MongoDB chamado ObjectId e é uma chave
hexadecimal UUID. Esse é o id da entidade Pessoa. Adicionalmente, o
framework Spring-data MongoDB grava o nome da classe Java que foi usada.
Conclusão
O framework spring ajuda muito a tirar a complexidade do código, fazendo o programador a focar no negócio. Não é necessário pensar em servlets, abrir conexões com o banco de dados, pensar em como um grafo de objeto deve ser montado. Somente deve ser pensado uma vez e usar no projeto inteiro. O framework faz o resto.
O framework AngularJS ajuda muito a criar uma página web. Não é necessário mais utilizar snippets java para adicionar uma funcionalidade. Basta utilizar o AngularJS para montar uma tabela, trazer dados de um serviço para a tela e ainda obter atualizações em tempo real. Isso ainda sem pensar em tags JSF.
Criar uma aplicação com esses dois frameworks deixa a vida do desenvolvedor um pouco mais fácil. A parte mais importante ainda é fazer o algoritmo do sistema. Mas esses posts criam uma aplicação exemplo, nada real. Deve-se fazer uma prova de conceito, medindo tempo de desenvolvimento, complexidade de implementação e complexidade de integração com outras aplicações com outras tecnologias.
O importante é dar certo!