This commit is contained in:
MAIZY Amaury 2025-04-30 09:01:07 +02:00
parent c83632ea6d
commit d66be27cfe
18 changed files with 173 additions and 98 deletions

View file

@ -33,7 +33,7 @@ public class Editeur {
@JsonManagedReference @JsonManagedReference
@ToString.Exclude @ToString.Exclude
@OneToMany(mappedBy = "editeur", cascade = CascadeType.REMOVE) // OneEditeurToManyJeux @OneToMany(mappedBy = "editeur", cascade = {CascadeType.REMOVE, CascadeType.PERSIST}) // OneEditeurToManyJeux
private List<Jeu> jeux; private List<Jeu> jeux;
public Editeur(String nom, String logo) { public Editeur(String nom, String logo) {

View file

@ -1,8 +1,10 @@
package fr.clelia.avis.business; package fr.clelia.avis.business;
import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NonNull; import lombok.NonNull;
@ -11,6 +13,7 @@ import java.util.List;
@Entity @Entity
@Data @Data
@Builder
public class Jeu { public class Jeu {
@Id @Id
@ -25,9 +28,8 @@ public class Jeu {
@JsonBackReference @JsonBackReference
private Editeur editeur; private Editeur editeur;
@ManyToMany @ManyToMany(fetch = FetchType.EAGER)
@NonNull @NonNull
@JsonManagedReference // On souhaite voir en Json les plateformes du jeu
private List<Plateforme> plateformes; private List<Plateforme> plateformes;
private LocalDate dateDeSortie; private LocalDate dateDeSortie;

View file

@ -16,9 +16,7 @@ public class Joueur extends Utilisateur {
private LocalDate dateDeNaissance; private LocalDate dateDeNaissance;
public Joueur(String pseudo, String email, String motDePasse, LocalDate dateDeNaissance) { public Joueur(String pseudo, String email, String motDePasse, LocalDate dateDeNaissance) {
this.setPseudo(pseudo); super(pseudo, email, motDePasse);
this.setEmail(email);
this.setMotDePasse(motDePasse);
this.dateDeNaissance = dateDeNaissance; this.dateDeNaissance = dateDeNaissance;
} }
} }

View file

@ -6,6 +6,8 @@ import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import org.springframework.boot.convert.DataSizeUnit; import org.springframework.boot.convert.DataSizeUnit;
import java.time.LocalDate;
@Entity @Entity
@Data @Data
@SuperBuilder @SuperBuilder
@ -15,9 +17,7 @@ public class Moderateur extends Utilisateur {
private String numeroDeTelephone; private String numeroDeTelephone;
public Moderateur(String pseudo, String email, String motDePasse, String numeroDeTelephone) { public Moderateur(String pseudo, String email, String motDePasse, String numeroDeTelephone) {
this.setPseudo(pseudo); super(pseudo, email, motDePasse);
this.setEmail(email);
this.setMotDePasse(motDePasse);
this.setNumeroDeTelephone(numeroDeTelephone); this.setNumeroDeTelephone(numeroDeTelephone);
} }
} }

View file

@ -26,8 +26,4 @@ public class Plateforme {
@NonNull @NonNull
private String nom; private String nom;
@ManyToMany(mappedBy="plateformes")
@JsonIgnore
@ToString.Exclude
private List<Jeu> jeux;
} }

View file

@ -25,4 +25,10 @@ public abstract class Utilisateur {
@OneToOne @OneToOne
protected Avatar avatar; protected Avatar avatar;
protected Utilisateur(String pseudo, String email, String motDePasse) {
this.pseudo = pseudo;
this.email = email;
this.motDePasse = motDePasse;
}
} }

View file

@ -1,17 +1,18 @@
package fr.clelia.avis.controller; package fr.clelia.avis.controller;
import fr.clelia.avis.exception.EditeurInexistantException;
import fr.clelia.avis.service.EditeurService; import fr.clelia.avis.service.EditeurService;
import fr.clelia.avis.util.ReponseApi;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
@Controller @Controller
public class EditeurController { public class EditeurController {
// Dépendance // Dépendance
private final EditeurService editeurService; private EditeurService editeurService;
public EditeurController(EditeurService editeurService) { public EditeurController(EditeurService editeurService) {
this.editeurService = editeurService; this.editeurService = editeurService;
@ -31,4 +32,5 @@ public class EditeurController {
modelAndView.addObject("nom", nomRecherche); modelAndView.addObject("nom", nomRecherche);
return modelAndView; return modelAndView;
} }
} }

View file

@ -1,24 +0,0 @@
package fr.clelia.avis.controller;
import fr.clelia.avis.business.Editeur;
import fr.clelia.avis.repository.EditeurRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/editeur")
public class EditeurRestController {
@Autowired
private EditeurRepository editeurRepository;
@GetMapping("/{id}")
public Editeur getEntityById(@PathVariable int id) {
return editeurRepository.findById(id);
}
}

View file

@ -0,0 +1,49 @@
package fr.clelia.avis.controller.rest;
import fr.clelia.avis.business.Editeur;
import fr.clelia.avis.exception.EditeurInexistantException;
import fr.clelia.avis.service.EditeurService;
import fr.clelia.avis.util.ReponseApi;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@AllArgsConstructor
@RestController
@RequestMapping("api/editeurs")
public class EditeurRestController {
private final EditeurService editeurService;
@GetMapping("")
@Operation(summary="Récupère tous les éditeurs")
public List<Editeur> getEditeurs() {
return editeurService.recupererEditeurs();
}
@GetMapping("/{id}")
@Operation(summary="Récupère un éditeur par son id")
public Editeur getEditeur(@PathVariable Long id) {
return editeurService.recupererEditeur(id);
}
@PostMapping("")
@ResponseStatus(HttpStatus.CREATED)
@Operation(summary = "Ajoute un nouvel éditeur")
public Editeur postEditeur(@RequestBody Editeur editeur) {
return editeurService.ajouterEditeur(editeur);
}
// TODO comprendre comment les plateformes sur le findAll
@ExceptionHandler(EditeurInexistantException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ReponseApi<String> traiterEditeurInexistantException(EditeurInexistantException e){
//return e.getMessage();
return new ReponseApi<>(String.valueOf(HttpStatus.NOT_FOUND.value()), e.getMessage(), null);
}
}

View file

@ -0,0 +1,8 @@
package fr.clelia.avis.exception;
public class EditeurInexistantException extends RuntimeException {
public EditeurInexistantException(String message) {
super(message);
}
}

View file

@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List; import java.util.List;
@ -14,21 +15,20 @@ import java.util.Random;
@Component // Spring va instancier cette classe @Component // Spring va instancier cette classe
// et placer cette instance dans son conteneur IoC // et placer cette instance dans son conteneur IoC
//@AllArgsConstructor @AllArgsConstructor
public class AjoutDonneesInitiales { public class AjoutDonneesInitiales {
// Dépendances // Dépendances
@Autowired //@Autowired
private EditeurRepository editeurRepository; private EditeurRepository editeurRepository;
@Autowired //@Autowired
private PlateformeRepository plateformeRepository; private PlateformeRepository plateformeRepository;
@Autowired
private JeuRepository jeuRepository; private JeuRepository jeuRepository;
@Autowired
private JoueurRepository joueurRepository; private JoueurRepository joueurRepository;
@Autowired
private ModerateurRepository moderateurRepository; private ModerateurRepository moderateurRepository;
private UtilisateurRepository utilisateurRepository;
@Transactional
@EventListener(ApplicationReadyEvent.class) @EventListener(ApplicationReadyEvent.class)
public void init() { public void init() {
System.out.println("Ajout des données initiales"); System.out.println("Ajout des données initiales");
@ -36,17 +36,16 @@ public class AjoutDonneesInitiales {
ajouterPlateformes(); ajouterPlateformes();
ajouterJeux(); ajouterJeux();
ajouterJoueurs(); ajouterJoueurs();
ajouteurModerateur(); ajouterModerateur();
afficherStatistiques(); afficherStatistiques();
// afficherJeuxSurPlateforme("Steam"); //utilisateurRepository.deleteByMotDePasse("12345");
} }
private void afficherStatistiques() { private void afficherStatistiques() {
editeurRepository.findByLogoStartsWith("micro") editeurRepository.findByLogoStartsWith("micro")
.forEach(System.out::println); .forEach(System.out::println);
plateformeRepository.findByNomStartsWith("Nintendo") joueurRepository.findJoueursTrentenaires().forEach(System.out::println);
.forEach(System.out::println); jeuRepository.findJeuxByPlateforme(plateformeRepository.findAll().get(0)).forEach(System.out::println);
// editeurRepository.findEditeurWithoutJeux();
} }
private void ajouterEditeurs() { private void ajouterEditeurs() {
@ -140,6 +139,7 @@ public class AjoutDonneesInitiales {
.editeur(editeur) .editeur(editeur)
.plateformes(List.of(plateformes.get(0))) .plateformes(List.of(plateformes.get(0)))
.build(); .build();
jeuRepository.save(jeuAvecBuilder);
jeuRepository.save(new Jeu("Rocket League", editeurRepository.findByNom("Psyonix"), List.of(plateformeRepository.findByNom("Windows")))); jeuRepository.save(new Jeu("Rocket League", editeurRepository.findByNom("Psyonix"), List.of(plateformeRepository.findByNom("Windows"))));
@ -208,15 +208,7 @@ public class AjoutDonneesInitiales {
} }
private void ajouteurModerateur() { private void ajouterModerateur() {
moderateurRepository.save(new Moderateur("Fx", "Fx@soprasteria.com", "12345", "+33777777777")); moderateurRepository.save(new Moderateur("Fx", "Fx@soprasteria.com", "12345", "+33777777777"));
} }
private void afficherJeuxSurPlateforme(String nomPlateforme) {
List<Jeu> jeux = jeuRepository.findJeuxByPlateforme(nomPlateforme);
System.out.println("Jeux disponibles sur " + nomPlateforme + " :");
jeux.forEach(System.out::println);
}
} }

View file

@ -1,6 +1,7 @@
package fr.clelia.avis.repository; package fr.clelia.avis.repository;
import fr.clelia.avis.business.Editeur; import fr.clelia.avis.business.Editeur;
import lombok.NonNull;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
@ -8,9 +9,11 @@ import org.springframework.data.repository.query.Param;
import java.util.List; import java.util.List;
public interface EditeurRepository extends JpaRepository<Editeur, Long> { public interface EditeurRepository extends JpaRepository<Editeur, Long> {
// Méthode dérivée // Méthode dérivée (Spring Data nous permet de faire ces méthodes)
List<Editeur> findByNomContainingIgnoreCase(String nomRecherche); List<Editeur> findByNomContainingIgnoreCase(String nomRecherche);
// Hibernate va traduire cette requête dans le SQL
// correspondant à notre couche de persistence (H2 ds ce projet)
@Query(""" @Query("""
SELECT e SELECT e
FROM Editeur e FROM Editeur e
@ -19,14 +22,4 @@ public interface EditeurRepository extends JpaRepository<Editeur, Long> {
List<Editeur> findByLogoStartsWith(@Param("logo") String logo); List<Editeur> findByLogoStartsWith(@Param("logo") String logo);
Editeur findByNom(String nom); Editeur findByNom(String nom);
@Query("""
SELECT e
FROM Editeur e
LEFT JOIN e.jeux j
WHERE j IS NULL
""")
List<Editeur> findEditeurWithoutJeux();
Editeur findById(int id);
} }

View file

@ -1,12 +1,16 @@
package fr.clelia.avis.repository; package fr.clelia.avis.repository;
import fr.clelia.avis.business.Jeu; import fr.clelia.avis.business.Jeu;
import fr.clelia.avis.business.Plateforme;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List; import java.util.List;
public interface JeuRepository extends JpaRepository<Jeu, Long> { public interface JeuRepository extends JpaRepository<Jeu, Long> {
@Query( @Query(
""" """
SELECT j SELECT j
@ -14,5 +18,15 @@ public interface JeuRepository extends JpaRepository<Jeu, Long> {
WHERE :plateforme member Of j.plateformes WHERE :plateforme member Of j.plateformes
""" """
) )
List<Jeu> findJeuxByPlateforme(String plateforme); List<Jeu> findJeuxByPlateforme(Plateforme plateforme);
@Query("""
SELECT j
FROM Jeu j
JOIN j.plateformes p
WHERE p.nom = :nomPlateforme
""")
List<Jeu> findJeuxByNomPlateforme(@Param("nomPlateforme") String nomPlateforme);
List<Jeu> findByPlateformesNom(String nom);
} }

View file

@ -3,9 +3,25 @@ package fr.clelia.avis.repository;
import fr.clelia.avis.business.Joueur; import fr.clelia.avis.business.Joueur;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List; import java.util.List;
public interface JoueurRepository extends JpaRepository<Joueur, Long> { public interface JoueurRepository extends JpaRepository<Joueur, Long> {
@Query("""
FROM Joueur
WHERE
month(dateDeNaissance) = month(current_date())
AND day(dateDeNaissance) = day(current_date())
""")
List<Joueur> findJoueursAnniversaire();
@Query("""
SELECT j
FROM Joueur j
WHERE
j.dateDeNaissance <= current_date() - 30 year
AND j.dateDeNaissance > current_date() - 40 year
""")
List<Joueur> findJoueursTrentenaires();
} }

View file

@ -1,23 +1,8 @@
package fr.clelia.avis.repository; package fr.clelia.avis.repository;
import fr.clelia.avis.business.Editeur;
import fr.clelia.avis.business.Plateforme; import fr.clelia.avis.business.Plateforme;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface PlateformeRepository extends JpaRepository<Plateforme, Long> { public interface PlateformeRepository extends JpaRepository<Plateforme, Long> {
// Méthode dérivée Plateforme findByNom(String nintendoSwitch);
List<Plateforme> findByNomContainingIgnoreCase(String nomRecherche);
@Query("""
SELECT p
FROM Plateforme p
WHERE p.nom LIKE concat(:nom, '%')
""")
List<Plateforme> findByNomStartsWith(@Param("nom") String nom);
Plateforme findByNom(String nom);
} }

View file

@ -9,4 +9,8 @@ public interface EditeurService {
List<Editeur> recupererEditeurs(); List<Editeur> recupererEditeurs();
List<Editeur> recupererEditeursAyantUnNomContenant(String nomRecherche); List<Editeur> recupererEditeursAyantUnNomContenant(String nomRecherche);
Editeur recupererEditeur(Long id);
Editeur ajouterEditeur(Editeur editeur);
} }

View file

@ -1,17 +1,20 @@
package fr.clelia.avis.service.impl; package fr.clelia.avis.service.impl;
import fr.clelia.avis.business.Editeur; import fr.clelia.avis.business.Editeur;
import fr.clelia.avis.exception.EditeurInexistantException;
import fr.clelia.avis.repository.EditeurRepository; import fr.clelia.avis.repository.EditeurRepository;
import fr.clelia.avis.service.EditeurService; import fr.clelia.avis.service.EditeurService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
//@Component //@Component
@Service @Service
@Transactional
public class EditeurServiceImpl implements EditeurService { public class EditeurServiceImpl implements EditeurService {
private final EditeurRepository editeurRepository; private EditeurRepository editeurRepository;
// Ce constructeur va faire déduire à Spring // Ce constructeur va faire déduire à Spring
// qu'il doit d'abord instancier la repo // qu'il doit d'abord instancier la repo
@ -29,4 +32,15 @@ public class EditeurServiceImpl implements EditeurService {
public List<Editeur> recupererEditeursAyantUnNomContenant(String nomRecherche) { public List<Editeur> recupererEditeursAyantUnNomContenant(String nomRecherche) {
return editeurRepository.findByNomContainingIgnoreCase(nomRecherche); return editeurRepository.findByNomContainingIgnoreCase(nomRecherche);
} }
@Override
public Editeur recupererEditeur(Long id) {
// C'est un des rôles du service de lever des exceptions maison
return editeurRepository.findById(id).orElseThrow(() -> new EditeurInexistantException("L'éditeur ayant l'id " + id + " n'existe pas"));
}
@Override
public Editeur ajouterEditeur(Editeur editeur) {
return editeurRepository.save(editeur);
}
} }

View file

@ -0,0 +1,20 @@
package fr.clelia.avis.util;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
public class ReponseApi<T> {
private String statut;
@JsonInclude(Include.NON_NULL)
private String message;
@JsonInclude(Include.NON_NULL)
private T t;
}