Écriture d'une application Web simple à l'aide de Spring MVC, Spring Data JPA et Hibernate

Bonjour, Habr! Je vous présente la traduction du guide «Spring MVC + Spring Data JPA + Hibernate - CRUD Example» de Nam Ha Minh.

Dans ce didacticiel Spring Java, vous apprendrez à configurer une application Spring MVC pour qu'elle fonctionne avec Spring Data JPA en développant une application Web simple qui vous permet de gérer les informations client.

À la fin de ce didacticiel, vous pouvez créer une application Web Java basée sur les technologies Spring MVC et Spring Data JPA, qui ressemble à ceci:

image

Programmes et technologies utilisés dans ce guide: Java 8, Apache Tomcat 9, MySQL Server 5.7, Eclipse IDE 4.7 (Oxygen), Spring Framework 5.1, Hibernate 5.4, Spring Data JPA 2.1.5 et Servlet 3.1.

Commençons par créer une base de données.

1. Création d'une base de données


Nous utiliserons MySQL. Dans notre exemple, nous travaillerons avec les données de la table client , qui se trouve dans le schéma nommé sales . La table client comprend 4 champs: id , nom , email et adresse :

image

Vous pouvez exécuter le script MySQL suivant pour créer le schéma et la table:

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. Création d'un projet dans Eclipse


Créez un projet Web dynamique dans Eclipse et convertissez-le en projet Maven: pour ce faire, cliquez avec le bouton droit sur le projet, sélectionnez Configurer> Convertir en projet Maven . Dans la boîte de dialogue Créer un nouveau POM qui s'ouvre, entrez les informations suivantes:

- ID de groupe: net.codejava
- ID d'artefact: CustomerManager

Assurez-vous également que la version JRE du projet Java est 8 ou ultérieure.

Ensuite, ouvrez pom.xml (le fichier Maven) pour configurer les dépendances de ce projet. Déclarez les propriétés de version pour les frameworks Spring et Hibernate:

 <properties> <spring.version>5.1.5.RELEASE</spring.version> <hibernate.version>5.4.1.Final</hibernate.version> </properties> 

Spécifiez la dépendance pour Spring Framework:

 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> 

Pour créer des applications Web Spring MVC:

 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> 

Pour utiliser 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> 

Nous utilisons Hibernate comme implémentation JPA, alors ajoutez la dépendance suivante:

 <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> 

Pour que l'application fonctionne avec MySQL, nous avons besoin d'une dépendance pour le pilote JDBC MySQL:

 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.14</version> <scope>runtime</scope> </dependency> 

Et maintenant les dépendances pour Java Servlet, JSP et 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> 

Créez deux packages Java à la racine du projet:
- net.codejava.config : pour les classes de configuration.
- net.codejava.customer : pour les classes d'application.

3. Création d'un fichier de configuration JPA


Puisque nous utilisons JPA, nous devons définir les propriétés de connexion à la base de données dans le fichier persistence.xml , et non dans hibernate.cfg.xml . Créez un nouveau répertoire nommé META-INF dans le dossier source du projet pour y placer le fichier persistence.xml :

image

Et entrez le code ci-dessous dans ce fichier:

 <?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> 

Comme vous pouvez le voir, nous spécifions les propriétés de connexion à la base de données, telles que l'URL, l'utilisateur, le mot de passe et la classe de pilote JDBC. Notez également que le nom SalesDB sera utilisé par nous dans le code de configuration.

4. Création d'une classe modèle


Créez une classe Customer qui correspond à la table client de la base de données comme suit:

 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; } //       .       IDE,  . } 

Comme vous pouvez le voir, nous utilisons l'annotation @Entity pour mapper cette classe à la table client (le nom de la classe est le même que le nom de la table). Tous les noms de champ de classe sont identiques aux noms de champ de la table. Le champ id a des annotations @Id et @GeneratedValue pour indiquer que ce champ est une clé primaire et que sa valeur est générée automatiquement.

5. Configuration de Spring MVC et Spring Data JPA


Ensuite, nous écrivons du code Java pour configurer Spring MVC et Spring Data JPA. Nous utiliserons la configuration basée sur Java, car elle est plus simple que XML.

Configurer le servlet Spring Dispatcher


Pour utiliser Spring MVC dans notre application, nous devons enregistrer le servlet Spring Dispatcher au démarrage de l'application en écrivant la classe suivante:

 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("/"); } } 

La méthode onStartup() de cette classe sera automatiquement appelée par le servlet lors du chargement de l'application. Le servlet Spring Dispatcher traite toutes les demandes en faisant correspondre l'URL "/" et recherche la configuration dans la classe WebMvcConfig , qui est décrite ci-dessous.

Configurer Spring MVC


Créez la classe WebMvcConfig dans le package net.codejava.config contenant le code suivant:

 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; } } 

Cette classe est marquée de l'annotation @Configuration indiquant à Spring qu'il s'agit d'un fichier de configuration. @ComponentScan indique à Spring de rechercher les classes de configuration dans le package net.codejava .

Dans cette classe, nous créons un bean qui reconnaît les vues en spécifiant un préfixe et un suffixe pour ces vues. Par conséquent, créez le répertoire views dans le WebContent/WEB-INF pour stocker les fichiers JSP.

Ici, vous pouvez ajouter d'autres configurations Spring MVC.

Configuration de Spring Data JPA


Pour travailler avec Spring Data JPA, nous devons créer deux composants beans: JpaTransactionManager et JpaTransactionManager . Par conséquent, nous allons créer une autre classe de configuration 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; } } 

Ici, nous utilisons deux annotations importantes:

  • @EnableJpaRepositories : indique Ă  Spring Data JPA de rechercher les classes de rĂ©fĂ©rentiel dans le package spĂ©cifiĂ© (net.codejava) pour injecter le code appropriĂ© au moment de l'exĂ©cution.
  • @EnableTransactionManagement : indique Ă  Spring Data JPA de gĂ©nĂ©rer du code pour gĂ©rer les transactions lors de l'exĂ©cution.

Dans cette classe, la première méthode crée une instance de EntityManagerFactory pour contrôler l'unité de persistance de notre SalesDB (ce nom est spécifié dans persistence.xml ci-dessus).

La dernière méthode crée une instance de JpaTransactionManager pour JpaTransactionManager , créée précédemment par la méthode.

Il s'agit de la configuration minimale requise pour utiliser Spring Data JPA.

Création d'une interface de référentiel


Créez une interface CustomerRepository qui étend l'interface CrudRepository définie dans 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> {    } 

C'est presque tout le code dont nous avons besoin pour accéder aux données. D'accord? Avec Spring Data JPA, nous n'avons pas besoin d'écrire de code DAO (Java Data Acces Object). CrudRepository simplement une interface qui étend l'interface CrudRepository , qui définit les méthodes CRUD telles que save() , findAll() , findById() , deleteById() , etc. Au moment de l'exécution, Spring Data JPA génère automatiquement du code.

Veuillez noter que nous devons spécifier le type de la classe de modèle et le type du champ de clé primaire lors de l'extension de CrudRepository : CrudRepository<Customer, Long> .

7. Création d'une classe de service


Ensuite, créez la 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); } } 

Remarquez l'annotation @Transactional qui @Transactional notre classe. Cela signifie que toutes les méthodes de cette classe seront interceptées par Spring Data JPA pour la gestion des transactions. Et l'instance d'interface CustomerRepository sera incorporée dans cette classe:

 @Autowired CustomerRepository repo; 

Cela semble magique car nous n'écrivons pas de code DAO, mais Spring Data JPA créera automatiquement une implémentation au moment de l'exécution.

Comme vous pouvez le voir, toutes les méthodes de cette classe sont destinées aux opérations CRUD. Il délègue simplement l'appel entier à l'objet CustomerRepository . Cette classe peut vous sembler redondante, mais il est nécessaire de séparer le niveau métier / service du niveau référentiel / DAO.

8. Création d'un contrôleur Spring MVC


Créez une classe CustomerContoroller pour gérer toutes les demandes des clients:

 package net.codejava.customer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @Controller public class CustomerController { @Autowired private CustomerService customerService; //     } 

Il s'agit d'une classe de contrôleur Spring MVC typique qui est annotée à l'aide de @Controller . Vous pouvez voir que l'instance CustomerService est injectée dans cet objet à l'aide de l'annotation @Autowired .

Nous écrirons les méthodes de traitement dans les sections suivantes.

9. Ajout d'une liste de clients


Tous les clients seront affichés sur la page d'accueil de notre application. Pour ce faire, ajoutez la méthode de traitement appropriée à notre classe CustomerController :

 @RequestMapping("/") public ModelAndView home() { List<Customer> listCustomer = customerService.listAll(); ModelAndView mav = new ModelAndView("index"); mav.addObject("listCustomer", listCustomer); return mav; } 

La page d'accueil de navigation ( index.jsp ) devrait ressembler Ă  ceci:

 <%@ 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> 

Vous pouvez maintenant démarrer l'application Web. Ajoutez quelques lignes à la table des clients et accédez à http://localhost:8080/CustomerManager/ et vous verrez quelque chose de similaire:

image

10. Ajout d'un nouvel utilisateur


Afin d'implémenter la fonction de création d'un nouveau client, nous devons écrire deux méthodes de gestionnaire. Et le premier affichera un nouveau formulaire pour ajouter un client:

 @RequestMapping("/new") public String newCustomerForm(Map<String, Object> model) { Customer customer = new Customer(); model.put("customer", customer); return "new_customer"; } 

new_customer.jsp le formulaire JSP lui-mĂŞme avec le nom 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> 

Maintenant, sur la page principale, vous verrez le lien Nouveau client , lorsque vous cliquez dessus, vous verrez un nouveau formulaire:

image

La deuxième méthode de gestionnaire traitera le bouton Enregistrer sous cette forme:

 @RequestMapping(value = "/save", method = RequestMethod.POST) public String saveCustomer(@ModelAttribute("customer") Customer customer) { customerService.save(customer); return "redirect:/"; } 

Comme vous pouvez le voir, il redirige le client vers la page d'accueil, après avoir correctement enregistré l'utilisateur.

11. Modifier les données utilisateur


Pour implémenter la fonction d'édition client, ajoutez la méthode de gestionnaire suivante à la 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; } 

edit_customer.jsp formulaire edit_customer.jsp , qui est appelé par cette méthode:

 <%@ 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> 

Cliquez sur le lien hypertexte Modifier à côté du client sur la page d'accueil, le formulaire de modification du client sera appelé, qui ressemblera à ceci:



La méthode du gestionnaire traite toujours le bouton Enregistrer .

12. Suppression d'un client


Pour implémenter la fonction de suppression, écrivez la méthode de gestionnaire suivante dans la classe CustomerController :

 @RequestMapping("/delete") public String deleteCustomerForm(@RequestParam long id) { customerService.delete(id); return "redirect:/"; } 

Cliquez sur le lien hypertexte Supprimer à côté du client sur la page principale. Le client sera supprimé et la liste sera mise à jour.

13. Recherche par les clients


Enfin, implémentons une fonction de recherche qui permet à l'utilisateur de rechercher des clients en entrant un mot-clé. La fonction de recherche recherche des mots clés dans trois champs: nom, email et adresse, pour lesquels nous devons écrire notre propre méthode dans l'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); } 

La méthode search() n'est qu'une méthode abstraite annotée avec @Query . La requête de recherche est une requête JPA.

Ajoutez ensuite la méthode à la classe CustomerService :

 public List<Customer> search(String keyword) { return repo.search(keyword); } 

Ajoutez maintenant une méthode de gestionnaire à la 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; } 

Et créez une search.jsp résultats de recherche 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> 

Pour tester la fonction de recherche, entrez un mot-clé dans le champ de recherche de la page d'accueil et appuyez sur Entrée. Vous verrez la page des résultats de la recherche:


Conclusions


Dans ce guide, vous avez appris à développer une application Web Spring MVC à l'aide de Spring Data JPA pour accéder aux données. Comme vous pouvez le voir, Spring Data JPA réduit et simplifie considérablement le code que nous devons écrire.

Ă€ titre de comparaison, voici la structure du projet dans l'IDE Eclipse:


Merci d'avoir lu!

Source: https://habr.com/ru/post/fr479286/


All Articles