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 :

Création d'une classe "custom" pour les collections d'entités (JPA-EJB-Glassfish)


Sujet :

JPA Java

  1. #1
    Membre habitué Avatar de touftouf57
    Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2007
    Messages : 362
    Points : 174
    Points
    174
    Par défaut Création d'une classe "custom" pour les collections d'entités (JPA-EJB-Glassfish)
    Bonjour,

    Je cherche à faire une classe héritant de HashSet, (et donc un interface héritant de Set), pour mes entités.

    (Précision j'utilise JPA pour la persistence, et l'application est déployée sur un serveur glassfish.)

    Je m'explique j'ai comme classes:
    • Client
    • Contact (extends Personne)
    • ChargeAaffaire (extends Personne)


    Ces classes ont une propriété:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private Set<Affaire> affaires;
    Or la classe Affaire est une classe Mère.
    OffrePrix et Commande héritent de Affaire.
    Expertise hérite de OffrePrix.

    J'ai donc tous les types d'affaire dans ma propriété affaires, ce qui est voulu pour le moment.

    Maintenant j'aimerais pouvoir limiter les résultats selon certains critères:
    OffresEnCours, OffresDeclinee, OffresPasseEnCommande, OffresASuivre, CommandesEnCours, CommandeLivrees....

    J'ai donc créé Une classe Affaires qui hérite de HashSet et dans laquelle je défini les différents getters:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Affaires extends HashSet<Affaire>{
     
    public Set<Affaire> getAffaireEnCours(){}
    public Set<Commande> getCommandeEnCours(){}
    public Set<Expertise> getExpertiseEnCours(){}
    public Set<OffrePrix> getOffrePrixEnCours(){}
    public Set<OffrePrix> getOffrePrixDeclinee(){}
    public Set<OffrePrix> getOffresEnCommande(){}
    public Set<OffrePrix> getOffresASuivre(){}
    Ceci dans l'objectif de pouvoir obtenir ces affaires "filtrées" dans ma page jsf par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <h:dataTable value="#{clientMB.client.offreEnCours}"....
    J'ai essayé et cela ne veut pas se déployer. J'obtiens cette erreur durant le déployement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Exception Description: The target entity of the relationship attribute [affaires] on the class [class com.enregistrementAffaires.entites.ChargeAffaire] cannot be determined.  When not using generics, ensure the target entity is defined on the relationship mapping.
    Si je comprend bien, c'est parce que dans la classe ChargeAffaire, la propriété qui contient la collection n'est pas générique, et donc qu'il ne sait pas faire le "mappedBy = "chargeAffaire"" sur ma classe Affaires. Exact?
    Donc comment puis-je y remédier?

    Et sinon que me conseillerez-vous de faire pour pouvoir obtenir/extraire les différents types d'affaire(Design Pattern, architecture,....)? Ou bien cela ne doit pas du tout être fait de cette façon mais plutôt de définir les Query dans mon stateless Bean? Je suis ouvert à toutes solutions intéressantes.

    Merci beaucoup

  2. #2
    Membre habitué Avatar de touftouf57
    Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2007
    Messages : 362
    Points : 174
    Points
    174
    Par défaut
    Bonjour, bonsoir

    Bon j'ai cherché de mon coté, et j'ai peut-être une piste:
    IndirectContainer et ValueHolderInterface du package org.eclipse.persistence.indirection

    Mais je ne pige pas du tout comment l'implémenter

    Quelqu'un aurait-il une explication simple?

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Ton problème de base doit être lié au mapping, il faudrait le montrer.

    Dans l'absolut, je trouve la solution plutôt mauvaise (mais ce n'est que mon avis).
    J'arriverais encore à comprendre une classe étendant Set avec des getters spécialisés, dans le genre
    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
     
    public class Affaires extends HashSet implements Set
    {
       public Set<Affaire> getAffairesEnCours()
       {
          Set<Affaire> values = new HashSet();
          Iterator it = iterator();
          while (it.hasNext())
          {
             Affaire affaire = it.next();
             if (affaire.isEnCours()) values.add(affaire);
          }
          return values;
       }
    }
    (et encore, ce n'est pas super performant)
    Mais plusieurs Set dans l'objet, bof... il faut à chaque ajout/suppression mettre à jour 2 Set...

    Ceci dit, ce n'est pas le rôle de l'entité de faire ça mais plutôt de la DAO (ou de l'EJB)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre habitué Avatar de touftouf57
    Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2007
    Messages : 362
    Points : 174
    Points
    174
    Par défaut
    Merci OButterlin!

    Je n'ai pas été informé que tu avais posté, c'est pourquoi je réagit si tard.

    Donc selon toi je devrait plutôt faire ça dans la couche DAO (EJB) et donc de faire une méthode du type:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public Set<OffrePrix> getOffresEnCours(ChargeAffaire chargeAffaire)
    Et donc de définir les requêtes EL dans l'entité.

    Sur le sujet suivant:
    J'arriverais encore à comprendre une classe étendant Set avec des getters spécialisés, dans le genre
    Code :


    public class Affaires extends HashSet implements Set
    {
    public Set<Affaire> getAffairesEnCours()
    {
    Set<Affaire> values = new HashSet();
    Iterator it = iterator();
    while (it.hasNext())
    {
    Affaire affaire = it.next();
    if (affaire.isEnCours()) values.add(affaire);
    }
    return values;
    }
    }


    (et encore, ce n'est pas super performant)
    J'étais justement parti la dessus, mais je me faisait bouler lors du déploiement. C'était d'ailleurs à ce moment que j'obtenais un message disant que JPA ne supportais que les List, Set, Map et Collection et qu'il fallait définir un IndirectContainer ainsi qu'un ValueHolderInterface.
    Je comprend bien pourquoi, car comment JPA sait-il qu'il faut instancier Affaires au lieu de Set<Affaire>?

    Tu me demandes le mapping, mais tout est définit dans les classes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public abstract class Affaire implements Serializable{....
    @JoinColumn(name = "IdChargeAffaire")
        @ManyToOne
        protected ChargeAffaire chargeAffaire;
    ...}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public class ChargeAffaire extends Personne implements Serializable {
    ....
        @OneToMany(mappedBy = "chargeAffaire")
        private Set<Affaire> affaires;
    ...}
    J'avais juste remplacé le private Set<Affaire> par Affaires.

    Te faut-il autre chose ou bien est-il possible de définir un mapping ailleurs (fichier XML) avec EclipseLink (JPA2.0)?

    En tout cas merci de m'avoir donné ton avis. Donc, selon toi, il vaut mieux faire ça dans la couche DAO.

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    En ce qui me concerne, je ferais ceci :

    - je mettrais un seul Set<Affaire> dans l'objet Entité parce que de ce point de vue, on référence les Affaires liées à l'élément en cours (côté relationnel)

    - j'utiliserais un filtre pour limiter la portée

    Regarde cet exemple, peut-être que tu y trouveras un intérêt
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
     
    <html>
    <%@page contentType="text/html; charset=ISO-8859-1" %>
    <%@page import="java.util.List"%>
    <%@page import="java.util.ArrayList"%> 
    <%@page import="org.apache.commons.collections.CollectionUtils"%>
    <%@page import="org.apache.commons.collections.Predicate"%>
    <%!
    public class Utilisateur
    {
        private String uid;
        private String nom;
        private String role;
        public Utilisateur(String uid, String nom, String role)
        {
            super();
            this.uid = uid;
            this.nom = nom;
            this.role = role;
        }
        public String getUid()
        {
            return uid;
        }
        public void setUid(String uid)
        {
            this.uid = uid;
        }
        public String getNom()
        {
            return nom;
        }
        public void setNom(String nom)
        {
            this.nom = nom;
        }
        public String getRole()
        {
            return role;
        }
        public void setRole(String role)
        {
            this.role = role;
        }
    }
    %>
     
    <%
    List<Utilisateur> list = new ArrayList<Utilisateur>();
    list.add(new Utilisateur("OB", "Olivier BUTTERLIN", "Administrateur"));
    list.add(new Utilisateur("WS", "Stephane WETTER", "Utilisateur"));
    list.add(new Utilisateur("SC", "Stéphane COHEN", "Administrateur"));
    list.add(new Utilisateur("DT", "Dominique TSCHIRHART", "Utilisateur"));
    list.add(new Utilisateur("JW", "Jacques WEBER", "Installateur"));
    list.add(new Utilisateur("AM", "Albert MEYER", "Contrôleur"));
    %>
     
    <table border=1>
    <%
    List<Utilisateur> wlist = new ArrayList<Utilisateur>();
    Predicate p1 = new Predicate(){
        public boolean evaluate(Object o)
        {
            if (o instanceof Utilisateur && ((Utilisateur)o).getRole().equals("Administrateur")) return true;
            return false;
        }
    };
    Predicate p2 = new Predicate(){
        public boolean evaluate(Object o)
        {
            if (o instanceof Utilisateur && ((Utilisateur)o).getRole().equals("Utilisateur")) return true;
            return false;
        }
    };
     
     
    out.println("<tr><td colspan=3 style='background:#f0f0f0'>Administrateurs : </td></tr>");
    CollectionUtils.select(list, p1, wlist);
    for (Utilisateur utilisateur : wlist)
    {
        out.println("<tr><td>" + utilisateur.getUid() + "</td><td>" + utilisateur.getNom() + "</td><td>" + utilisateur.getRole() + "</td></tr>");
    }
     
     
    out.println("<tr><td colspan=3 style='background:#f0f0f0'>Utilisateurs : </td></tr>");
    wlist.clear();
    CollectionUtils.select(list, p2, wlist);
    for (Utilisateur utilisateur : wlist)
    {
        out.println("<tr><td>" + utilisateur.getUid() + "</td><td>" + utilisateur.getNom() + "</td><td>" + utilisateur.getRole() + "</td></tr>");
    }
     
    %>
     
    </table>
     
    </html>
    Si le volume des données est important, je ne lierais pas le Set<Affaire> à l'entité mais j'utiliserais des méthodes spécialisées dans ma DAO pour extraire les listes d'affaires en fonction des critères voulus.
    Dans ce cas, il faut prévoir les objets List ou Set dans le managedBean.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

Discussions similaires

  1. Réponses: 6
    Dernier message: 20/12/2017, 13h04
  2. création d'une classe pour une table
    Par asma07 dans le forum C#
    Réponses: 3
    Dernier message: 19/10/2009, 17h00
  3. Réponses: 0
    Dernier message: 12/08/2008, 17h12

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