3 - Persistência Com Spring Data
3 - Persistência Com Spring Data
Descrição
Propósito
Preparação
Objetivos
Módulo 1
Spring framework
Descrever o funcionamento do framework Spring e do Spring Data.
Módulo 2
Módulo 3
Módulo 4
meeting_room
Introdução
Neste conteúdo, vamos abordar os elementos de persistência do
framework Spring com base em Spring Data e JPA, utilizando o
Spring Tools Suite. Inicialmente, veremos as características
básicas do Spring e aprenderemos a construir um sistema Web
padrão, baseado em rotas e controladores, persistindo os dados
em base H2.
1 - Spring framework
Ao final deste módulo, você será capaz de descrever o funcionamento
do framework Spring e do Spring Data.
Características gerais
Modularização do framework
video_library
Framework Spring e Spring
Data
Assista ao vídeo e confira os principais pontos sobre este tópico.
XML De Configuração
content_copy
Arquitetura de implementação
Observe que a camada Model será definida no pacote
exemplo01.model, onde as entidades são criadas com o mapeamento
objeto-relacional do JPA.
Java
content_copy
Java
content_copy
Enquanto a anotação Component coloca a classe no contexto do Spring,
ou seja, transforma-a em um bean, a anotação PersistenceContext
obtém o gerenciador de entidades por meio da fábrica configurada
anteriormente. O gerenciador será utilizado para consultar as entidades
ou manipulá-las, como nos métodos findAll e persist.
Java
content_copy
Java
content_copy
A classe GerenciadorProduto pertence à camada Controller, no pacote
exemplo01.controller. Utilizando a anotação Autowired, configuramos
automaticamente nosso DAO. Transactional define uma transação
gerenciada pelo contexto, podendo ser configurada como somente
leitura, quando não modificamos valores.
Java
content_copy
video_library
Arquitetura MVC com
Spring Framework
Assista ao vídeo e confira os principais pontos sobre este tópico.
H2 Database
Banco de dados Open Source, que funciona em memória, com um console
acessível pelo browser dentro do contexto da aplicação.
SQL
content_copy
Java
content_copy
Comentário
Como queremos testar as camadas Model e Controller, precisamos do
controlador no contexto do Spring, mediante a anotação Autowired, e de
um direcionamento para a linha de comando. Para alterar a execução,
precisamos do método commandLineRunner, anotado como Bean,
assumindo um processamento sequencial.
Rotas e controladores
video_library
Rotas e controladores
Assista ao vídeo e confira os principais pontos sobre este tópico.
Criação do projeto Persistencia002
Crie o projeto Persistencia002, com os pacotes com.persistencia, H2
Database, Spring Data JPA, Spring Web e Thymeleaf. Observe:
rotas
Endereços que iniciam ações nos controladores com subsequente
redirecionamento para a página de resposta. Essa é uma estratégia
adotada no Express, um servidor minimalista construído com NodeJS,
sistemas Web com ASP.NET, e no Spring Boot, entre outros.
Java
content_copy
A anotação Controller define um controlador Web capaz de responder
às solicitações GET e POST que serão utilizadas.
EnableTransactionManagement habilita transações via container do
Spring, e RequestMapping define a rota inicial de acesso. Como atributo,
há apenas uma instância de ProdutoDAO, colocada no contexto do
Spring pela anotação Autowired.
Atenção!
Ao adotar EnableTransactionManagement, as transações serão
gerenciadas pelo contexto do Spring de forma automática.
Cada método do controlador tem uma rota relativa para o acesso, bem
como o método HTTP utilizado. Uma rota relativa é complementada
pela inicial, como no método listaProdutos, com a rota de mesmo nome,
resultando em http://localhost:8080/web/produtos/listaProdutos.
Comentário
A lista de produtos, obtida via findAll, é fornecida com o apelido
produtos para o template por meio de um ModelMap. Para esse método,
o retorno é o nome do template, que se chamará listaProdutos.
${...} expand_more
Acessa o valor de uma variável, que pode ser local ou fornecida
no Model.
*{...} expand_more
#{...} expand_more
@{...} expand_more
~{...} expand_more
Página inicial
Para resolver o problema na chamada para a raiz, vamos adicionar a
classe HomeController ao pacote com.persistencia.controller:
Java
content_copy
Temos o direcionamento para o template home_tl quando a raiz do site
é requisitada no modo GET. Para criar o template, utilizamos o botão
direito sobre o diretório templates, dentro de resources, seguido de New
e File. Nesse caso, adotamos o nome home_tl.html. A extensão deve
ser digitada, e o conteúdo do arquivo é apresentado a seguir:
HTML
content_copy
HTML
content_copy
O primeiro link aponta para a rota /web/produtos/dadosProduto, sem a
complementação com o código, para iniciar o formulário em modo de
inclusão. Em seguida, temos uma divisão da classe container,
responsável por organizar os painéis que exibirão os dados.
Comentário
O texto é substituído pelo valor do campo, com a utilização de th:text,
tendo ainda os links para a exclusão, com o código fornecido pelo
parâmetro na requisição, e para a inclusão, em que acrescentamos o
código do produto ao final da rota, por meio da variável de associação
com o nome cod. Note que o uso de arroba é necessário para a
conversão de todos os endereços.
Java
content_copy
Agora, vamos definir o modelo para cadastro, criando o arquivo
dadosProduto.html no diretório templates:
HTML
content_copy
Comentário
Definido o objeto do formulário, os campos de entrada são associados a
seus atributos por meio da notação de asterisco, com a especificação
do atributo entre chaves, juntamente com o uso de th:field. A
configuração utilizada aqui efetuará o preenchimento automático dos
dados, bem como associará corretamente os nomes dos campos para
envio ao servidor.
Questão 1
A Controller
B Abstraction
C Presentation
D View
E Model
Questão 2
A Controller
B Autowired
C Component
D RequestMapping
E Transactional
SQL
content_copy
SQL
content_copy
No ambiente de programação orientado a objetos, é necessário efetuar
o mapeamento objeto-relacional, em que os conjuntos de registros são
expressos como coleções de objetos – técnica que já utilizamos ao
trabalhar com Spring Data e JPA.
Instalação do PostgreSQL
video_library
Instalação do PostgreSQL e
PGAdmin
Assista ao vídeo e confira os principais pontos sobre este tópico.
Ferramenta PGAdmin
A ferramenta administrativa do PostgreSQL é o pgAdmin. Para criar o
banco, clique com o botão direito na divisão Databases, escolha a opção
Create, seguida de Database, e forneça o nome do banco – que, no
caso, será loja:
Criação do banco de dados no pgAdmin.
SQL
content_copy
Java
content_copy
Java
content_copy
Java
content_copy
Você precisa alterar a conexão padrão com o banco de dados em
application.properties, no diretório resources:
Java
content_copy
Comentário
Algo que merece cuidado é a estratégia de criação, na qual o uso de
create apaga e cria as tabelas a partir dos campos das entidades JPA,
update cria as estruturas inexistentes, e none apenas utiliza as tabelas
do banco. Podemos executar o servidor, que não terá páginas de acesso
ainda, mas permitirá verificar se alguma configuração relacionada ao
banco ou às entidades JPA está incorreta, já que o console apresentaria
os erros.
Fundamentos do REST
video_library
Fundamentos do REST e a
ferramenta Postman
Assista ao vídeo e confira os principais pontos sobre este tópico.
Exemplo
O endereço http://localhost:8080/produto retornaria todos os produtos
da base, enquanto http://localhost:8080/produto/101 forneceria apenas
o produto cujo código tem valor 101, devido ao acréscimo da chave no
final do endereço.
check /produto
Modo: GET
Objetivo: Consulta
Exemplo de chamada:
http://localhost:8080/produto
check /produto/{codigo}
Modo: GET
Objetivo: Consulta
Exemplo de chamada:
http://localhost:8080/produto/101
check /produto
Modo: POST
Objetivo: Inclusão
Exemplo de chamada:
http://localhost:8080/produto
check /produto/{codigo}
M d PUT
Modo: PUT
Objetivo: Alteração
Exemplo de chamada: http://localhost:8080/
produto/101
check /produto/{codigo}
Modo: DELETE
Objetivo: Exclusão
Exemplo de chamada: http://localhost:8080/
produto/101
JSON
content_copy
video_library
API REST para o
PostgreSQL
Assista ao vídeo e confira os principais pontos sobre este tópico.
Definição da camada Controller
Agora, vamos à camada Controller! Inicie pela criação de
ProdutoService, no pacote com.persistencia.controller:
Java
content_copy
Atenção!
Para transformar atributos em propriedades, podemos clicar com o
botão direito sobre o código, no editor, e escolher Source, seguido de
Generate Getters and Setters.
JSON
content_copy
Após iniciar a execução de nosso servidor (no Spring Tool –
Persistencia003), basta efetuar a chamada da nova requisição, com o
clique no botão Send. Teremos como retorno apenas uma resposta do
tipo Http 200 Ok e um corpo vazio. É possível verificar a inclusão no
PostgreSQL por meio do pgAdmin.
Atenção!
Salve cada requisição, clicando no botão Save.
Java
content_copy
A classe será utilizada pelo controlador com o nome MovimentoService,
que será criado no pacote com.persistencia.controller:
Java
content_copy
Comentário
Como temos uma relação do tipo OneToMany em Produto, a forma mais
simples de obter as movimentações é por meio de getMovimentos, ou
seja, a partir do código do produto efetuamos a busca via prodDAO e
retornamos seus movimentos.
JSON
content_copy
Atenção!
Para testar a remoção do movimento, vamos criar a requisição de nome
Exclusão, na coleção Movimentos, apontando para um endereço como
http://localhost:8080/movimento/1/101, no modo DELETE.
Questão 1
A @ManyToOne
B @Entity
C @OneToMany
D @Id
E @ManyToMany
Parabéns! A alternativa A está correta.
Para as entidades JPA, um relacionamento de um-para-muitos deve
ser anotado na entidade dependente, como @ManyToOne, com a
recepção em uma instância da entidade principal. Já na principal,
devemos ter @OneToMany, com uma coleção de dependentes.
Com relação às demais, @ManyToMay define um relacionamento
de muitos-para-muitos, no qual as duas entidades são fortes,
@Entity define uma entidade, e @Id define a chave primária.
Questão 2
Atenção!
Enquanto no modelo relacional definimos esquemas fixos para
armazenagem, as estruturas de dados podem ser alteradas
dinamicamente em bases NoSQL.
Instalação do MongoDB
Assista ao vídeo e confira os principais pontos sobre este tópico.
Download do MongoDB.
JSON
content_copy
check $gt
Retorna quando o campo apresenta valor maior que
o especificado.
check $lt
Retorna quando o campo apresenta valor menor
que o especificado.
check $in
Verifica se combina com qualquer dos valores do
vetor.
check $nin
Verifica se não ocorre combinação com qualquer
dos valores do vetor.
check $and
Combinação lógica de condições com uso de and.
check $or
Combinação lógica de condições com uso de or.
check $exists
Retorna os documentos que apresentam
determinado campo.
check $all
Verifica se todos os valores do vetor estão
presentes.
check $size
Verifica se o campo, do tipo vetor, tem o tamanho
especificado.
check $regex
Seleciona os documentos a partir de uma
expressão regular.
Consulta MongoDB
content_copy
Devido à disposição dos campos na sintaxe JSON, operadores lógicos
são utilizados de forma diferente da adotada nas sintaxes mais comuns.
Eles são aplicados a vetores de operandos, e não na conexão entre eles.
Podemos observar uma consulta mais complexa a seguir:
Consulta MongoDB
content_copy
Observe o retorno dos livros que foram publicados após o ano 2000 e
antes do ano 2020, ou onde todos os nomes do conjunto ($all)
aparecem na lista de autores. Para a restrição do período de publicação,
foi utilizado o conector $and (ambas condições verdadeiras), enquanto
$or exigirá ao menos um filtro aceito.
video_library
Criando um projeto Spring
Data para o banco de dados
MongoDB
Assista ao vídeo e confira os principais pontos sobre este tópico.
Criação do projeto Persistencia004
Visando experimentar o uso de Spring Data para o banco de dados
MongoDB, vamos criar o projeto Persistencia004, do tipo Spring Starter
Project, com artefato de mesmo nome.
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=loja
server.port=8081
Java
content_copy
Utilizamos as coleções do MongoDB através da anotação Document. Da
mesma forma que antes, definimos o identificador através da anotação
Id, mas, agora, adotando o nome fixo _id ao nível do banco.
Java
content_copy
Java
content_copy
Inicialmente, temos a caracterização da classe como um serviço,
através da anotação Service, e instanciamos um executor de operações
do tipo MongoOperations, no contexto do Spring. No método getValor,
tendo como parâmetro o nome da sequência, podemos observar o
executor sendo utilizado.
Comentário
Temos também a opção de geração, em FindAndModifyOptions, quando
ainda não existe uma referência para a sequência, e a obtenção como
DataSequence. Ao final, teremos o retorno do valor corrente para o
campo atual, após a modificação.
Java
content_copy
video_library
API REST para o MongoDB
Assista ao vídeo e confira os principais pontos sobre este tópico.
Java
content_copy
Comentário
Os métodos incluir e alterar recuperam os dados do livro através de
RequestBody, mas, na inclusão, substituímos o id pelo valor
autoincrementado, obtido a partir do serviço.
Questão 1
A $in
B $all
C $exists
D $nin
E $gt
Questão 2
B @RequestMapping
C @PathVariable
D @RequestBody
E @ModelAttribute
Biblioteca Retrofit
video_library
Cliente REST com Retrofit
Assista ao vídeo e confira os principais pontos sobre este tópico.
filter_2
Selecione maven-archetype-quickstart (apache) como modelo
estrutural do projeto e clique em Next.
filter_3
Chegando à última tela do assistente, utilize o valor persistencia para o
grupo e Persistencia005 para o artefato, clicando em Finish para gerar o
projeto.
Assim, teremos:
Java
content_copy
Atenção!
As dependências também podem ser incluídas com o clique do botão
direito sobre o arquivo pom.xml e a escolha da opção Maven, seguida
de Add Dependency.
Java
content_copy
Note que temos a anotação Body, indicando que o parâmetro livro será
utilizado no corpo da requisição, enquanto Path instrui a utilizar o
parâmetro id na construção da rota. De forma geral, ocorre uma
inversão no sentido da utilização dos parâmetros: no cliente, eles
preenchem as informações necessárias e, no servidor, eles capturam os
valores enviados.
Java
content_copy
Java
content_copy
Antes de executar nosso novo projeto, devemos iniciar Persistencia004,
já que será o provedor de informações.
Java
content_copy
Código XML
content_copy
Implementação dos pacotes
Tudo que fizemos foi acrescentar as bibliotecas necessárias para
utilizar o Retrofit e o conversor de JSON. Salvando o arquivo, podemos
iniciar nossa implementação, a começar pela cópia dos pacotes
com.persistencia.model e com.persistencia.service de
Persistencia005, incluindo suas respectivas classes e interfaces.
Atenção!
Um erro deverá ocorrer ao nível da entidade Livro, devido ao fato de a
inferência de tipo para os genéricos ter sido adicionada em versões
mais recentes do compilador. É possível corrigir isso por meio da
sugestão oferecida para mudança do nível de código. Essa mudança
também pode ser feita com a abertura das propriedades do projeto, a
escolha da opção Java Compiler, no menu de navegação esquerdo, e a
marcação da opção use compliance from execution environment.
Java
content_copy
A classe Movimento adota um acesso mais plano, sem o uso de getters
e setters:
Java
content_copy
Java
content_copy
A construção da interface segue os moldes anteriores com:
Java
content_copy
Java
content_copy
Temos um objeto Retrofit apontando para a porta 8080, e subsequente
obtenção das instâncias de acesso baseadas em IProdutoService e
IMovimentoService. As chamadas para o Web Service de produtos são
similares às que foram utilizadas no cliente anterior, com a substituição
da classe Livro pela classe Produto.
Comentário
O método excluirMovimento, quando executado corretamente ao nível
do servidor, retornará sucesso ou falha em decorrência de restrições
que podem ocorrer durante o processamento, enquanto uma falha de
comunicação causar uma exceção, levando ao retorno de um
MovimentoVO com código zero e campo sucesso indicando a falha.
Comentário
Já que nossa arquitetura utiliza Web Services RESTful e a camada de
integração encapsulou as chamadas necessárias, não incluiremos
elementos relacionados à persistência no novo projeto. Será necessária
apenas a seleção das bibliotecas Spring Web e Thymeleaf.
Java
content_copy
Inicialmente, temos uma instância de ProdutoClient, o método privado
obterOrdenado, que recupera os produtos a partir da chamada para
obterProdutos, ordenando o resultado através do método sort, e um
Comparator. Esse método será chamado quando o template de destino
for produtoListagem, no qual os produtos serão exibidos em uma tabela
HTML.
Comentário
Note que excluirProduto conseguirá detectar apenas erros de conexão.
Será necessária uma consulta, após a tentativa de exclusão, para
verificar se a integridade referencial não impediu a remoção, de forma a
obter a mensagem correta. Em ambos os casos, teremos como destino
o template produtoListagem.
Java
content_copy
Java
content_copy
Java
content_copy
Como o novo aplicativo deverá executar em paralelo aos servidores
REST, ele deve ocupar uma porta diferente. Por isso, no diretório
resources é necessário alterar o arquivo application.properties para o
seguinte conteúdo, de forma a escolher a porta 8082:
server.port=8082
Persistencia003 expand_more
Porta: 8080
Característica: API REST para gerenciamento de produtos, com
persistência no banco de dados PostgreSQL.
Persistencia004 expand_more
Porta: 8081
Característica: API REST para gerenciamento de livros, com
persistência através do banco de dados MongoDB.
PersistenciaFinal expand_more
Porta: 8082
Característica: Sistema cadastral no modelo Web, comunicando-
se com as APIs por intermédio do projeto CamadaIntegracao.
Utilização do Bootstrap
O framework Bootstrap facilita muito a definição do design para páginas
HTML. Acesse https://getbootstrap.com:
Página oficial do Bootstrap.
Utilização do Thymeleaf
Como o Thymeleaf permite definir fragmentos reutilizáveis,
começaremos criando os modelos que serão incluídos nos templates de
resposta. O primeiro fragmento, com o nome inclusoes, será definido no
arquivo bsincludes.html, com a inclusão de todas as bibliotecas
necessárias:
HTML
content_copy
Página inicial
Outro fragmento será o menuprincipal, no arquivo menu.html, conforme
codificação:
HTML
content_copy
HTML
content_copy
HTML
content_copy
HTML
content_copy
HTML
content_copy
Após a parte comum e o título, temos a apresentação dos dados,
seguida do mesmo painel de apresentação de mensagens da listagem
de produtos.
HTML
content_copy
Para os livros, temos apenas uma exibição no formato cards, na qual o
conjunto fica em uma div com classe card-columns. Cada ocorrência
em uma div é configurada como card, repetida pelo th:each.
Questão 1
B Bootstrap
C Axios
D Retrofit
E Express
Questão 2
A btn-danger
B btn-primary
C btn-success
D btn-info
E btn-warning
Considerações finais
O framework Spring, adotado no mercado de forma ampla, desponta
como uma ferramenta de grande produtividade, por permitir a
construção de sistemas Web na arquitetura MVC, com prazos curtos e
garantia da qualidade necessária.
Explore +
Verifique a documentação Spring Tutorial, oferecida pelo Baeldung, com
uma excelente trilha de aprendizagem para o framework Spring.
Referências
BOAGLIO, F. Spring Boot. 1. ed. São Paulo: Casa do Código, 2017.
BRADSHAW, S.; BRAZIL, E.; CHODOROW K. MongoDB: definitive guide. 3.
ed. USA: O’Reilly, 2020.
COSMINA, I.; HARROP, R.; SCHAEFER, C.; HO, C. Pro Spring. 5. ed. USA:
Apress, 2017.
DEITEL, H.; DEITEL P. Java, como programar. 10. ed. São Paulo: Pearson,
2016.
OBE, R.; HSU, L. PostgreSQL up & running. 3. ed. USA: O’Reilly, 2018.
Download material
Relatar problema