3 - ENTITE VIN : CLE PRIMAIRE COMPOSITE avec @IdClass (pinard03)
Création du projet pinard03
Pour ce projet, j’ai utilisé Lombok dont voici le lien pour découvrir comment l’installer pour Eclipse :
https://projectlombok.org/setup/eclipse
Vous pourrez l’ajouter à vos dépendances Gradle ou Maven et ajouter les annoatations suivantes pour la classe Vin.java :
@Entity
@IdClass(VinPK.class)
@Getter
@Setter
@NoArgsConstructor
@EqualsAndHashCode
@ToString
public class Vin implements Serializable {
J’ai aussi utilisé un type enum pour le choix des couleurs du vin :
public enum choix {ROUGE,BLANC,ROSE};
@Enumerated(value = EnumType.STRING)
@Column(length = 5)
private choix couleur;
- Copier le contenu du projet pinard01
Objectif : Créer une entité Vin avec une clef composite, c’est-à-dire une clef composée du codeProduit et de la designation.
- Utiliser l’annotation @IdClass sur l’entité Vin
-
Cette clé primaire sera composée du produit et de la designation
- Modifier la classe Vin :
- Il faut rajouter l’annotation @IdClass sur la classe Vin :
@Entity
@IdClass(VinPK.class)
public class Vin implements Serializable {
}
Il faut l’annotation @Id devant le champ codeProduit ou la méthode getCodeProduit() :
@Id
public Integer getCodeProduit() {
return this.codeProduit;
}
ainsi que devant le champ designation ou la méthode getDesignation() :
@Id
public String getDesignation() {
return designation;
}
- Créer la classe VinPK qui va contenir les 2 attributs qui composent la clef composite
Dans le package fr.apprenant.model
, créer ensuite la classe VinPK qui comportera les attributs suivants :
public class VinPK implements Serializable {
private Integer codeProduit;
private String designation;
- ajouter les getters et setters pour ces attributs ainsi que les méthodes equals() et hashCode().
- modifier la signature du Repository (car nouvelle clé primaire composée)
Remarque : Si vous le faites seul(e), il faut penser à faire passer une clef de type VinPk et non plus seulement le codeProduit pour détruire ou mettre à jour une quantité dans le contrôleur. Voici un bout de code pour vous mettre sur la voie avec l’instanciation d’un Vin v1 dans le contrôleur :
Vin v4=new Vin();
v4.setCodeProduit(111111);
v4.setDesignation("Clos du Baron 1998");
v4.setRegion("Bordeaux (Saint-Julien)");
v4.setCouleur(choix.BLANC);
v4.setPrix(45.20);
v4.setRemise(0);
v4.setQuantite(50);
updateQuantite(new VinPK(v4.getCodeProduit(),v4.getDesignation()),40);
/**
* Met à jour la quantité d'un objet de type Vin
*/
public void updateQuantite(VinPK vinPk, int quantite)
{
(vinRepository.getOne(vinPk)).setQuantite(quantite);
}
- Lancez l’application SpringBoot et testez sur le
localhost:8080
Pour avoir un code respectant la notion de composant, vous pourriez réécrire ce contrôleur en créant une classe VinService pour y intégrer toutes les méthodes métiers et ainsi ne pas avoir autant de code dans la méthode String home()
. Vous pourriez aussi remplir la table Vin avec un fichier data.sql
dans le répertoire resources
, à vous de faire les modifications (même si le code fonctionne) :
@GetMapping("/")
@ResponseBody
public String home(){
Vin v1=new Vin();
v1.setCodeProduit(777777);
v1.setDesignation("Les Hauts du Tertre 1999");
v1.setRegion("Bordeaux (Margaux)");
v1.setCouleur(choix.ROUGE);
v1.setPrix(11.50);
v1.setRemise(0);
v1.setQuantite(2);
Vin v2=new Vin();
v2.setCodeProduit(888888);
v2.setDesignation("Château Marquis de Terme 1998");
v2.setRegion("Bordeaux (Margaux)");
v2.setCouleur(choix.BLANC);
v2.setPrix(19.00);
v2.setRemise(0);
v2.setQuantite(3);
Vin v3=new Vin();
v3.setCodeProduit(999999);
v3.setDesignation("Clos du Marquis 1999");
v3.setRegion("Bordeaux (Saint-Julien)");
v3.setCouleur(choix.ROUGE);
v3.setPrix(22.90);
v3.setRemise(0);
v3.setQuantite(15);
Vin v4=new Vin();
v4.setCodeProduit(111111);
v4.setDesignation("Clos du Baron 1998");
v4.setRegion("Bordeaux (Saint-Julien)");
v4.setCouleur(choix.BLANC);
v4.setPrix(45.20);
v4.setRemise(0);
v4.setQuantite(50);
System.out.println("ajout du produit v1 : "+v1);
ajoutVin(v1);
System.out.println("ajout du produit v2 : "+v2);
ajoutVin(v2);
System.out.println("ajout du produit v3 : "+v3);
v3=ajoutVin(v3);
v3.setQuantite(10);
updateVin(v3);
System.out.println("ajout du produit v4 : "+v4);
v4=ajoutVin(v4);
updateQuantite(new VinPK(v4.getCodeProduit(),v4.getDesignation()),40);
StringBuilder sb = new StringBuilder();
sb.append("<h1>Regardez dans votre console et dans votre base de données MySQL <strong>JPA</strong></h1>");
sb.append("<a href='http://localhost:8080/vins'>Voir la liste des vins enregistrés</a>");
return sb.toString();
}
public Optional<Vin> findById(VinPK vinPk){
return vinRepository.findById(vinPk);
}
/**
* Retourne tous les produits dans une liste
*/
@GetMapping("/vins")
public Collection<Vin> findAll(){
return vinRepository.findAll();
}
/**
* Ajoute un vin
*/
public Vin ajoutVin(Vin vin){
return vinRepository.saveAndFlush(vin);
}
/**
* Met un jour un enregistrement pour un objet Vin
*/
public Vin updateVin(Vin vin){
return vinRepository.saveAndFlush(vin);
}
/**
* Met à jour la quantité d'un objet de type Vin
*/
public void updateQuantite(VinPK vinPk, int quantite){
(vinRepository.getOne(vinPk)).setQuantite(quantite);
}
- Voici ce que vous devez obtenir comme structure pour la table Vin :
CREATE TABLE IF NOT EXISTS `vin` (
`code_produit` int(11) NOT NULL,
`designation` varchar(50) NOT NULL,
`couleur` varchar(5) DEFAULT NULL,
`prix` double NOT NULL,
`quantite` int(11) NOT NULL,
`region` varchar(45) DEFAULT NULL,
`remise` double NOT NULL,
PRIMARY KEY (`code_produit`,`designation`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;