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