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

Persistance des données Java Discussion :

Comment ne pas récupérer toutes les informations d'une table jointe ?


Sujet :

Persistance des données Java

  1. #1
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 695
    Points : 2 434
    Points
    2 434
    Par défaut Comment ne pas récupérer toutes les informations d'une table jointe ?
    Bonjour.

    Je résume mon soucis :
    Il y a une base de données avec une table User et une table Country liées par une relation 1-n (Un utilisateur réside dans un pays) :

    Nom : DB2.png
Affichages : 258
Taille : 29,2 Ko


    Il y a un web service REST pour récupérer les données d'un utilisateur, en Spring + Persistance :
    Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Controller
    @Api(value = "/users")
    @RequestMapping("/users")
    public class UserController {
        @RequestMapping(value = "/", method = RequestMethod.GET)
        @ResponseBody
        public ResponseEntity<Iterable<User>> listUsers() throws ServletException {
            return new ResponseEntity<>( userDao.findAll(), HttpStatus.OK );
        }
    }

    La relation User/Country est définie dans le modèle comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Entity
    public class User implements Serializable {
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "country")
        private Country country;
    }
     
    @Entity
    public class Country implements Serializable {
        @JsonIgnore
        @OneToMany(mappedBy="country",fetch=FetchType.LAZY)
        private List<User> users;
    }
    Le problème est que quand je récupère les données des utilisateurs, je m'attends à n'avoir que le code du pays, mais les données du pays viennent aussi avec. Au lieu d'avoir
    Code json : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    [
        {"id":1,"mail":"test1@test.net","username":"test1","password":"hxdylk1csg3fsqklfvq4","country":"FR"},
        {"id":2,"mail":"test2@test.net","username":"test2","password":"gfgh4dxg8sgbsbgqE78f","country":"BE"}
    ]
    J'ai :
    Code json : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    [
        {"id":1,"mail":"test1@test.net","username":"test1","password":"hxdylk1csg3fsqklfvq4","country":
        	{"code":"FR", "name":"France", "pleindautresdonnees"}
        },
        {"id":2,"mail":"test2@test.net","username":"test2","password":"gfgh4dxg8sgbsbgqE78f","country":
        	{"code":"BE", "name":"Belgique", "pleindautresdonnees"}
        },
    ]

    J'ai raccourci le résultat, il y a en réalité beaucoup plus de données provoquant au passage une erreur de stream.

    Je pensais que l'ajout de FetchType.LAZY dans le modèle résoudrait le soucis.
    Je suis un peu perdu, est-ce que vous avez une idée d'où ça peut venir, et comment arriver à ce que je veux ?

    Merci.
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Peut-on voir le code de ta méthode userDao.findAll() ?

  3. #3
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 695
    Points : 2 434
    Points
    2 434
    Par défaut
    Je n'ai pas fourni d'implémentation, c'est celle par défaut.

    Quand je clique dessus dans mon IDE, je tombe sur celle de CrudRepository (package org.springframework.data.repository). En effet, c'est par elle que je passe car mon UserDao implémente cette classe (public interface UserDao extends CrudRepository<User,Integer>{}).
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  4. #4
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 936
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 936
    Points : 4 356
    Points
    4 356
    Par défaut
    Citation Envoyé par Daïmanu Voir le message
    Bonjour.

    Je résume mon soucis :
    Il y a une base de données avec une table User et une table Country liées par une relation 1-n (Un utilisateur réside dans un pays) :
    Lazy signifie juste que vous chargez l'entité en relation lors de l'accès dans le code Java, dans ce cas-ci le Lazy sur Country dans User n'a aucun intérêt puisque vous voulez avoir le code pays.

    Si ce que vous voulez faire c'est juste de l'affichage des Users :
    - soit vous mettez Country en eager dans User : l'ORM fera un (left) join
    - soit vous mappez sur une @Entity (read-only) basée sur un select :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    @Entity
    @Subselect("select u.*, c.code as country_code, c.name as country_name from users u left join country c on u.ref_country = c.pk"
    public class DisplayUser {
     
    @Column(name="country_code", updatable=false)
    pro
     
    …
    }
    et dans ce cas le mapping de u.ref_country devra se faire un le type sous-jacent de la PK et pas sur l'entité Country:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    @Column(name="ref_country")
    protected Long refCountry ;
    ou

    vous mappez uniquement les champs de User que vous voulez et vous explicitez tous ces champs dans le select au lieu de faire "u.*"


    le @Subselect peut aussi être une vue évidemment :
    @Subselect("select * from v_displayusers")

    et vous pouvez ré-utilisez DisplayUser dans d'autres queries en appelant directement les fonctionnalités de l'entity manager (en ajoutant des commandes de tri par exemple)

  5. #5
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 695
    Points : 2 434
    Points
    2 434
    Par défaut
    Bonjour.

    Merci pour les précisions sur Lazy.

    J'ai trouvé une solution qui reprend l'idée de modèle personnalisé et simplifié.

    J'ai rajouté une classe UserSummary dans laquelle j'ai mis uniquement les champs que je veux afficher, dont un String pour le code pays.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class UserSummary {
        public UserSummary(int id, String mail, String username, String country) {
            this.id = id;
            this.mail = mail;
            this.username = username;
            this.country = country;
        }
        /* tous les champs, getters et setters */
    }
    Je cache au passage le mot de passe.

    Il y une nouvelle méthode listAll au niveau du Dao que j'utilise dans le contrôleur, cette méthode utilise le summary comme ceci :
    Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    import org.springframework.data.jpa.repository.Query;
     
    public interface UserDao extends CrudRepository<User,Integer> {    @Query("SELECT new com.project.UserSummary(u.id, u.mail, u.username, u.country) " +
                "FROM User u")
        public List<UserSummary> listAll();
    }

    C'est contraignant et sûrement un peu sale, mais ça fonctionne.

    Merci !
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 09/04/2015, 21h28
  2. [Débutant] Comment ne pas retourner toutes les entités liées ?
    Par Lord Yu dans le forum Entity Framework
    Réponses: 2
    Dernier message: 22/02/2013, 09h05
  3. Problème pour récupérer toutes les informations d'un XML
    Par neo62matrix dans le forum Général Python
    Réponses: 2
    Dernier message: 30/03/2012, 10h55
  4. Les fichiers .INI, lire toutes les informations d'une section
    Par echap2000 dans le forum C++Builder
    Réponses: 9
    Dernier message: 15/05/2006, 12h14

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