TUTORIAL
SPRING MVC
CRUD WITH
SPRING DATA &
PostrgreSQL
Par
TECHNOLOGIES UTILISEES
JDK 1.7 + JDK 1.8
Tomcat 6
Eclipse STS
PostgresSQL4
Spring 4
JPA2
Hibernate 5
NOTE :
- Une connexion internet est obligatoire pour le fonctionnement de Maven
- La structure finale du projet est présentée à la fin du tutorial
- Il est fortement recommandé d’utiliser une version de Microsoft Office
autre que 2006 pour une bonne lisiblité du document
OBJECTIF
Créer une application de gestion des employés avec :
- Spring MVC côté présentation
- Spring CORE côté couche service
- Spring DATA côté repository
- JPA côté persistance
- PostgreSQL comme SGBD
MISE EN PLACE DE L’ENVIRONNEMENT DE DEVELOPPEMENT
(1) Télécharger « Eclipse STS »
(2) Décompresser l’archive dans un dossier proche de la racine ; exemple
« C:\soft »
MISE EN PLACE DE LA BASE DE DONNEES
(1) Télécharger et installer « PostgresSQL »
(2) Accéder à pgAdmin PostgresSQL Tool
(3) Créer un nouvelle base de données « spring »
1
(4) Créer la table « EMPLOYEE » avec une clé primaire et un
séquenceur avec l’outil « pgAdmin » de postgreSQL
a. Table : EMPLOYEE
b. Clé primaire : PK_EMPLOYEE_ID
c. Sequenceur : EMPLOYEE_SEQ
-- Table: "EMPLOYEE"
-- DROP TABLE "EMPLOYEE";
CREATE TABLE "EMPLOYEE"
(
"ID" numeric NOT NULL,
"FIRST_NAME" character(100),
"LAST_NAME" character(100),
CONSTRAINT "PK_EMPLOYEE_ID" PRIMARY KEY ("ID")
)
WITH (
OIDS=FALSE
);
ALTER TABLE "EMPLOYEE"
OWNER TO postgres;
-- Constraint: "PK_EMPLOYEE_ID"
-- ALTER TABLE "EMPLOYEE" DROP CONSTRAINT "PK_EMPLOYEE_ID";
ALTER TABLE "EMPLOYEE"
ADD CONSTRAINT "PK_EMPLOYEE_ID" PRIMARY KEY("ID");
2
-- Sequence: "EMPLOYEE_SEQ"
-- DROP SEQUENCE "EMPLOYEE_SEQ";
CREATE SEQUENCE "EMPLOYEE_SEQ"
INCREMENT 1
MINVALUE 1
MAXVALUE 999999999999999999
START 22
CACHE 1;
ALTER TABLE "EMPLOYEE_SEQ"
OWNER TO postgres;
MISE EN PLACE DU SERVEUR D’APPLICATION
(1) Télécharger « Tomcat »
(2) Décompresser l’archive dans un dossier proche de la racine ; exemple
« C:\soft »
CREATION DU PROJET
(1) Créer un projet « maven » sous STS :
a. Choisir un nouveau projet Spring
3
b. Choisir un nouveau projet Spring : « Spring Legacy Project »
(2) Créer un projet « Spring MVC Project »
4
(3) Spécifier la structure des paquets du projet « [Link] » :
(4) Mettre en place l’arborecence de packets suivantes :
(5) Ajouter les dépendances nécessaires :
a. Spring context API : core du framework Spring
b. Spring MVC API : framework MVC de Spring
c. Spring ORM API : framework d’accès DB Spring
d. Spring DATA API : framework Spring Data
e. Hibernate API : JPA provider implémentation
f. Hibernate Validator API : implémentation de Beans Validation
g. PostgresSQL JDBC API : implémentation PostgresSQL de JDBC
h. Apache Common Lang API : API utilitaire
5
<properties>
<java-version>1.8</java-version>
<[Link]-
version>[Link]</[Link]-version>
<[Link]-version>1.6.10</[Link]-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
<[Link]-version>[Link]</[Link]-version>
<[Link]-validator-
version>[Link]</[Link]-validator-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-context</artifactId>
<version>${[Link]-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j --
>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${[Link]-version}</version>
</dependency>
6
<!-- Database access dependencies - START -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-orm</artifactId>
<version>${[Link]-version}</version>
</dependency>
<!--
[Link] -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>hibernate-core</artifactId>
<version>${[Link]-version}</version>
</dependency>
<!--
[Link]
-->
<dependency>
<groupId>[Link]</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${[Link]-validator-version}</version>
</dependency>
<!-- [Link] --
>
<dependency>
<groupId>[Link]</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1212.jre7</version>
</dependency>
7
<!-- Spring Data -->
<!--
[Link]
data-jpa -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>[Link]</version>
</dependency>
<!--
[Link]
-->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-beans</artifactId>
<version>${[Link]-version}</version>
</dependency>
<!-- Database access dependencies - END -->
8
CREATION DU MODELE
Créer une nouvelle entité modèle « [Link] »
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Entity
@Table(name = "\"EMPLOYEE\"")
@NamedQueries({
@NamedQuery(name="[Link]",
query="SELECT emp FROM Employee emp"),
@NamedQuery(name="[Link]",
query="SELECT emp FROM Employee emp WHERE [Link]
= :firstName")})
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name = "\"EMPLOYEE_GENERATOR\"", sequenceName =
"\"EMPLOYEE_SEQ\"")
@GeneratedValue(strategy = [Link], generator =
"\"EMPLOYEE_GENERATOR\"")
@Column(name = "\"ID\"")
private Integer id;
9
@Column(name = "\"FIRST_NAME\"")
@Size(min=1, max=100)
@NotNull
@NotBlank
@NotEmpty
private String firstName;
@Column(name = "\"LAST_NAME\"")
@Size(min=1, max=100)
private String lastName;
@Formula("firstName" + "_" + "lastName")
private transient String completeName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
[Link] = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
[Link] = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
[Link] = lastName;
}
10
COUCHE REPOSITORY
Dans la couche Repository on va développer les classes Repository
de l’EMPLOYEE
DEVELOPPER L’INTERFACE REPOSITORY EMPLOYEE
« [Link] »
Source : [Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Repository
public interface EmployeeRepository extends JpaRepository<Employee,
Integer>{
List<Employee> findByFirstName(String firstName);
@Query("SELECT emp FROM Employee emp WHERE [Link]
LIKE :firstNameLike")
Page<Employee>
performSearchByFirstName(@Param("firstNameLike") String
firstNameLike,
Pageable pageable);
11
DEVELOPPER LA COUCHE SERVICE
Dans la couche Service on va développer les classes Service de
l’EMPLOYEE qui fait de simples appels aux méthodes de
« EmployeeRepository » pré-définies.
DEVELOPPER L’INTERFACE SERVICE EMPLOYEE
« [Link] »
Source : [Link]
package [Link];
import [Link];
import [Link];
public interface EmployeeService {
public List<Employee> list();
public Employee get(int id);
public void saveOrUpdate(Employee employee);
public void delete(int id);
12
DEVELOPPER L’IMPLEMENTATION SERVICE EMPLOYEE
« [Link]
Service : [Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Service
@Transactional
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
@Override
public List<Employee> list() {
return [Link]();
}
@Override
public Employee get(int id) {
return [Link](id);
}
@Override
public void saveOrUpdate(Employee employee) {
[Link](employee);
}
@Override
public void delete(int id) {
[Link](id);
}
}
13
CONFIGURER L’ACCES A LA BASE DE DONNEES DANS LE FICHIER
« [Link] »
La Configuration de l’accès à la base de données sera mise dans « root-
[Link] » le ficher root car le même projet peut exposer un Web service et
un module web en même temps en partageant le même accès à la base de
données
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="[Link]
xmlns:xsi="[Link]
xmlns:tx="[Link]
xmlns:jpa="[Link]
xmlns:context="[Link]
xsi:schemaLocation="[Link]
ns [Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
<!-- Root Context: defines shared resources visible to all
other web components -->
<!-- Database access configuration -->
<bean id="entityManagerFactoryBean"
name="entityManagerFactoryBean"
class="[Link]
rFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan"
value="[Link]" />
<property name="persistenceProvider">
<bean
class="[Link]" />
</property>
14
<property name="jpaProperties">
<props>
<prop
key="[Link]">[Link]</p
rop>
<prop key="hiberate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="dataSource" name="dataSource"
class="[Link]
">
<property name="driverClassName"
value="[Link]"/>
<property name="url"
value="jdbc:postgresql://localhost:5432/spring4"/>
<property name="username" value="postgres"/>
<property name="password" value="sayo"/>
</bean>
<bean id="transactionManager" name="transactionManager"
class="[Link]">
<property name="entityManagerFactory"
ref="entityManagerFactoryBean"/>
</bean>
15
<tx:annotation-driven transaction-manager="transactionManager"/>
<jpa:repositories base-
package="[Link]"
entity-manager-factory-
ref="entityManagerFactoryBean"
transaction-manager-
ref="transactionManager"/>
<context:component-scan base-
package="[Link]" />
</beans>
Note : il faut remplacer le mot de passe de la DB « sayo » par celui
que vous avez saisie lors de l’installation de postgreSQL.
16
DEVELOPPER LA COUCHE PRESENTATION
Dans ce tutorial on va utiliser la notion de ModelAttribute
DEVELOPPER LE CONTROLEUR « [Link] »
Source : [Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
/**
* Handles requests for the application home page.
*/
@Controller
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@RequestMapping("/")
public String handleRequest(Model model) throws Exception {
List<Employee> listEmployees = [Link]();
[Link]("employeeList", listEmployees);
return "employeeList";
}
17
/**
* load new user form
*
* @param model
* @return
*/
@RequestMapping(value = "/new", method = [Link])
public String newEmployee(Model model) {
[Link]("employee", new Employee());
return "employeeForm";
}
/**
* delete user
*
* @param id
* @param model
* @return
*/
@RequestMapping(value = "/delete", method =
[Link])
public String deleteEmployee(@RequestParam("id") Integer id,
Model model) {
[Link](id);
return "redirect:/";
}
18
/**
* save or create user
*
* @param employee
* @return
*/
@RequestMapping(value = "/save", method = [Link])
public String saveEmployee(@ModelAttribute Employee employee)
{
[Link](employee);
return "redirect:/";
}
}
19
DEVELOPPER LE CONTROLEUR « [Link] »
Source : EmployeeInfoController
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
/**
* Handles requests for the application home page.
*/
@Controller
public class EmployeeInfoController {
@Autowired
private EmployeeService employeeService;
@ModelAttribute
public Employee loadEmployee(@RequestParam("id") Integer id)
{
return [Link](id);
}
20
/**
* edit user form
*
* @param employee
* @param model
* @return
*/
@RequestMapping(value = "/edit", method = [Link])
public String editEmployee(@ModelAttribute Employee employee,
Model model) {
[Link]("employee", employee);
return "employeeForm";
}
/**
* User info
*
* @param employee
* @param model
* @return
*/
@RequestMapping(value = "/info", method = [Link])
public String findEmployee(@ModelAttribute Employee employee,
Model model) {
[Link]("employee", employee);
return "employeeInfo";
}
21
DEVELPPER LES PAGES JSP
[Link]
Source : [Link]
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"[Link]
<%@ taglib uri="[Link] prefix="c"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-
8">
<title>Home</title>
</head>
<body>
<c:url var="newEmployeeURL" value="/new" />
<div align="center">
<h1>Employees List</h1>
<h2>
<a href="${newEmployeeURL}">New Employee</a>
</h2>
<table border="1">
<th>No</th>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Actions</th>
22
<c:forEach var="employee" items="${employeeList}"
varStatus="status">
<tr>
<td>${[Link] + 1}</td>
<td>${[Link]}</td>
<td>${[Link]}</td>
<td>${[Link]}</td>
<td>
<c:url var="editEmployeeURL"
value="/edit">
<c:param name="id"
value="${[Link]}" />
</c:url>
<c:url var="deleteEmployeeURL"
value="/delete">
<c:param name="id"
value="${[Link]}" />
</c:url>
<a href="${editEmployeeURL}">Edit</a>
<form action="${deleteEmployeeURL}"
method="post"
name="deleteEmployee">
<input type="hidden" name="id"
value="${[Link]}" /> <input
type="submit"
value="Delete" />
</form></td>
</tr>
</c:forEach>
</table>
</div>
</body>
</html>
23
[Link]
Source : [Link]
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"[Link]
<%@ taglib prefix="form"
uri="[Link]
<%@ taglib uri="[Link] prefix="c"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>New or Edit User</title>
</head>
<body>
<c:url var="saveEmployeeURL" value="/save" />
<div align="center">
<h1>New/Edit User</h1>
<table>
<form:form action="${saveEmployeeURL}" method="post"
modelAttribute="employee">
<form:hidden path="id" />
<tr>
<td>First Name:</td>
<td><form:input path="firstName"
maxlength="100"/></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName"
maxlength="100"/></td>
</tr>
24
<tr>
<td colspan="2" align="center"><input
type="submit"
value="Save"></td>
</tr>
</form:form>
</table>
</div>
</body>
</html>
25
CONFIGURER LE MODULE WEB
CONFIGURER LE WEB CONTEXT SPRING « [Link] »
Dans ce fichier de configuration, on va configurer le module WEB :
- Activer le Spring MVC
- Indiquer l’emplacement des contrôleurs
- Décrire la technologie de la couche présentation (VIEW) qui est dans ce
tutoriels les JSP.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="[Link]
xmlns:xsi="[Link]
xmlns:mvc="[Link]
xmlns:context="[Link]
xsi:schemaLocation="[Link]
ns [Link]
[Link]
[Link]
[Link]
[Link]
default-autowire="byName">
<!-- DispatcherServlet Context: defines this servlet's request-
processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven />
26
<!-- Handles HTTP GET requests for /resources/** by efficiently
serving up static resources in the ${webappRoot}/resources
directory -->
<mvc:resources mapping="/resources/**" location="/resources/"
/>
<!-- Resolves views selected for rendering by @Controllers
to .jsp resources in the /WEB-INF/views directory -->
<bean
class="[Link]
solver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<context:component-scan base-
package="[Link]" />
</beans>
27
CONFIGURER LE « [Link] »
Dans le fichier « [Link] » on va :
- Indiquer l’emplacement des fichiers de configuration
- Configurer le composant qui va charger le module
- Configurer le MVC2 de Spring MVC
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
[Link]
<!-- The definition of the Root Spring Container shared by
all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/[Link]</param-
value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and
Filters -->
<listener>
<listener-
class>[Link]</liste
ner-class>
</listener>
28
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-
class>[Link]</servlet-
class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-
[Link]</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
29
DEPLOIEMENT
Ajouter « Tomcat » dans STS
Déployer le projet dans le serveur d’application
STRUCTURE FINALE FU PORJET
30