IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JPA Java Discussion :

Association et objets inclus


Sujet :

JPA Java

  1. #1
    Membre actif
    Homme Profil pro
    Reconversion
    Inscrit en
    novembre 2018
    Messages
    383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Reconversion
    Secteur : Santé

    Informations forums :
    Inscription : novembre 2018
    Messages : 383
    Points : 222
    Points
    222
    Par défaut Association et objets inclus
    Bonjour,

    Débutant en spécification JPA, je cherche à comprendre le mécanisme des objets inclus et des associations entre entités. Je suis entrain de suivre un tutoriel qui permet de réaliser une application de bibliothèque.
    Il est dit dans le tuto ceci concernant la règle de fonctionnement des emprunts de livres :

    "un Client peut effectuer un prêt de plusieurs Livres ; et comme un Livre a plusieurs exemplaires, il peut être emprunté par plusieurs Clients.
    Chaque prêt ayant une date de début et de fin à prendre en compte, on se retrouve dans une association porteuse de propriétés. "

    Voici un modèle UML à ma façon :

    Nom : Screenshot from 2020-07-17 14-21-29.png
Affichages : 88
Taille : 43,8 Ko

    Une chose m'échappe dans ce schéma : est-ce qu'il faut comprendre qu'un prêt appartient à un seul livre ? Du coup ça devient contradictoire avec l'énoncé, non ?

    Enfin une dernière question sur l'endroit où placer les annotations d'association : je vois dans certains exemples qu'elles sont tantôt au dessus des getters ou au-dessus des propriétés. Quelle est la différence ?

    Merci beaucoup.

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    janvier 2009
    Messages
    181
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : janvier 2009
    Messages : 181
    Points : 307
    Points
    307
    Par défaut
    Plusieurs questions dans ce post.

    Pour la première (la classe prêt), tu as ce que l'on appelle (en UML) une classe d'association. Dans la base de données, cela se caractérisera par une table ayant une clé primaire sur deux id, chaque id étant une clé étrangère sur une des table (1 pour livre, l'autre pour client).

    D'ailleurs, je recommande plutôt @EmbeddedId (Meilleur lien trouvé: https://blog.axopen.com/2013/11/les-...c-hibernate-4/ ).

    Seconde question: Où mettre les annotations JPA?

    Le mettre sur les méthodes ou les attributs, dans les 2 cas c'est correct. D'ailleurs, JBoss recommande, il me semble les méthodes. Spring, dans mes souvenir, recommandait les attributs.

    En ce qui me concerne, je recommande les attributs. C'est un avis personnel.
    Je trouve ça plus lisible et on sait d’emblée que l'attribut correspond à un champ dans la BDD, ce qui évite de rechercher le setter.

  3. #3
    Membre actif
    Homme Profil pro
    Reconversion
    Inscrit en
    novembre 2018
    Messages
    383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Reconversion
    Secteur : Santé

    Informations forums :
    Inscription : novembre 2018
    Messages : 383
    Points : 222
    Points
    222
    Par défaut
    Bonjour et merci pour votre réponse,

    Du coup pur le modèle merisien, cela donnerait quelque chose comme ceci ?

    Nom : Screenshot from 2020-07-24 09-13-48.png
Affichages : 62
Taille : 20,0 Ko

    Merci

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    janvier 2009
    Messages
    181
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : janvier 2009
    Messages : 181
    Points : 307
    Points
    307
    Par défaut
    Non, il n'y a pas de clé étrangère dans livre (fk_id_pret) et client (fk_id_pret).

    De plus, en parlant Merise, on a un MCD ou un MCD?
    Le schéma ne correspond à rien.

    Pour être plus précis, il y a deux possibilités.
    1. Le client m’emprunte qu'une seule fois le livre. Dans ce cas, on a une double clé primaire (id_livre, id_client) qui sont des clés étrangères (sur id_livre de la table livre et id_client sur la table client).
    2. Le client emprunte le livre plusieurs fois. Dans ce cas, on a un id unique dans la table pret, et une clé étrangère dans la table livre (fk_livre) et une clé étrangère dans la table client (fk_client).

    Notez que j'ai différentié la clé primaire (id) de la clé étrangère (fk).

    Notez aussi que pour utiliser JPA/Hibernate à bon escient, il faut de bonnes connaissances de la BDD relationnelle ainsi que de ce que l'on appellera la théori des ORM (JPA est un ORM).

    C'est là où réside la difficulté de JPA/Hibernate.

  5. #5
    Membre actif
    Homme Profil pro
    Reconversion
    Inscrit en
    novembre 2018
    Messages
    383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Reconversion
    Secteur : Santé

    Informations forums :
    Inscription : novembre 2018
    Messages : 383
    Points : 222
    Points
    222
    Par défaut
    Merci encore,

    du coup j'ai distingué le MCD du MLD selon vos explications pour essayer d'être plus rigoureux même si j'ai du mal à comprendre les 2 possibilités d'emprunt d'un livre une seule fois ou plusieurs fois.
    D'ailleurs comment est-il possible d'avoir une clé étrangère livre dans la table livre et idem pour client ?

    Voici ce que donne mon MLD, je crée une clé primaire composée de l'id de la table livre et client. Cela répond au fait que :
    - 1 livre (qui existe en plusieurs exemplaires) peut-être emprunté au moins une fois
    - 1 prêt est composé d'au moins 1 livre
    - 1 prêt concerne un client
    - 1 prêt concerne un livre

    Nom : Screenshot from 2020-07-24 16-55-34.png
Affichages : 60
Taille : 33,5 Ko

  6. #6
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    novembre 2006
    Messages
    7 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : novembre 2006
    Messages : 7 183
    Points : 9 306
    Points
    9 306
    Billets dans le blog
    1
    Par défaut
    Pour répondre à ton problème de compréhension...
    Un prêt concerne 1 instance de livre et 1 instance de client.
    Un client peut emprunter plusieurs fois la même référence de livre vu qu'il existe plusieurs mêmes livres au sens d'une référence littéraire (ils auront chacun leur propre clé primaire, ce ne sont pas les mêmes instances).
    Ce serait le cas d'une personne empruntant pour une autre bibliothèque (avoir une seule fois un livre à succès risque d'étaler un peu trop les emprunts des consommateurs, d'où l'intérêt d'en avoir plusieurs identiques).

    Sinon, personnellement, je préfère les annotations sur les getter, ça évite de surcharger les propriétés de l'entity (ce que PhilippeGibault voit comme un avantage me paraît un inconvénient, mais comme il l'a dit, les 2 fonctionnent, c'est surtout une question de feeling ).
    Par contre, il faut savoir qu'il y a une différence à l'exécution. Avec un AccessType PROPERTY (le défaut et recommandé), le chargement/mise à jour se fait via les getter/setter. En utilisant AccesType FIELD, l'opération se fait directement par les champs.

    Enfin, personnellement toujours, je ne conseille pas de mettre les Set liés à la table de relation dans les entités Livre et Client, ça n'a pas d'intérêt du point de vue persistance et presque aucun intérêt du point de vue requête pour l'IHM.
    Ça risque juste de ralentir les accès à un livre ou un client (sauf à mettre un FetchType LAZY).

    Je préconise toujours de voir le modèle entity d'un point de vue "gestion" des tables et non du point de vue d'une fonctionnalité IHM (rechercher les livres empruntés par un client etc...).
    Si on recherche les livres empruntés par un client pour une plage de dates données, il est beaucoup plus judicieux de faire un Query sur la table de relation, laquelle devrait avoir des relations ManyToOne vers les entités Livre et Client.
    Du coup, via les instruction join fetch, on peut charger les informations liées dans la requête JPQL (select a from Pret a join fetch a.livre where ...)
    L'autre intérêt de ce mapping serait de persister via l'entity Pret un livre et/ou un client inexistant (voir l'attribut cascade sur la relation ManyToOne) au moment de la demande (même si ça n'a pas forcément un intérêt dans ton cas, il faut savoir que c'est possible).
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre actif
    Homme Profil pro
    Reconversion
    Inscrit en
    novembre 2018
    Messages
    383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Reconversion
    Secteur : Santé

    Informations forums :
    Inscription : novembre 2018
    Messages : 383
    Points : 222
    Points
    222
    Par défaut
    Bonjour,

    Merci encore, du coup peut-on dire que chaque clé étrangère côté modèle relationnel correspond à une instance côté objet. Il y a autant d'instances que d'occurences des entités mises en relation avec la table d'association ?
    Pour être plus clair : si plusieurs livres sont souscrits dans un même prêt, il y a autant d'instances de livres qui sont persistées en BDD ?

    - Ok pour les set<>, je croyais que c'était obligatoire, mais tu m'en avais parlé dans un autre post
    - Est-ce que vous auriez une référence pour m'initier à la modélisation. Je sais qu'il y a bcp de tutos mais j'aimerais trouver un ouvrage de référence qui soit en même temps accessible pour les débutants

    Merci à tous les 2, bonne semaine

  8. #8
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    novembre 2006
    Messages
    7 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : novembre 2006
    Messages : 7 183
    Points : 9 306
    Points
    9 306
    Billets dans le blog
    1
    Par défaut
    Non, tu raisonnes au niveau "humain", un prêt de plusieurs choses...

    Là, informatiquement parlant, un prêt représente une association entre un client et un livre.
    Si le même jour le client emprunte plusieurs livres, il y aura autant d'enregistrements dans la table Pret que de livres empruntés, le point commun à tous ces enregistrements étant l'id du client, associé chaque fois à un autre id de livre (sachant qu'il y a plusieurs instances d'une même référence de livre possibles).

    Pour la référence à une documentation pour s'initier à la modélisation, je n'en connais pas spécialement, sa date un peu pour moi
    Mais tu peux trouver pas mal d'informations sur le MCD de Merise sur le net.
    La seule chose que je te conseille, c'est de partir systématiquement sur des clés primaires non significatives (id auto-généré), la seule chose qu'on demande à une clé primaire étant d'identifier un et un seul enregistrement d'une table de base de données.
    Ça n'empêche pas d'avoir des méthodes de recherches par clé logique et d'utiliser un query pour trouver l'enregistrement correspondant, par contre, ça simplifie grandement les relations entre tables.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Membre actif
    Homme Profil pro
    Reconversion
    Inscrit en
    novembre 2018
    Messages
    383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Reconversion
    Secteur : Santé

    Informations forums :
    Inscription : novembre 2018
    Messages : 383
    Points : 222
    Points
    222
    Par défaut
    Merci beaucoup pour tes explications (et ta patience...)

    C'est là que je bloquais :
    informatiquement parlant, un prêt représente une association entre un client et un livre
    Je pensais que le prêt pouvait contenir une collection de livre. Je vais m'exercer sur d'autres exemples.

    Merci encore, je dois bcp à ce forum et ses intervenants

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    janvier 2009
    Messages
    181
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : janvier 2009
    Messages : 181
    Points : 307
    Points
    307
    Par défaut
    Nom : developpez_r.jpeg
Affichages : 57
Taille : 1 008,5 Ko

    Je pense qu'il y a beaucoup de lacunes, que se soit sur la BDD relationnelle, Merise, UML ou ce que l'on appelle "La théorie des ORM", Hibernate/JPA étant un ORM.

    J'ai fait (rapidement) l'ensemble des Merise/UML.

    Déjà, partons du principe qu'un livre peut-être emprunté plusieurs fois par un client.

    Le MCD change donc radicalement.
    Notez qu'ici on a des clés technique. Alors qu'en toute rigueur, on devrait avoir des clés fonctionnelles (ISBN pour un livre, numéro client pour le client, numéro de prêt...).

    Le MCP devient plus facile, et laisse apparaître un id unique(id_pret) qui correspond à l'id de la table prêt (qui n'est pas une table de jointure, mais d'association).
    De fait, le couple (fk_client,fk_livre) n'est pas unique, il peut-être présent pour plusieurs id_pret, ce qui correspond à une personne qui emprunte encore le même livre.

    Je donne aussi la version UML.

    Dans ce cas là, effectivement, on a 1 classe qui correspond à une table. Ce n'est pas forcement vrai (cas de l'héritage, par exemple).

    En ce qui me concerne, j'ai l'habitude de mapper au mieux la BDD, et d'enlever ce qui est inutile sur la couche supérieure (DTO et service).
    Je fais donc un mapping dans les 2 sens. Mais là, c'est personnel.

    On a donc pour la classe Livre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    @Entity
    @Table(name="livre")
    public class Livre{
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name="id_livre")
        private Integer idLivre;
     
        @Column(name="titre")
        private String titre;
     
        @Column(name="auteur")
        private String auteur;
     
        @OneToMany(mappedBy="livre",fetch = FetchType.LAZY)
        private Set<Pret> prets;
    //Getter Setter
    }
    Pour la classe Pret, on a simplement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    @Entity
    @Table(name="pret")
    public class Pret{
     
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name="id_pret")
        private Integer idLivre;
     
        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name="fk_livre")
        private Livre livre;
     
        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name="fk_client")
        private Client client;
     
        @Column(name="date_debut")
        @Temporal(TemporalType.DATE)//On a une date simple, sans l'heure
        private Date dateDebut
     
        @Column(name="date_fin")
        @Temporal(TemporalType.DATE)//On a une date simple, sans l'heure
        private Date dateFin
    //Getter Setter
    }
    Et enfin pour Client:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    @Entity
    @Table(name="client")
    public class Client{
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name="id_client")
        private Integer idClient;
     
        @Column(name="nom")
        private String nom;
     
        @Column(name="prenom")
        private String prenom;
     
        @OneToMany(mappedBy="client",fetch = FetchType.LAZY)
        private Set<Pret> prets;
    //Getter Setter
    Notez , sur un autre sujet, que j'ai défini les stratégie de chargement (je charge tout ce qui est lié Eager/Je ne charge pas Lazy).

    Pour la modélisation UML, je recommande le livre de Laurent Audibert qui d'ailleurs est sur Developpez:
    https://laurent-audibert.developpez.com/Cours-UML/

    Laurent Audibert a aussi un cours de BDD qui aborde (de très bonne façon d'ailleurs) la modélisation Merise:
    https://laurent-audibert.developpez.com/Cours-BD/

    Il y a le livre de Jean Luc Hainaut qui est très bien aussi, et celui de Gardarin, même si il est vieux.

    Côté JPA/ORM, le livre de référence est celui de Anthony Patricio (Java Persistence et Hibernate).
    Il commence à dater, mais sur l'aspect théorique, il est encore bon.

    Il y a aussi Doudoux:
    https://jmdoudoux.developpez.com/cou...ap-jpa.php#jpa

  11. #11
    Membre actif
    Homme Profil pro
    Reconversion
    Inscrit en
    novembre 2018
    Messages
    383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Reconversion
    Secteur : Santé

    Informations forums :
    Inscription : novembre 2018
    Messages : 383
    Points : 222
    Points
    222
    Par défaut
    Bonjour,

    Je n'avais pas pris le temps de vous remercier...Tous mes remerciements pour cette réponse très complète.
    J'ai entrepris le cours de Laurent Audibert sur la modélisation et j'enchainerai sur l'uml.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 29/10/2008, 11h03
  2. Réponses: 6
    Dernier message: 09/04/2008, 09h57
  3. Treeview: associé un objet à chaque Item ?
    Par TSalm dans le forum Framework .NET
    Réponses: 2
    Dernier message: 29/10/2007, 16h57
  4. Association entre objet Id ou référence ?
    Par grosFab dans le forum Langages de programmation
    Réponses: 1
    Dernier message: 19/04/2007, 13h41
  5. [JNI] : Obtenir les champs d'un objet inclus dans un objet
    Par jojo29 dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 27/04/2006, 13h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo