Aplicação Spring MVC com MongoDB

Neste artigo criaremos um aplicação simples utilizando Spring MVC juntamente com MongoDB.

Boa Leitura.

capa

Antes de começarmos a criar nosso projeto, primeiramente tem que conhecer um pouco sobre  o banco de dados mongodb e Mongo Shell. Sua instalação pode ser vista aqui Obtendo e Configurando o MongoDB em seu Ambiente.

Spring MVC  é um framework  Action Based que tem ganhado bastante espaço ultimamente no universo Java para criação de projeto Web, antes dele era Struts 1 que também é um framework Action Based.

O projeto vai ser bem simples, um crud utilizando mongodb com um relacionamento entre dois documentos.

Criando o Projeto

Com o Eclipse aberto, vá File -> New – > Maven Project irá abrir a seguinte Janela :

maven

clique em Next para ir para a seguinte tela :

maven2

clique em Next, na próxima deixe preenchida da seguinte forma  e clique em Finish:

blog2

com o projeto criado,vá em src/main/webapp, nela apague a pasta WEB-INF. Depois clique com o botão direito do mouse e vá em Properties, navegue até a opção Targeted Runtimes, marque a opção, que no caso vamos utilizar o Tomcat, depois clique em Uninstall Facets… :

target-maven

facets

ao chegar nesta tela desmaque Dynamic Web Module , altere Java 1.5 para 1.8 e clique em Finish. Abra novamente a mesma tela e maque Dynamic Web Module e mude de 2.3 para 3.1 e clique em Next para configura a proxima tela e a configure como abaixo :

web

Clique em Finish e depois em OK.

Agora iremos configurar nosso pom.xml, com a seguinte configurações :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>br.com.danieldias</groupId>
	<artifactId>SpringMongo</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>SpringMongo Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<!-- Mongo Driver -->
		<dependency>
			<groupId>org.mongodb</groupId>
			<artifactId>mongodb-driver</artifactId>
			<version>3.2.2</version>
		</dependency>

		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.3.0.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>4.3.0.RELEASE</version>
		</dependency>

		<!-- JSTL -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>SpringMongo</finalName>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>
</project>

Na pasta WEB-INF , configure o web.xml na seguinte forma :

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <display-name>SpringMongo</display-name>

  <servlet>
    <servlet-name>springDispatcherServlet</servlet-name>
    <servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
<servlet-mapping>
    <servlet-name>springDispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

Ainda dentro de WEB-INF crie um xml com o nome spring-context.xml, com o seguinte conteúdo e também crie uma pasta chamada views:

<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">

<!-- scaneia todos os pacotes a procura de componentes do Spring-->
  <context:component-scan base-package="br.com.danieldias"/> 

      <context:annotation-config />
	<mvc:annotation-driven />

<!-- configura css,js,etc -->
<mvc:resources location="/recursos/" mapping="/recursos/**"/>

	<!-- Configurando a localização das Views. -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
			<property name="prefix" value="/WEB-INF/views/"/>
			<property name="suffix" value=".jsp"/>
	</bean>

</beans>

Agora na pasta webapp crie uma pasta chamada recursos com as seguinte subpastas : css, js e imagens, dentro de cada uma delas  seguinte arquivos :

  • jquery-ui-1.9.2.custom.min.css
  • calendar.gif
  • datepicker-pt-BR.js
  • jquery-3.1.0.min.js
  • jquery-ui-1.9.2.custom.min.js

Depois clique em cima do projeto e de “Alt +F5” para fazer update do maven :

f5

Clique em OK e finalizamos a parte de criação projeto, podemos da inicio a codificação de nossas classes .

Criando a Constantes.java

Está classe é bem simples, ela irá somente conter valores constantes, que não serão modificadas. Isso para evitar ter muitas hardCode espalhado por todo o código, assim esse classe irá centralizar tudo de maneira organizada.

Crie uma classe chamada Constantes no package br.com.danieldias.commons, com o seguinte conteúdo :

package br.com.danieldias.commons;

/**
 * @author daniel
 * github:Daniel-Dos
 * daniel.dias.analistati@gmail.com
 * twitter:@danieldiasjava
 */
public class Constantes {

	/*Nome o Banco e da Collection*/
	public static final String BANCO_NOME = "danieldiasjava";
	public static final String COLLECTION_NOME = "pessoas";

	/*Nomes das Colunas para o MongoDB*/
	public static final String NOME = "nome";
	public static final String IDADE = "idade";
	public static final String PROFISSAO = "profissao";
	public static final String ENDERECO = "endereco";
	public static final String CIDADE = "cidade";
	public static final String BAIRRO = "bairro";
	public static final String ESTADO = "estado";
	public static final String NASCIMENTO = "nascimento";
	public static final String JUGS = "jugs";
}

Criando as Entidades

Crie as classes Pessoa.java e Endereco.java no package br.com.danieldias.model , com o seguinte conteúdo :

package br.com.danieldias.model;

import java.util.Calendar;

import org.springframework.format.annotation.DateTimeFormat;

/**
 * @author daniel
 * github:Daniel-Dos
 * daniel.dias.analistati@gmail.com
 * twitter:@danieldiasjava
 */
public class Pessoa {

	private String nome;
	private String profissao;
	private String jugs;
	private int idade;
	private Endereco endereco;

	@DateTimeFormat(pattern="dd/MM/yyyy")
	private Calendar dataNascimento;

	public Pessoa() {
		this("","","",0,null,null);
	}

	public Pessoa(String nome, String profissao,
		      String jugs, int idade,
		      Endereco endereco,Calendar dataNascimento) {
		this.nome = nome;
		this.profissao = profissao;
		this.jugs = jugs;
		this.idade = idade;
		this.endereco = endereco;
		this.dataNascimento = dataNascimento;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getProfissao() {
		return profissao;
	}

	public void setProfissao(String profissao) {
		this.profissao = profissao;
	}

	public String getJugs() {
		return jugs;
	}

	public void setJugs(String jugs) {
		this.jugs = jugs;
	}

	public int getIdade() {
		return idade;
	}

	public void setIdade(int idade) {
		this.idade = idade;
	}

	public Endereco getEndereco() {
		return endereco;
	}

	public void setEndereco(Endereco endereco) {
		this.endereco = endereco;
	}

	public Calendar getDataNascimento() {
		return dataNascimento;
	}

	public void setDataNascimento(Calendar dataNascimento) {
		this.dataNascimento = dataNascimento;
	}
}

A classe pessoa bem simples, apenas com uma anotação na dataNascimento para o Spring lidar com esse tipo.

package br.com.danieldias.model;

/**
 * @author daniel
 * github:Daniel-Dos
 * daniel.dias.analistati@gmail.com
 * twitter:@danieldiasjava
 */
public class Endereco {

	private String cidade;
	private String bairro;
	private String estado;

	public Endereco() {
		this("","","");
	}

	public Endereco(String cidade, String bairro, String estado) {
		this.setCidade(cidade);
		this.setBairro(bairro);
		this.setEstado(estado);
	}

	public String getCidade() {
		return cidade;
	}

	public void setCidade(String cidade) {
		this.cidade = cidade;
	}

	public String getBairro() {
		return bairro;
	}

	public void setBairro(String bairro) {
		this.bairro = bairro;
	}

	public String getEstado() {
		return estado;
	}

	public void setEstado(String estado) {
		this.estado = estado;
	}
}

Criando o Repositorio

Agora criaremos uma Inteface chamada MongoDAO e uma classe chamada PessoaDAO no package br.com.danieldias.persistencia, com os seguintes conteúdos:

package br.com.danieldias.persistencia;

import org.bson.Document;

import com.mongodb.client.MongoCursor;

import br.com.danieldias.model.Pessoa;

/**
 * @author daniel
 * github:Daniel-Dos
 * daniel.dias.analistati@gmail.com
 * twitter:@danieldiasjava
 */
public interface MongoDAO {

	void inserir(Pessoa pessoa);
	void atualizar(Pessoa pessoa);
	void excluir(Object _id);
	Document porId(Object _id);
	MongoCursor<Document>mostraTodos();
}

A classe PessoaDAO é onde fica todas as operações de CRUD para o MongoDB, nada muito fora do comum, tudo muito simples e fácil compreensão. Repare que estamos usando a classe Constantes aqui  no lugar de String para facilitar o entendimento e deixar o código mas limpo.

package br.com.danieldias.persistencia;

import static com.mongodb.client.model.Filters.eq;
import java.util.ArrayList;
import java.util.List;

import org.bson.Document;
import org.springframework.stereotype.Repository;

import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;

import br.com.danieldias.commons.Constantes;
import br.com.danieldias.model.Pessoa;

/**
 * @author daniel
 * github:Daniel-Dos
 * daniel.dias.analistati@gmail.com
 * twitter:@danieldiasjava
 */
@Repository
public class PessoaDAO implements MongoDAO {

	MongoClient conexao;
	MongoDatabase dataBase;
	MongoCollection<Document> collectionPessoas;

	public PessoaDAO() {
		conexao = new MongoClient();
		dataBase = conexao.getDatabase(Constantes.BANCO_NOME);
		collectionPessoas = dataBase.getCollection(Constantes.COLLECTION_NOME);
	}

	@Override
	public void inserir(Pessoa pessoa) {

		List<Document> jugs = new ArrayList<>();
		jugs.add(new Document(Constantes.NOME,pessoa.getJugs()));

		collectionPessoas.insertOne(
				new Document(Constantes.NOME,pessoa.getNome())
				.append(Constantes.IDADE, pessoa.getIdade())
				.append(Constantes.PROFISSAO, pessoa.getProfissao())
				.append(Constantes.ENDERECO,
						new Document(Constantes.CIDADE,pessoa.getEndereco().getCidade())
						.append(Constantes.BAIRRO, pessoa.getEndereco().getBairro())
						.append(Constantes.ESTADO, pessoa.getEndereco().getEstado())
						)
				.append(Constantes.NASCIMENTO, pessoa.getDataNascimento().getTime())
				.append(Constantes.JUGS,jugs)
				);
	}

	@Override
	public void atualizar(Pessoa pessoa) {

		collectionPessoas.updateOne(eq(Constantes.NOME,pessoa.getNome()),
				new Document("$set",
						new Document(Constantes.IDADE,pessoa.getIdade())
						.append(Constantes.PROFISSAO, pessoa.getProfissao())
						.append(Constantes.ENDERECO,
								new Document(Constantes.CIDADE,pessoa.getEndereco().getCidade())
								.append(Constantes.BAIRRO, pessoa.getEndereco().getBairro())
								.append(Constantes.ESTADO, pessoa.getEndereco().getEstado())
								)
						)
				);
	}

	@Override
	public void excluir(Object _id) {

		collectionPessoas.deleteOne(porId(_id));
	}

	@Override
	public Document porId(Object _id) {

		return collectionPessoas.find(eq("_id",_id)).first();
	}

	@Override
	public MongoCursor<Document> mostraTodos() {

		return collectionPessoas.find().iterator();
	}
}

Criando os Controles

O primeiro controle que iremos criar ,será o que chama a pagina principal listando todos os dados do banco quando iniciar a aplicação.

Crie uma nova classe chamada IndexController no package br.com.danieldias.controller, com o seguinte conteúdo :

package br.com.danieldias.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author daniel
 * github:Daniel-Dos
 * daniel.dias.analistati@gmail.com
 * twitter:@danieldiasjava
 */
@Controller
@RequestMapping("*")
public class IndexController {

	@RequestMapping("*")
	public String index() {
		return "redirect:/pessoas/listaPessoa";
	}
}

Ainda no mesmo package cria a classe PessoasControler com o seguinte conteúdo :

package br.com.danieldias.controller;

import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import br.com.danieldias.model.Pessoa;
import br.com.danieldias.persistencia.MongoDAO;

/**
 * @author daniel
 * github:Daniel-Dos
 * daniel.dias.analistati@gmail.com
 * twitter:@danieldiasjava
 */
@Controller
@RequestMapping("/pessoas")
public class PessoasControler {

	@Autowired
	MongoDAO dao;

	@GetMapping("/inserirPessoa.html")
	public ModelAndView cadastrar() {
		return new ModelAndView("inserirPessoa");
	}

	@GetMapping("/alterarPessoa.html/{_id}")
	public ModelAndView alterar(@PathVariable("_id") ObjectId _id) {
		return new ModelAndView("alterarPessoa","atualizar",dao.porId(_id));
	}

	@PostMapping("inserirPessoa")
	public String adicionar(Pessoa pessoa) {
		dao.inserir(pessoa);
		return "redirect:/pessoas/listaPessoa";
	}

	@GetMapping("listaPessoa")
	public String listar(Model model) {
		model.addAttribute("listas", dao.mostraTodos());
		return "lista";
	}

	@PostMapping("alterar")
	public String update(Pessoa pessoa) {
		dao.atualizar(pessoa);
		return "redirect:/pessoas/listaPessoa";
	}

	@GetMapping("remover/{_id}")
	public String deletar(@PathVariable("_id") ObjectId _id) {
		dao.excluir(_id);
		return "redirect:/pessoas/listaPessoa";
	}
}

Está classe também tem um conteúdo bem simples, a única diferença são as novas anotações para Mapping que a partir do Spring 4.3.0 , podemos está utilizando essas anotações : @GetMapping, @PostMapping, que são a mesma coisa quando fazemos desta maneira : @RequestMapping(value = “alterar”, method = “RequestMethod.POST”)

Criando as Views

Agora daremos inicio a criação de 3 páginas para nossa aplicação que são : alterarPessoa.jsp, inserirPessoa.jsp e lista.jsp, que devem ser criada na pasta views que fica dentro de WEB-INF .

Iniciaremos pela a página lista.jsp, onde a mesma terá uma tabela onde os dados serão apresentados, 3 links um para chamar a paǵina alterarPessoa.jsp passando um parâmetro que é seu id e um que irá chamar no controle o deletar com parâmetro id e um para estarmos adicionando os dados no formulario inserirPessoa.jsp

A página fica da seguinte forma :

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Lista de Pessoas</title>
</head>
<body>
		<h1 align="center">Listagem dos Dados</h1>
<a href="inserirPessoa.html">Adicionar</a>
		<table align="center" border="4">
		<tr bgcolor="gray">
		    <th>ID</th>
			<th>Nome</th>
			<th>Idade</th>
			<th>Profissão</th>
			<th>Cidade</th>
			<th>Bairro</th>
			<th>Estado</th>
			<th>Jugs</th>
			<th>Data</th>
			<th>Editar</th>
			<th>Deletar</th>
		</tr>
		<c:forEach items="${listas}" var="pessoas">
			<tr>
				<td>${pessoas._id}</td>
				<td>${pessoas.nome}</td>
				<td>${pessoas.idade}</td>
				<td>${pessoas.profissao}</td>
				<td>${pessoas.endereco.cidade}</td>
				<td>${pessoas.endereco.bairro}</td>
				<td>${pessoas.endereco.estado}</td>
				<td>${pessoas.jugs.get(0).nome}</td>
				<td>
				<fmt:formatDate value="${pessoas.nascimento}" pattern="dd/MM/yyyy"/>
				</td>
				<td><a href="alterarPessoa.html/${pessoas._id }">Alterar</a></td>
				<td><a href="remover/${pessoas._id}">Excluir</a></td>
			</tr>
		</c:forEach>
	</table>
</body>
</html>

Algo importante nesta tela. Aqui os atributos passado devem SER o mesmo que estão no mongoDB, ou seja as colunas tem que ter os mesmo nome. A mesma coisa nesse techo : ${pessoas.jugs.get(0).nome}, aqui estou retornado o primeiro posição no array, se quisermos chamar outra posição fazemos assim : ${pessoas.jugs.get(1).lideres}.

A proxima tela é um formulario bem simples com o seguinte conteudo :

<%@ page language="java" contentType="text/html; charset=UTF-8"     pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Inserir Pessoas</title>
	<link rel="stylesheet" href="../recursos/css/jquery-ui-1.9.2.custom.min.css">
<script src="../recursos/js/jquery-3.1.0.min.js"></script>
<script src="../recursos/js/jquery-ui-1.9.2.custom.min.js"></script>
<script src="../recursos/js/datepicker-pt-BR.js"></script>
<script type="text/javascript">
		$(function(){
		  $("#date").datepicker({
		      showOn:"button",
			  buttonImage:"../recursos/imagem/calendar.gif",
			  buttonImageOnly:true
		   });
		});
		</script>

</head>
<body>
<form  action="inserirPessoa" method="post">
<fieldset>
<legend>Dados</legend>

   Nome: <input type="text" name="nome" />

   Idade: <input type="number" name="idade"/>

   Profissão: <input type="text" name="profissao"/>

   Cidade: <input type="text" name="endereco.cidade"/>

   Bairro: <input type="text" name="endereco.bairro"/>

   Estado: <input type="text" name="endereco.estado"/>

   Data de Nascimento: <input id="date" type="text" name="dataNascimento" placeholder="dd/mm/yyyy"/>

   JUGS:
   <input type="checkbox" name="jugs" value="SouJava"/>SouJava
   <input type="checkbox" name="jugs" value="RioJug"/>RioJug
   <input type="checkbox" name="jugs" value="SouJava Campinas"/>SouJava Campinas

   <input type="submit" value="Cadastrar Dados."/></fieldset>
</form>

</body>
</html>

e última tela que contem um formulário já preenchido com os valores do banco que podem ser alterados :

<%@ page language="java" contentType="text/html; charset=UTF-8"     pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Alterar Pessoas</title>
</head>
<body>
<form  action="../alterar" method="post">
<fieldset>
<legend>Alteração de Dados</legend>

	Nome: <input type="text" name="nome" value="${atualizar.nome}" disabled="disabled"/>

    Idade: <input type="number" name="idade" value="${atualizar.idade}"/>

    Profissão: <input type="text" name="profissao" value="${atualizar.profissao}"/>

    Cidade: <input type="text" name="endereco.cidade" value="${atualizar.endereco.cidade}"/>

    Bairro: <input type="text" name="endereco.bairro" value="${atualizar.endereco.bairro}"/>

    Estado: <input type="text" name="endereco.estado" value="${atualizar.endereco.estado}"/>

              <input type="submit" value="Alterar Dados."/></fieldset>
</form>

</body>
</html>

Rodando a Aplicação

Com tudo pronto, podemos testar a nossa aplicação:

Primeiramente inicie o MongoDB  através do prompt/terminal com o seguinte comando : mongod, como na imagem

mongod

Depois rode a aplicação no tomcat , com o botão direito do mouse clique no seu projeto e vá em Run As -> Run on Server, ao inicia a aplicação a página principal será carregada com abaixo :

lista

Ao clicar em Adicionar irá para a tela de cadastro :

cadatrar

Ao clicar em adicionar, a pagina irá redirecionar para a tela principal novamente com os dados carregados :

retorno

Ao clicar no link Alterar, vai carregar a pagina de alteração de dados e se clicar em Excluir vai apagar o dado e vai voltar para a pagina principal :

alterar

RoboMongo

Com os nossos dados Gravados, podemos ver como fica a sua estrutura no banco, ao invés de utilizar o mongo Shell para visualizar os dados , irei usar uma ferramente de administraçao para está lidando com varias operações referente ao MongoDB, essa ferramente se chama RoboMongo , instalação facil basta descompactar e executar .

Ao executar o RoboMongo irá aparecer a seguinte tela :

robomongo

clique em Create , de um nome para a conexao e clique em OK :

teste

depois de salvo, clique em Connect, que irar leva-lo a seguinte pagina,basta clicar na collection pessoas e ira carregar os dados armazenados :

mostar

Bem isso é tudo, aqui aprendemos a como fazer uma aplicação Spring MVC com MongoDB e de quebra conhecemos uma nova ferramenta para o mesmo. O projeto pode ser baixado no meu GitHub.

REFERÊNCIAS

 http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/

PERSISTINDO DADOS COM HIBERNATE OGM

A última parte prática da  minha monografia de especialização em Desenvolvimento Java. Neste capitulo irá aprender a usar o Framework de Persistência Hibernate OGM para bancos NoSQL .

Boa Leitura.

Assim como existe o Hibernate ORM (object-relational mapping), que é utilizado para mapeamentos entre os bancos relacionais, existe também o Hibernate OGM (Object/Grid Mapper) para estar trabalhando com bancos NoSQL.

Segundo Leonard (2013), o Hibernate OGM utiliza módulos do Hibernate ORM tanto quanto possível, a arquitetura OGM essencialmente estende a arquitetura ORM, ligando diferentes componentes dentro e fora. De acordo com ele, o Hibernate ORM converte e persiste dado entre os bancos relacionais e as linguagens de programação orientada a objetos, utilizando um conjunto de interfaces e classes. Este inclui uma camada JDBC para esta ligando as bases de dados e envio de consultas e as interfaces persistentes e carregadores, que são responsáveis pela persistência e entidades de carga e coleções.

Leonard (2013) explica que o Hibernate OGM é destinado a realizar os mesmos objetivos que o ORM, porem usando NoSQL. A diferença entre eles, é que no ORM precisamos da camada JDBC, mas no OGM essa camada não é necessária, em vez disso ela oferece dois novos elementos que são: um provedor de armazenamento de dados e um dialeto de armazenamento de dados.

Marchioni (2015) explica que uma aplicação ira interagir com a JPA ou com a API nativa do Hibernate. Uma vez que ela utiliza os recursos do ORM como explicado anteriormente, onde estão contidos no núcleo do Hibernate. Por sua vez, são delegados do núcleo hibernate a execução de consultas e operações CRUD para o Hibernate OGM.

De acordo Marchioni (2015) o mecanismo de consulta ira conduzir a execução de instruções JP-QL para o armazenamento subjacente. Outras operações de CRUD vai ser executada para ser diretamente armazenada, com a mediação do provedor de armazenamento de dados, que seria o uso do controlador MongoDB para o nosso caso.

A figura 65 descreve a arquitetura do Hibernate OGM, mostrando sua relação com o Hibernate ORM, como foi explicado por Marchioni.

ogm
Figura 65 – Arquitetura Hibernate OGM Fonte: MARCHIONI, 2015. p. 118

CRIANDO UM PROJETO JAVA WEB UTILIZANDO HIBERNATE OGM

Iremos reaproveitar o projeto web criado na sessão anterior, para esta atualizando o mesmo para esta funcionando com o Hibernate OGM.

Primeiramente vamos adicionar a dependência do Hibernate OGM no arquivo pom.xml do projeto anterior. O arquivo deve contém os seguintes trechos:

      <depencendyManagement>
            <dependencies>
                  <dependency>
                         <groupId>org.hibernate.ogm</groupId>
                         <artifactId>hibernate-ogm-bom</artifactId>
                         <version>5.0.0.Final</version>
                         <type>pom</type>
                         <scope>import</scope>
                    </dependency>
              </dependencies>
      </dependencyManagement>

     <dependencies>
           <dependency>
                <groupId>org.hibernate.ogm</groupId>
                <artifactId>hibernate-ogm-mongodb</artifactId>
           </dependency>
    </dependencies>

Figura 66 – Dependência Hibernate OGM Fonte: Autoria Própria

A Figura 66, adicionamos duas dependências para o projeto. A primeira ira ser feita o download de toda a biblioteca para o Hibernate OGM. O segundo irá fazer o download do mongo drive.

MAPEANDO AS COLEÇÕES DE BANCO DE DADOS

Vamos agora adicionar classes Java, para fazer o mapeamento. Aqui utilizaremos a mesma classe da figura 56, mas com elementos para funcionar com framework. A figura 67, adicionamos anotações na classe para que seja reconhecida no hibernate OGM.

Assim como no Hibernate ORM, estas anotações têm o mesmo efeito no Hibernate OGM, onde:

  • @Entity: Uma classe anotada com ela se torna uma classe entidade, ou seja,
    se torna um documento e os seus atributos se tornam os campos do
    documento.
  • @Id: Diz que o atributo é chave primaria da tabela.
@Entity
public class Pessoa {

    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
     private String id;

     private String nome;
     private int idade;
     private String email;
     private String telefone;

     public Pessoa(String id,String nome, int idade, String email, String telefone) {
          this.id = id;
          this.nome = nome;
          this.idade = idade;
          this.email = email;
          this.telefone = telefone;
       }

     public Pessoa() {
       this.("","",0,"","");
   }

    // Getter e Setter foram emitido para abreviar.
 

Figura 67 – Classe entidade Fonte: Autoria Própria

CONFIGURANDO O PERSISTENCE.XML

Para podemos está acessando banco de dados, teremos que configura um arquivo de configuração do JPA chamado persistence.xml a sua configuração é bem semelhante quando se uso o Hibernate ORM.

Esse arquivo deve ser criado na seguinte pasta do projeto src/main/resources/META-INF:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

	<persistence-unit name="TCC" transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
		<class>br.com.danieldias.tcc.modelo.Pessoa</class>

		<properties>
			<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
			<property name="hibernate.ogm.datastore.database" value="TCC" />
			<property name="hibernate.ogm.datastore.host" value="127.0.0.1" />
			<property name="hibernate.ogm.datastore.provider" value="MONGODB" />
			<property name="hibernate.ogm.datastore.port" value="27017" />
			<property name="hibernate.ogm.datastore.create_database" value="true" />
		</properties>
	</persistence-unit>
</persistence>

Figura 68 – persistence.xml Fonte: Autoria Própria

INSERINDO COM HIBERNATE OGM

Modificaremos a classe InserirControle, para esta utilizando o JPA para persistir. O código sofrera poucas mudanças, pois iremos apenas mudar a parte de conexão.

Na Figura 69, trocamos a conexão que foi feita na Figura 57. Como podemos notar, o código diminuiu bastante se comparado com a outra.

@WebServlet("/InserirControler")
public class InserirControle extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // criando uma instancia de Pessoa
        Pessoa pessoa = new Pessoa();

        //Recuperando dados do JSP
        pessoa.setNome(request.getParameter("nome"));
        pessoa.setIdade(Integer.parseInt(request.getParameter("idade")));
        pessoa.setTelefone(request.getParameter("telefone"));
        pessoa.setEmail(request.getParameter("email"));

        // Criando o EntityManager
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("TCC");
        EntityManager em = emf.createEntityManager();

        // Criando a transação
        em.getTransaction.begin();

       // Persistindo Dados
       em.persist(pessoa);

      // Enviando o commit para o banco
      em.getTransaction.commit();
      em.close(); // Fechando a conexão
    }
}

Figura 69 – InserirControle Fonte: Autoria Própria.

LISTANDO COM HIBERNATE OGM

Modificaremos a classe ConsultarTodosControler, para trazer os dados a partir do JPA. A figura 70, demonstra como podemos trazer todos os dados da nossa coleção utilizando o JP-QL.

@WebServlet("/ConsultarTodosControler")
public class ConsultarTodosControler extends HttpServlet {
      private static final long serialVersionUID = 1L;

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        RequestDispacher visao = null;

        // Criando o EntityManager
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("TCC");
        EntityManager em = emf.createEntityManager();

       // Criando a transação
       em.getTransaction().begin();

      // Criando uma lista de pessoa / JP-QL
      List<Pessoa> pessoas = em.createQuery("FROM Pessoa",Pessoa.class).getResultList();
      em.getTransaction().commit();
      em.close();

     // Configurando um atributo para JSP listar os dados
     request.setAttribute("listas",pessoas);

    // Retorna para a pagina listar.jsp
    visao = request.getRequestDispacher("listar.jsp");
    visao.forward(request,response);
  }
}

Figura 70 – ConsultarTodosControle Fonte: Autoria Própria.

ATUALIZANDO COM HIBERNATE OGM

A classe AlterarControler, irá atualizar 3 campos da collection a partir de uma consulta pelo nome passando o parâmetro utilizando JP-QL, como demonstrada na figura 71.

@WebServlet("/AlterarControler")
public class AlterarControler extends HttpServlet {
     private static final long serialVersionUID = 1L;

     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

      Pessoa pessoa = new Pessoa();

     // Recuperando dados do JSP
     pessoa.setNome(request.getParameter("nome"));
     pessoa.setIdade(Integer.parseInt(request.getParameter("idade")));
     pessoa.setTelefone(request.getParameter("telefone"));
     pessoa.setEmail(request.getParameter("email"));

      // Criando a EntityManager
      EntityManagerFactory emf = Persistence.createEntityManagerFactroy("TCC");
      EntityManager em = emf.createEntityManager();

     // Criando a transação
     em.getTransaction().begin();

     //Criando uma consulta
     Query query = em.createQuery("FROM Pessoa where nome=:nome",Pessoa.class);
     query.setParameter("nome",pessoa.getNome());

     Pessoa id (Pessoa) query.getSingleResult();
     pessoa.setId(id.getId());
     pessoa.setNome(id.getNome());

     em.merge(pessoa);
     em.getTransaction().commit();
     em.close();
    }
}

Figura 71 – AlterarControle Fonte: Autoria Própria.

Após a fazer a consulta, irá trazer um único registro que coincide com o argumento passado. Logo após os métodos setId e setNome, recebe o valor da variável id, para que a mesma são sejam alteradas e que não criem um novo registro no banco.

DELETANDO COM HIBERNATE OGM

Por último, será modificada a classe DeletarControler. Onde utilizamos consulta nativa do MongoDB para estarmos deletando os dados. Onde foi criada uma variável String contendo a operação nativa do MongoDB, que no caso iremos deletar todos os documentos que contém o nome especificado ao passarmos o parâmetro no formato Json do MongoDB, conforme demonstrado na figura 72 .

@WebServlet("/DeletarControle")
public class DeletarControler extends HttpServlet {
     private static final long serialVersionUID = 1L;

     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

      Pessoa pessoa = new Pessoa();

     // Recuperando dados do JSP
     pessoa.setNome(request.getParameter("nome"));

      // Criando a EntityManager
      EntityManagerFactory emf = Persistence.createEntityManagerFactroy("TCC");
      EntityManager em = emf.createEntityManager();

     // Criando a transação
     em.getTransaction().begin();

    // Criando uma consulta nativa
    String query1 = "db.Pessoa.remove({'nome': '" + pessoa.getNome() + "'})";

    Query query = (Query) em.createNativeQuery(query1, Pessoa.class);
    query.executeUpdate();

    em.getTransaction().commit();
    em.close();
    }
}

Figura 72 – DeletarControle Fonte: Autoria Própria.

Contudo, finalizamos este capitulo demonstrando como podemos está construindo sistemas em Java sendo desktop ou web, utilizando MongoDB para armazenamento.

Visto que a implementação para fazer operações no banco via Driver Java é bem simples, já que os métodos contidos no driver são praticamente o mesmo apresentado no Mongo Shell, o que facilita muito no desenvolvimento.

Foi apresentado o Hibernate OGM, um framework para manipulação dos dados no MongoDB, que utilizar módulos do Hibernate ORM.

O framework facilitou ainda mais interação com o MongoDB utilizando JPA ou a API nativa do Hibernate e ainda permite a utilização de operações nativa do MongoDB, que é uma boa escolha se caso sentirmos limitado ao utilizar o Hibernate OGM.

REFERÊNCIAS

Leonard, Anghel. Pro Hibernate and MongoDB. Apress,2013.

Marchioni, Francesco. MongoDB for Java Developers. Birmingham: Packt Publishing Ltd,2015.