Créer des entités avec JPA
Notions théoriques
Qu'est-ce qu'une entité JPA ?
Une entité JPA est une classe Java dont les instances sont persistées en base de données. Chaque instance correspond à une ligne dans une table.
| Doctrine (Symfony) | JPA (Spring Boot) |
|---|---|
#[ORM\Entity] | @Entity |
#[ORM\Table(name: 'articles')] | @Table(name = "articles") |
#[ORM\Id] | @Id |
#[ORM\GeneratedValue] | @GeneratedValue(strategy = GenerationType.IDENTITY) |
#[ORM\Column] | @Column |
#[ORM\Column(type: 'text')] | @Column(columnDefinition = "TEXT") |
Annotations JPA essentielles
import jakarta.persistence.*;
@Entity // Déclare une entité JPA
@Table(name = "articles") // Nom de la table (optionnel si identique au nom de classe en snake_case)
public class Article {
@Id // Clé primaire
@GeneratedValue(strategy = GenerationType.IDENTITY) // Auto-incrémentée (comme AUTO_INCREMENT)
private Long id;
@Column(nullable = false, length = 255) // Contraintes SQL
private String titre;
@Column(columnDefinition = "TEXT") // Type TEXT (au lieu de VARCHAR)
private String contenu;
// Getters et setters...
}
Depuis Spring Boot 3.x et Jakarta EE 9+, les annotations utilisent le package jakarta.persistence.* et non javax.persistence.*. Si IntelliJ propose les deux, choisissez toujours jakarta.
L'entité Article du projet MonBlog
package org.joliciel.monblog.entity;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import org.hibernate.annotations.CreationTimestamp;
import java.time.LocalDateTime;
@Entity
@Table(name = "articles")
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "Le titre est obligatoire")
@Size(min = 3, max = 255, message = "Le titre doit faire entre 3 et 255 caractères")
@Column(nullable = false, length = 255)
private String titre;
@NotBlank(message = "Le contenu est obligatoire")
@Column(columnDefinition = "TEXT", nullable = false)
private String contenu;
@CreationTimestamp // Remplie automatiquement à la création
@Column(name = "date_creation", updatable = false)
private LocalDateTime dateCreation;
// Constructeur sans argument requis par JPA
public Article() {}
// Constructeur pratique
public Article(String titre, String contenu) {
this.titre = titre;
this.contenu = contenu;
}
// Getters et setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getTitre() { return titre; }
public void setTitre(String titre) { this.titre = titre; }
public String getContenu() { return contenu; }
public void setContenu(String contenu) { this.contenu = contenu; }
public LocalDateTime getDateCreation() { return dateCreation; }
public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
}
Conventions de nommage
| Élément Java | Convention | Exemple |
|---|---|---|
| Classe entité | PascalCase (singulier) | Article, Utilisateur |
| Package | tout en minuscules | entity ou domain |
| Attributs | camelCase | dateCreation, nomUtilisateur |
| Colonne SQL | snake_case | date_creation, nom_utilisateur |
Bean Validation sur les entités
Les annotations de validation (package jakarta.validation.*) s'appliquent directement sur les attributs de l'entité :
@NotBlank(message = "Ce champ est obligatoire")
@Size(min = 2, max = 100)
@Email(message = "Format d'email invalide")
@Min(value = 0, message = "Doit être positif")
@Max(value = 150)
@Pattern(regexp = "^[A-Za-z]+$", message = "Lettres uniquement")
Ces annotations sont vérifiées automatiquement quand vous utilisez @Valid dans le contrôleur (séance 520).
L'annotation @CreationTimestamp
@CreationTimestamp (de Hibernate) remplit automatiquement la date et l'heure à la première sauvegarde de l'entité. Une fois sauvegardée, la valeur ne change plus grâce à updatable = false sur @Column.
En Doctrine Symfony, l'équivalent est #[ORM\Column(type: 'datetime_immutable')] #[Gedmo\Timestampable(on: 'create')] ou la méthode dans un lifecycle callback.
Exemple pratique
Voici l'entité Utilisateur qui sera utilisée pour l'authentification :
package org.joliciel.monblog.entity;
import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
@Entity
@Table(name = "utilisateurs")
public class Utilisateur {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Email(message = "Format d'email invalide")
@Column(unique = true, nullable = false, length = 180)
private String email;
@NotBlank
@Column(nullable = false)
private String password; // Sera haché avec BCrypt (séance 532)
@Column(length = 50)
private String role; // "ROLE_USER" ou "ROLE_ADMIN"
// Constructeur sans argument (requis par JPA)
public Utilisateur() {}
public Utilisateur(String email, String password, String role) {
this.email = email;
this.password = password;
this.role = role;
}
// Getters et setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
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; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
}
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Dans ce TP, vous allez créer l'entité Article du projet MonBlog.
Étape 1 — Créer le package entity et la classe Article
Dans IntelliJ, créez un package entity sous org.joliciel.monblog, puis créez la classe Article.
Les noms de tables SQL sont traditionnellement au pluriel (articles, utilisateurs) car une table contient plusieurs lignes. Les classes Java sont au singulier (Article, Utilisateur) car une instance représente un seul objet.
Étape 2 — Ajouter la clé primaire
Utilisez Long (objet, peut être null) plutôt que long (primitif) pour les clés primaires. Un id à null indique qu'un objet n'est pas encore sauvegardé en base — c'est une convention importante dans JPA.
Étape 3 — Ajouter le titre et le contenu avec validation
Mettez les contraintes à la fois sur les annotations JPA (@Column(nullable = false)) ET sur les annotations de validation (@NotBlank). JPA crée les contraintes SQL, Bean Validation les vérifie en Java avant d'envoyer la requête. Les deux couches se complètent.