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

Java EE Discussion :

JEE - Récupérer des entités "légères"


Sujet :

Java EE

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2011
    Messages : 43
    Points : 18
    Points
    18
    Par défaut JEE - Récupérer des entités "légères"
    Bonjour,

    Voilà mon souci. Je fais de l'auto complétion sur un de mes formulaires, et je vais chercher en base une liste d'objets Personne. Le problème c'est que cet objet a des jointures en base (et donc des attributs en java), mais je ne souhaite récupérer que l'objet Java simple, sans certains attributs (Role, Nationnalité) car cela consomme des ressources lors de la récupération et j'ai pas besoin de ces attributs.

    Voici un extrait de ma classe (les annotations sont sur les getters) :

    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 = "MDA_PERSONNE")
    public class Person extends AbstractIdentifiable {
     
    	private static final long serialVersionUID = 7782496106619218553L;
     
    	public enum SexType {
    		masculin, feminin
    	};
     
    	private Long id;
    	private boolean valid;
    	private String firstName;
    	private String name;
    	private String maidenName;
    	private SexType sex;
    	private Date dateOfBirth;
    	private String tel;
    	private String mail;
    	private String web;
     
    	private Nationality nationality;
    	private User user;
     
    	private Set<PersonRoleJoin> personRoleJoins;
     
    	private List<Role> roles = new ArrayList<Role>();
    Quelqu'un aurait une solution à me proposer ?

    Merci.

  2. #2
    Modérateur
    Avatar de paissad
    Homme Profil pro
    Ingénieur de développement (Java/JEE/Eclipse RCP,EMF & webMethods)
    Inscrit en
    Avril 2006
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur de développement (Java/JEE/Eclipse RCP,EMF & webMethods)
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 043
    Points : 2 560
    Points
    2 560
    Par défaut
    Bonjour,
    d'abord, tu devrais quand même montrer tes relations histoire qu'on voit ce qu'il y a ^^
    Ensuite, dans tes relations, es-tu en LAZY loading au lieu de EAGER ?

    Cordialement
    Nous n'héritons pas de la terre de nos parents, nous l'empruntons à nos enfants.
    Le chat du site est aussi ici pour aider. Ne pas hésiter à visiter !

  3. #3
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2011
    Messages : 43
    Points : 18
    Points
    18
    Par défaut
    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
    @OneToOne(mappedBy = "person")
    	public User getUser() {
    		return user;
    	}
     
    	public void setUser(User user) {
    		this.user = user;
    	}
     
    	@OneToOne
    	@JoinColumn(name = "NATNUM", referencedColumnName = "NATNUM", nullable = false)
    	public Nationality getNationality() {
    		return nationality;
    	}
     
    	public void setNationality(Nationality nationality) {
    		this.nationality = nationality;
    	}
     
    	@OneToMany(mappedBy = "person", fetch = FetchType.EAGER)
    	public Set<PersonRoleJoin> getPersonRoleJoins() {
    		return personRoleJoins;
    	}
    Voilà l'aperçu, je suis en mode "EAGER" mais en "Lazy" j'avais pas mal de soucis (des exceptions sur ma collection), et surtout y a defois où j'ai besoin de ma personne en mode EAGER.

    En gros :

    => Comment récupérer une entité sans ses objets en relations ?

  4. #4
    Membre régulier
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2009
    Messages
    169
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Octobre 2009
    Messages : 169
    Points : 100
    Points
    100
    Par défaut
    Pour se faire, tu n'as pas vraiment le choix, il faut passer les liaisons en LAZY, et charger les relations lorsque tu en as besoin en explicitant le join, ou en faisant appel à la relation quand ta transaction est encore active.

    HadanMarv

  5. #5
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2011
    Messages : 43
    Points : 18
    Points
    18
    Par défaut
    Ok mais le vrai problème (et ça personne ne peut me répondre), c'est que j'ai vraiment cru comprendre qu'il faut passer par des "Set" et non des "List" pour faire ça. Or, sur les pages JSF, tu ne peux pas afficher des "Set", mais seulement des "List".

    Quelqu'un peut-il m'éclairer là-dessus ?

  6. #6
    Modérateur
    Avatar de paissad
    Homme Profil pro
    Ingénieur de développement (Java/JEE/Eclipse RCP,EMF & webMethods)
    Inscrit en
    Avril 2006
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur de développement (Java/JEE/Eclipse RCP,EMF & webMethods)
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 043
    Points : 2 560
    Points
    2 560
    Par défaut
    Cela n'a rien à voir avec les types de Collection utilisés (Set, ou List ou Map ou autre chose ...)
    Nous n'héritons pas de la terre de nos parents, nous l'empruntons à nos enfants.
    Le chat du site est aussi ici pour aider. Ne pas hésiter à visiter !

  7. #7
    Membre chevronné
    Avatar de fxrobin
    Homme Profil pro
    Architecte SI, Java Fan, API Manager
    Inscrit en
    Novembre 2007
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Architecte SI, Java Fan, API Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2007
    Messages : 875
    Points : 2 112
    Points
    2 112
    Par défaut
    Citation Envoyé par zaitsev Voir le message
    Ok mais le vrai problème (et ça personne ne peut me répondre), c'est que j'ai vraiment cru comprendre qu'il faut passer par des "Set" et non des "List" pour faire ça. Or, sur les pages JSF, tu ne peux pas afficher des "Set", mais seulement des "List".

    Quelqu'un peut-il m'éclairer là-dessus ?

    même si cela n'a rien n'a voir, pour accéder aux données d'un Set en tant que List dans une page JSF (dataTable), il suffit d'enrober l'instance de ton Set dans une instance de List grâce au constructeur qui va bien:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Set <MonTypeObjet> monSet = .... ;
    List <MonTypeObjet> maList = new ArrayList <MonTypeObjet> (monSet);
    Les API Java sont bien faites quand même :
    http://docs.oracle.com/javase/6/docs...til.Collection)


    sinon pour le "problème de fond", effectivement il faut passer par du LAZY_LOADING
    Moins on code, moins il y a de bug ... et vice-versa ainsi qu'inversement ...

  8. #8
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2011
    Messages : 43
    Points : 18
    Points
    18
    Par défaut
    Ok, merci de ta réponse.

    Maintenant que je réalise mes chargements en LAZY, j'obtiens des erreurs du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    failed to lazily initialize a collection of role
    Je trouve pas de solutions, j'ai lu des conseils portant sur les transactions mais moi j'ai mes simples classes Java du modèle avec le get/set, donc je ne vois pas comment m'en sortir ?

  9. #9
    Membre régulier
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2009
    Messages
    169
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Octobre 2009
    Messages : 169
    Points : 100
    Points
    100
    Par défaut
    charger les relations lorsque tu en as besoin en explicitant le join, ou en faisant appel à la relation quand ta transaction est encore active.
    Ce qui veut dire qu'au moment de la recherche tu dois spécifier le join au niveau du criteriaQuery par exemple, ou bien faire appel aux get en direction de ta relation pendant que la transaction est encore active.

    Si ce n'est pas clair, montre nous un bout de ton code permettant la récupération en base afin te pouvoir t'aider de manière plus efficace.

    HadanMarv

  10. #10
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2011
    Messages : 43
    Points : 18
    Points
    18
    Par défaut
    Je ne vois pas trop le rapport avec Criteria, c'est hibernate qui se charge de "remplir" mes classes du modèle, avec les get/set, donc pas de code criteria. Voici du code :

    Ici le code de ma classe du modèle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	@OneToMany(mappedBy = "person", fetch = FetchType.EAGER)
    	public Set<PersonRoleJoin> getPersonRoleJoins() {
    		return personRoleJoins;
    	}
     
    	public void setPersonRoleJoins(Set<PersonRoleJoin> personRoleJoins) {
    		this.personRoleJoins = personRoleJoins;
    	}
    Ici le code de mon bean controlleur, qui plantera (sur la ligne 12) si je met du LAZY dans le code du dessus :

    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
    public List<Role> getUserRoleLinks() {
     
    		Portal portal = sessionController.getPortal();
    		User user = sessionController.getUser();
    		Person person = user.getPerson();
     
    		// user not logged
    		if (person == null || portal == null) {
    			return roles;
    		}
     
    		Set<PersonRoleJoin> personRoleJoins = person.getPersonRoleJoins();
     
    		// we only add roles associated to the current user portal
    		for (PersonRoleJoin personRoleJoin : personRoleJoins) {
     
    			Role role = personRoleJoin.getRole();
     
    			if (role.getPortal().compareTo(portal) == 0) {
     
    				roles.add(role);
     
    			}
    		}
    		return roles;
    	}

  11. #11
    Membre chevronné
    Avatar de fxrobin
    Homme Profil pro
    Architecte SI, Java Fan, API Manager
    Inscrit en
    Novembre 2007
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Architecte SI, Java Fan, API Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2007
    Messages : 875
    Points : 2 112
    Points
    2 112
    Par défaut
    Salut, je crois qu'en LAZY loading il te faut initialiser ton Set avec une instance "vide" dans la déclaration de ta classe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    private Set<PersonRoleJoin> personRoleJoins = new HashSet <PersonRoleJoin> ();
    de mémoire le lazy loading n'instancie pas de liste / set, mais les peuple, alors que le EAGER instancie des List / Set qu'il affecte à ta variable.
    Moins on code, moins il y a de bug ... et vice-versa ainsi qu'inversement ...

  12. #12
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2011
    Messages : 43
    Points : 18
    Points
    18
    Par défaut
    Merci de ton aide, j'ai vraiment cru que c'était une bonne piste mais malheureusement, même en instanciant mes " Set " j'obtiens toujours cette erreur :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    javax.servlet.ServletException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: net.atos.si.aix.portail.model.Person.personRoleJoins, no session or session was closed

  13. #13
    Membre chevronné
    Avatar de fxrobin
    Homme Profil pro
    Architecte SI, Java Fan, API Manager
    Inscrit en
    Novembre 2007
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Architecte SI, Java Fan, API Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2007
    Messages : 875
    Points : 2 112
    Points
    2 112
    Par défaut
    Tu utilises quoi ?

    EJB Entity + EJB Session ?
    Classe Entity + Session Hibernate ?

    Si tu es dans le second cas :
    - http://www.objis.com/formation-java/...bernate-3.html
    - http://www.developpez.net/forums/d28...led-to-lazily/

    un peu de recherche avec Google, ça aide aussi
    Moins on code, moins il y a de bug ... et vice-versa ainsi qu'inversement ...

  14. #14
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2011
    Messages : 43
    Points : 18
    Points
    18
    Par défaut
    J'utilise les EJB entity (@Entity...) et les EJB Session (@Stateful).

    Franchement j'ai pas mal cherché mais il faut avouer que c'est pas très très clair, faire du Lazy sur des collections de ton entité, ca devrait quand même être la base.

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Le lazy loading est bien de base, mais il faut comprendre que si tu utilises une trasaction JTA par défaut, dès que tu sorts du conteneur d'EJB tes entities sont "détachées" et donc, tous les objets non initialisés poseront problème au niveau de la couche de présentation.

    Il existe plusieurs moyen de contourner le problème, en particulier les DTO, très critiqués, mais très utiles quand on veut utiliser les même entity dans différents contextes.
    Tu pourrais éventuellement utiliser un Query plutôt que find, ce qui te permettrait d'ajouter les demandes "join fetch" qui vont bien en fonction de ce que tu veux initialiser.
    Sinon, il y a PersistenceContextType.EXTENDED qui permettrait d'utiliser la même transaction plusieurs fois...

    Perso, j'aime bien les DTO
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  16. #16
    Membre averti
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    250
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2011
    Messages : 250
    Points : 403
    Points
    403
    Par défaut
    Pour récupérer un objet "light", tu peux utiliser un DTO ce qui te permet d'avoir des objets simples ,ou comme alternative une requête HQL du type
    select new MonObj(ppt1,ppt2) from MonObj.
    Cela nécessite que ta classe MonObj possède un constructeur avec les propriété issues du résultat de ton select.
    Avec ce type de syntaxe, tu peux remonter des objets pseudos-initalisés, les principales contraintes sont que tu ne peux remonter des propriétés de type collection et que bien évidemment tu ne peux/doit pas persister ces objets.

Discussions similaires

  1. Réponses: 14
    Dernier message: 30/11/2007, 11h58

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