Olá Habr! Apresento a você a tradução do guia 
“Spring MVC + Spring Data JPA + Hibernate - Exemplo CRUD” de Nam Ha Minh.
Neste tutorial do Spring Java, você aprenderá como configurar um aplicativo Spring MVC para trabalhar com o Spring Data JPA, desenvolvendo um aplicativo da web simples que permite gerenciar informações do cliente.
Após a conclusão deste tutorial, você pode criar um aplicativo da Web Java baseado nas tecnologias Spring MVC e Spring Data JPA, com a seguinte aparência:
Programas e tecnologias usados neste guia: Java 8, Apache Tomcat 9, MySQL Server 5.7, Eclipse IDE 4.7 (Oxigênio), Spring Framework 5.1, Hibernate 5.4, Spring Data JPA 2.1.5 e Servlet 3.1.
Vamos começar criando um banco de dados.
1. Criando um banco de dados
Vamos usar o MySQL. Em nosso exemplo, trabalharemos com dados na tabela de 
clientes , localizada no esquema chamado 
sales . A tabela de 
clientes possui 4 campos: 
id , 
nome , 
email e 
endereço :
Você pode executar o seguinte script MySQL para criar o esquema e a tabela:
CREATE DATABASE `sales`; CREATE TABLE `customer` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, `email` varchar(45) NOT NULL, `address` varchar(45) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
2. Criando um projeto no Eclipse
Crie um projeto dinâmico da Web no Eclipse e converta-o em um projeto Maven: para fazer isso, clique com o botão direito do mouse no projeto, selecione 
Configurar> Converter em projeto Maven . Na caixa de diálogo 
Criar novo POM que é aberta, digite as seguintes informações:
- ID do grupo: 
net.codejava- ID do artefato: 
CustomerManagerVerifique também se a versão do JRE para o projeto Java é 8 ou posterior.
Em seguida, abra o 
pom.xml (arquivo Maven) para configurar as dependências para este projeto. Declare as propriedades da versão para Spring e Hibernate Frameworks:
 <properties> <spring.version>5.1.5.RELEASE</spring.version> <hibernate.version>5.4.1.Final</hibernate.version> </properties> 
Especifique a dependência para o Spring Framework:
 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> 
Para criar aplicativos da Web Spring MVC:
 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> 
Para usar o Spring Data JPA:
 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>2.1.5.RELEASE</version> </dependency> 
Usamos o Hibernate como a implementação JPA, portanto, adicione a seguinte dependência:
 <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> 
Para que o aplicativo funcione com o MySQL, precisamos de uma dependência do driver JDBC do MySQL:
 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.14</version> <scope>runtime</scope> </dependency> 
E agora as dependências para Java Servlet, JSP e JSTL:
 <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> 
Crie dois pacotes Java na raiz do projeto:
- 
net.codejava.config : para classes de configuração.
- 
net.codejava.customer : para classes de aplicativos.
3. Criando um arquivo de configuração JPA
Como usamos o JPA, precisamos definir propriedades para conectar-se ao banco de dados no arquivo 
persistence.xml , e não no 
hibernate.cfg.xml . Crie um novo diretório chamado 
META-INF na pasta de origem do projeto para colocar o arquivo 
persistence.xml nele:
E digite o código abaixo neste arquivo:
 <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" version="2.1"> <persistence-unit name="SalesDB"> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/sales" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="(password)" /> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.format_sql" value="true" /> </properties> </persistence-unit> </persistence> 
Como você pode ver, especificamos propriedades para conectar-se ao banco de dados, como URL, usuário, senha e a classe do driver JDBC. Observe também que o nome 
SalesDB será usado por nós no código de configuração.
4. Criando uma classe de modelo
Crie uma classe 
Customer que mapeia para a tabela de 
clientes no banco de dados da seguinte maneira:
 package net.codejava.customer; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String email; private String address; protected Customer() { } protected Customer(String name, String email, String address) { this.name = name; this.email = email; this.address = address; }  
Como você pode ver, usamos a anotação 
@Entity para mapear essa classe para a tabela do 
cliente (o nome da classe é o mesmo que o nome da tabela). Todos os nomes de campo de classe são idênticos aos nomes de campo na tabela. O campo 
id possui anotações 
@Id e 
@GeneratedValue para indicar que esse campo é uma chave primária e seu valor é gerado automaticamente.
5. Configuração do Spring MVC e Spring Data JPA
Em seguida, escrevemos o código Java para configurar o Spring MVC e o Spring Data JPA. Usaremos a configuração baseada em Java, pois é mais simples que XML.
Configurar o Servlet Spring Dispatcher
Para usar o Spring MVC em nosso aplicativo, precisamos registrar o Servlet Spring Dispatcher ao iniciar o aplicativo, escrevendo a seguinte classe:
 package net.codejava.config; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class WebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext(); appContext.register(WebMvcConfig.class); ServletRegistration.Dynamic dispatcher = servletContext.addServlet( "SpringDispatcher", new DispatcherServlet(appContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } } 
O método 
onStartup() dessa classe será chamado automaticamente pelo servlet quando o aplicativo carregar. O Spring Dispatcher Servlet processa todas as solicitações correspondendo à URL "/" e procura a configuração na classe 
WebMvcConfig , descrita abaixo.
Configurar o Spring MVC
Crie a classe 
WebMvcConfig no pacote 
net.codejava.config contém o seguinte código:
 package net.codejava.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration @ComponentScan("net.codejava ") public class WebMvcConfig { @Bean(name = "viewResolver") public InternalResourceViewResolver getViewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); return viewResolver; } } 
Essa classe é marcada com a anotação 
@Configuration informando ao Spring que é um arquivo de configuração. 
@ComponentScan diz ao Spring para procurar por classes de configuração no pacote 
net.codejava .
Nesta classe, criamos um bean que reconhece visualizações especificando um prefixo e sufixo para essas visualizações. Portanto, crie o diretório 
views dentro do diretório 
WebContent/WEB-INF para armazenar arquivos JSP.
Aqui você pode adicionar outras configurações do Spring MVC.
Configurando o Spring Data JPA
Para trabalhar com o Spring Data JPA, precisamos criar dois componentes de beans: 
EntityManagerFactory e 
JpaTransactionManager . Portanto, criaremos outra classe de configuração 
JpaConfig :
 package net.codejava.config; import javax.persistence.EntityManagerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalEntityManagerFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableJpaRepositories(basePackages = {"net.codejava.customer"}) @EnableTransactionManagement public class JpaConfig { @Bean public LocalEntityManagerFactoryBean entityManagerFactory() { LocalEntityManagerFactoryBean factoryBean = new LocalEntityManagerFactoryBean(); factoryBean.setPersistenceUnitName("SalesDB"); return factoryBean; } @Bean public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory); return transactionManager; } } 
Aqui usamos duas anotações importantes:
- @EnableJpaRepositories: diz ao Spring Data JPA para procurar classes de repositório no pacote especificado (net.codejava) para injetar o código apropriado no tempo de execução.
- @EnableTransactionManagement: informa ao Spring Data JPA para gerar código para gerenciar transações em tempo de execução.
Nesta classe, o primeiro método cria uma instância de 
EntityManagerFactory para controlar a unidade de persistência do nosso 
SalesDB (esse nome é especificado em 
persistence.xml acima).
O último método cria uma instância do 
JpaTransactionManager para 
EntityManagerFactory , criada pelo método anterior.
Essa é a configuração mínima necessária para usar o Spring Data JPA.
Criando uma interface de repositório
Crie uma interface 
CustomerRepository que estenda a interface 
CrudRepository definida no Spring Data JPA:
 package net.codejava.customer; import java.util.List; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; public interface CustomerRepository extends CrudRepository<Customer, Long> {    } 
Este é quase todo o código necessário para acessar os dados. Apenas concorda? Com o Spring Data JPA, não precisamos escrever o código DAO (Java Data Acces Object). Apenas declare uma interface que estenda a interface 
CrudRepository , que define métodos CRUD, como 
save() , 
findAll() , 
findById() , 
deleteById() etc. No tempo de execução, o Spring Data JPA gerará automaticamente o código.
Observe que devemos especificar o tipo da classe de modelo e o tipo do campo de chave primária ao estender 
CrudRepository : 
CrudRepository<Customer, Long> .
7. Criando uma classe de serviço
Em seguida, crie a classe 
CustomerService :
 package net.codejava.customer; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @Transactional public class CustomerService { @Autowired CustomerRepository repo; public void save(Customer customer) { repo.save(customer); } public List<Customer> listAll() { return (List<Customer>) repo.findAll(); } public Customer get(Long id) { return repo.findById(id).get(); } public void delete(Long id) { repo.deleteById(id); } } 
Observe a anotação 
@Transactional que 
@Transactional nossa classe. Isso significa que todos os métodos desta classe serão interceptados pelo Spring Data JPA para gerenciamento de transações. E a instância da interface 
CustomerRepository será incorporada nesta classe:
 @Autowired CustomerRepository repo; 
Isso parece mágico, pois não estamos escrevendo código DAO, mas o Spring Data JPA criará automaticamente uma implementação em tempo de execução.
Como você pode ver, todos os métodos nesta classe são para operações CRUD. Ele simplesmente delega a chamada inteira para o objeto 
CustomerRepository . Essa classe pode parecer redundante para você, mas é necessário separar o nível de negócios / serviço do nível de repositório / DAO.
8. Criando um Spring MVC Controller
Crie uma classe 
CustomerContoroller para lidar com todas as solicitações dos clientes:
 package net.codejava.customer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @Controller public class CustomerController { @Autowired private CustomerService customerService;  
Essa é uma classe típica do Spring MVC Controller anotada usando o 
@Controller . Você pode ver que a instância 
CustomerService está sendo injetada nesse objeto usando a anotação 
@Autowired .
Escreveremos os métodos de processamento nas seções a seguir.
9. Adicionando uma lista de clientes
Todos os clientes serão exibidos na página inicial do nosso aplicativo.Para fazer isso, adicione o método de processamento apropriado à nossa classe 
CustomerController :
 @RequestMapping("/") public ModelAndView home() { List<Customer> listCustomer = customerService.listAll(); ModelAndView mav = new ModelAndView("index"); mav.addObject("listCustomer", listCustomer); return mav; } 
A página inicial de navegação ( 
index.jsp ) deve ficar assim:
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!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=ISO-8859-1"> <title>Customer Manager</title> </head> <body> <div align="center"> <h2>Customer Manager</h2> <form method="get" action="search"> <input type="text" name="keyword" />  <input type="submit" value="Search" /> </form> <h3><a href="/new">New Customer</a></h3> <table border="1" cellpadding="5"> <tr> <th>ID</th> <th>Name</th> <th>E-mail</th> <th>Address</th> <th>Action</th> </tr> <c:forEach items="${listCustomer}" var="customer"> <tr> <td>${customer.id}</td> <td>${customer.name}</td> <td>${customer.email}</td> <td>${customer.address}</td> <td> <a href="/edit?id=${customer.id}">Edit</a>   <a href="/delete?id=${customer.id}">Delete</a> </td> </tr> </c:forEach> </table> </div> </body> </html> 
Agora você pode iniciar o aplicativo da web. Adicione algumas linhas à tabela de 
clientes e acesse 
http://localhost:8080/CustomerManager/ e você verá algo semelhante:
10. Adicionando um novo usuário
Para implementar a função de criar um novo cliente, precisamos escrever dois métodos manipuladores. E o primeiro exibirá um novo formulário para adicionar um cliente:
 @RequestMapping("/new") public String newCustomerForm(Map<String, Object> model) { Customer customer = new Customer(); model.put("customer", customer); return "new_customer"; } 
Vamos escrever o próprio formulário JSP com o nome 
new_customer.jsp :
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"    pageEncoding="ISO-8859-1"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>     <!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=ISO-8859-1"> <title>New Customer</title> </head> <body>    <div align="center">        <h2>New Customer</h2>        <form:form action="save" method="post" modelAttribute="customer">            <table border="0" cellpadding="5">                <tr>                    <td>Name: </td>                    <td><form:input path="name" /></td>                </tr>                <tr>                    <td>Email: </td>                    <td><form:input path="email" /></td>                </tr>                <tr>                    <td>Address: </td>                    <td><form:input path="address" /></td>                </tr>                   <tr>                    <td colspan="2"><input type="submit" value="Save"></td>                </tr>                               </table>        </form:form>    </div> </body> </html> 
Agora, na página principal, você verá o link 
Novo cliente , quando clicar nele, verá um novo formulário:
O método do segundo manipulador processará o botão 
Salvar neste formulário:
 @RequestMapping(value = "/save", method = RequestMethod.POST) public String saveCustomer(@ModelAttribute("customer") Customer customer) { customerService.save(customer); return "redirect:/"; } 
Como você pode ver, ele redireciona o cliente para a página inicial, após salvar o usuário com êxito.
11. Alterar dados do usuário
Para implementar a função de edição do cliente, adicione o seguinte método manipulador à classe 
CustomerController :
 @RequestMapping("/edit") public ModelAndView editCustomerForm(@RequestParam long id) {    ModelAndView mav = new ModelAndView("edit_customer");    Customer customer = customerService.get(id);    mav.addObject("customer", customer);    return mav; } 
Vamos escrever o formulário 
edit_customer.jsp , chamado por este método:
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <!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=ISO-8859-1"> <title>Edit Customer</title> </head> <body> <div align="center"> <h2>Edit Customer</h2> <form:form action="save" method="post" modelAttribute="customer"> <table border="0" cellpadding="5"> <tr> <td>ID: </td> <td>${customer.id} <form:hidden path="id"/> </td> </tr> <tr> <td>Name: </td> <td><form:input path="name" /></td> </tr> <tr> <td>Email: </td> <td><form:input path="email" /></td> </tr> <tr> <td>Address: </td> <td><form:input path="address" /></td> </tr> <tr> <td colspan="2"><input type="submit" value="Save"></td> </tr> </table> </form:form> </div> </body> </html> 
Clique no hiperlink 
Editar ao lado do cliente na página inicial, o formulário de edição do cliente será chamado, que será mais ou menos assim:
O método manipulador ainda processa o botão 
Salvar .
12. Removendo um Cliente
Para implementar a função de exclusão, escreva o seguinte método de manipulador na classe 
CustomerController :
 @RequestMapping("/delete") public String deleteCustomerForm(@RequestParam long id) { customerService.delete(id); return "redirect:/"; } 
Clique no hiperlink 
Excluir ao lado do cliente na página principal. O cliente será excluído e a lista será atualizada.
13. Pesquisa por clientes
Por fim, vamos implementar uma função de pesquisa que permita ao usuário pesquisar clientes inserindo uma palavra-chave. A função de pesquisa pesquisa palavras-chave em três campos: nome, email e endereço, para os quais precisamos escrever nosso próprio método na interface 
CustomerRepository :
 package net.codejava.customer; import java.util.List; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; public interface CustomerRepository extends CrudRepository<Customer, Long> { @Query(value = "SELECT c FROM Customer c WHERE c.name LIKE '%' || :keyword || '%'" + " OR c.email LIKE '%' || :keyword || '%'" + " OR c.address LIKE '%' || :keyword || '%'") public List<Customer> search(@Param("keyword") String keyword); } 
O método 
search() é apenas um método abstrato anotado com 
@Query . A consulta de pesquisa é uma consulta JPA.
Em seguida, adicione o método à classe 
CustomerService :
 public List<Customer> search(String keyword) { return repo.search(keyword); } 
Agora adicione um método manipulador à classe 
CustomerController :
 @RequestMapping("/search") public ModelAndView search(@RequestParam String keyword) { List<Customer> result = customerService.search(keyword); ModelAndView mav = new ModelAndView("search"); mav.addObject("result", result); return mav; } 
E crie uma 
search.jsp resultado da pesquisa 
search.jsp :
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!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=ISO-8859-1"> <title>Search Result</title> </head> <body> <div align="center"> <h2>Search Result</h2> <table border="1" cellpadding="5"> <tr> <th>ID</th> <th>Name</th> <th>E-mail</th> <th>Address</th> </tr> <c:forEach items="${result}" var="customer"> <tr> <td>${customer.id}</td> <td>${customer.name}</td> <td>${customer.email}</td> <td>${customer.address}</td> </tr> </c:forEach> </table> </div> </body> </html> 
Para testar a função de pesquisa, digite uma palavra-chave no campo de pesquisa na página inicial e pressione Enter. Você verá a página de resultados da pesquisa:
Conclusões
Neste guia, você aprendeu como desenvolver um aplicativo da Web Spring MVC usando o Spring Data JPA para acessar dados. Como você pode ver, o Spring Data JPA reduz e simplifica bastante o código que precisamos escrever.
Para comparação, aqui está a estrutura do projeto no Eclipse IDE:
Obrigado pela leitura!