Configuration du module métier
1. Structure
📁 quizmaker-backend/
├── 📁 quizmaker-domain/
│ └── src/main/java/fr/universite/nantes/quizmaker/data/
│ ├── entity/ # Entités JPA persistées
│ ├── repository/ # Interfaces d'accès aux données (Spring Data JPA)
│ └── service/ # Interfaces métier (contrats de service)
│ └── pom.xml
└── pom.xml
2. Configuration des paquets Java
Pour commencer, vous allez créer trois paquets Java qui vous aideront à organiser vos classes .
|
3. Implémentation d’un service
Le paquet fr.universite.nantes.quizmaker.data.service regroupe toutes les interfaces de service,
c’est-à-dire les contrats métier proposés par chaque domaine (authentification, utilisateur, etc.).
Les interfaces définissent les fonctionnalités de haut niveau sans se préoccuper de leur implémentation.
|
Cela permet de :
|
|
À présent, vous allez créer l’interface nommée
À ce stade, on ne fait qu’exposer une signature (pas d’implémentation). Cela permet de séparer la logique métier (implémentée plus tard) de la définition du service. Voici un exemple de service :
|
Indication de code
/**
* Authentifie un utilisateur à partir de son email et de son mot de passe.
* @param email email de l'utilisateur
* @param password mot de passe
* @return l'utilisateur authentifié (ou lève une exception en cas d'échec)
*/
User login(String email, String password);
4. Implémentation des entités
Le paquet fr.universite.nantes.quizmaker.data.entity contient les entités JPA représentant les tables de la base de données.
Chaque entité est une classe annotée avec l’annotation @Entity et mappée à une table via l’annotation @Table.
Ces entités définissent les champs qui seront persistés, ainsi que les métadonnées associées (nom de colonne, stratégie d’identifiant, etc.).
import jakarta.persistence.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Table(name = "user")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(nullable = false)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "firstname")
private String firstname;
@Column(name = "email")
private String email;
@Column(name = "password")
private String password;
// Getters & Setters
}
|
Dans ce projet, les entités peuvent être annotées avec |
|
Les entités ne doivent jamais être utilisées dans les contrôleurs pour retourner des réponses API. Utilisez des DTO pour exposer les données nécessaires au client, et ainsi éviter les fuites de structure interne ou de données sensibles. |
Chaque entité doit contenir contient :
|
Indication de code pour l’entité PersistentStudent
@Entity
@Table(name = "student")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class PersistentStudent {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(nullable = false)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "name")
private String name;
@Column(name = "firstname")
private String firstname;
@Column(name = "email")
private String email;
@Column(name = "password")
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFirstName(){
return firstname;
}
public void setFirstName(String firstname){
this.firstname = firstname;
}
public String getEmail(){
return email;
}
public void setEmail(String email){
this.email = email;
}
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
Indication de code pour l’entité PersistentTeacher
@Entity
@Table(name = "teacher")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class PersistentTeacher {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(nullable = false)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "name")
private String name;
@Column(name = "firstname")
private String firstname;
@Column(name = "email")
private String email;
@Column(name = "password")
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFirstName(){
return firstname;
}
public void setFirstName(String firstname){
this.firstname = firstname;
}
public String getEmail(){
return email;
}
public void setEmail(String email){
this.email = email;
}
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
5. Implémentation de référentiels
Le paquet fr.universite.nantes.quizmaker.data.repository contient les interfaces d’accès aux données.
Elles utilisent Spring Data JPA pour manipuler les entités en base de données sans avoir besoin d’implémenter manuellement les requêtes SQL.
Ces interfaces étendent JpaRepository et permettent d’accéder à des opérations courantes comme :
-
findById(…) -
findAll() -
save(…) -
deleteById(…)
| Grâce à Spring Data, ces méthodes sont automatiquement générées à l’exécution, ce qui réduit considérablement le code nécessaire pour interagir avec la base. |
Chaque référentiel est lié à une entité.
On lui donne généralement un nom clair reflétant son usage, souvent basé sur le nom de l’entité manipulée
(p.ex. : UserRepository pour l’entité User).
@Repository
public interface UserRepository extends JpaRepository<User, Long> {}
| Un référentiel ne contient aucune logique métier. Il sert uniquement à interagir avec la base de données, et doit être utilisé exclusivement au sein des services métier. |
Ces interfaces doivent hériter de l’interface |