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 :

Quelques questions sur l'utilisation d'Hibernate


Sujet :

Persistance des données Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Février 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Février 2017
    Messages : 4
    Par défaut Quelques questions sur l'utilisation d'Hibernate
    Bonjour,

    J'ai fais un petit projet test pour apprendre Hibernate et il y a un certain nombre de choses que je ne sais pas comment faire correctement (en gros ça marche mais ça à l'air de tenir plus de la chance que de la technique).

    J'ai une couche contrôleur, 1 couche service et 1 couche accès aux données. Dans ma couche accès aux données j'accède aux objets persistés via Hibernate (jusque là ça va). J'ai mis certaines relations en lazy loading (mettons une relation Classe vers Eleves). Là où ça se complique c'est que des fois j'ai besoin des données des élèves et des fois non, suivant les méthodes de ma couche contrôleur.

    1) Si je veux faire un service qui liste les classes, pas de problème la relation est en lazy loading et je ne récupère donc pas les données des élèves en trop tant que je n'en ai pas besoin. Par contre une Classe à une relation "parent" vers une Ecole (qui elle liste toutes les classes). Comme le client de mon service n'a pas besoin de ce lien, je le mets à null dans la couche contrôleur pour qu'il ne soit pas sérialisé. Ca fonctionne mais je ne comprends pas pourquoi ça n'a pas d'impact sur la base de données, alors que je n'ai pas détaché mon entité. J'ai de la chance et je ne peux pas compter que ça fonctionnera à tous les coups ou il y a une vrai raison et ça fonctionnera tout le temps?
    Avec les traces activées, je vois que les requêtes d'écriture ne sont pas déclanchées tout de suite (dès fois une lecture les délanche). Je suppose donc que le framework choisit quand exécuter les requêtes et j'ai juste eu de la chance qu'il n'ai pas choisit d'exécuter ma modif??? Ou alors c'est parceque lorsque je veux vraiment faire une modif c'est fait dans une méthode annotée @Transactional et qu'en dehors de ces méthodes aucune mise à jour n'est prise en compte?

    2) Pour éviter d'avoir des impacts sur la base de données j'ai essayé de détacher systématiquement mes entités dans la couche de persistence. Sauf que ça fonctionne très bien dans le cas où je n'ai pas besoin des données en lazy loading mais nettement moins bien quand j'essaye d'y accéder. Je comprends la raison, mais comment je devrais faire? ne jamais détacher? Ou détacher plus haut (couche service ou couche contrôleur)? Ca me gène un peu d'exposer l'EntityManager dans les couches supérieures donc je ne pense pas que ce soit la bonne solution... Du coup je ne détache pas, ça fonctionne mais je tombe dans le cas 1).

    Merci pour les éclaircissements que vous pourriez m'apporter.

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Première question: pourquoi diable y-a-t-il sérialisation entre ton controlleur et ton dao? Ce n'est à priori pas nécessaire.

    En supposant ce problème retiré, ce que tu dois faire, c'est avoir une seul et unique transaction qui dure tant que ton controlleur a besoin de données. A priori ton controlleur travaille pour 1 demande de ta vue (donc 1 transaction) en effectuant un certain nombre d'opérations sur le dao.

    Pour ce qui est de l'exécution des requêtes d'hibernate, le moment où elle s'exécuteront dépendra de si tu utilise hibernate tout seul ou comme un provider JPA. En JPA toute modification est prise en compte et la transaction commit par défaut. En Hibernate, la transaction ne commit pas sauf si tu le demande. Dans tous les cas, hibernate modifiera la db dès qu'il estime que la requête que tu t'apprête à exécuter aura besoin de données présentes dans les pojos modifiés pour retourner un résultat correct.

    Exemple: tu change le nom d'un élève puis tu cherche tous les élève dont le nom commence par a. Les modifications seront flushées.

  3. #3
    Candidat au Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Février 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Février 2017
    Messages : 4
    Par défaut
    J'ai du mal m'exprimer. La sérialisation n'est bien évidemment pas entre le controleur et le DAO mais entre le contrôleur et la vue. Je récupère des données dpuis mon DAO, elles remontent jusqu'à mon contrôleur et c'est là que j'essaye de retirer tout ce dont la vue n'a pas besoin. Le problème c'est que si mon objet est détaché au niveau du DAO je peux retirer les données dont je n'ai pas besoin (pour que la sérialisation soit plus légère) mais dans ce cas là je ne peux plus accéder aux données en lazy loading.
    Et si je ne détache pas je peux charger les données en lazy loading lorsque j'y accède dans mon contrôleur mais quand je retire des données (dans le contrôleur) avant la sérialisation je ne vois aucune requête dans la console mais j'ai peur qu'elle puisse être effectuée quand même au moment ou la transaction est flushée...

    Ex: une méthode du contrôleur qui récupère La liste des Eleves d'une classe n'a pas besoin de renvoyer à la vue la relation vers la Classe car on sait déjà dans quelle classe il est. Donc je fais un eleve.setClasse(null) dans le contrôleur. Même si je n'ai pas détaché l'objet Eleve je n'ai pas de requête qui efface la relation entre l'élève et la classe mais ça je ne comprends pas pourquoi...

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Il faudrait que tu détaille un peu plus ton architecture. Pourquoi ce besoin de sérialisation? Ton DAO et ta vue sont sur des JVMs différentes? Si c'est le cas, en général on ne transfère pas directement les objets Business, on recours plutôt à des DAO intermédiaire qui collent plus aux méthodes du controlleur qu'à la structure DB. Ce qui permet par exemple d'avoir une méthode qui retourne des collections, d'autres juste des données sommaires.
    Il faudrait aussi que tu détaille comment tu démarque tes transactions et tes sessions. Est-ce que tu fais du JPA?

  5. #5
    Candidat au Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Février 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Février 2017
    Messages : 4
    Par défaut
    J'utilise Spring + JPA. La sérialisation c'est de la sérialisation JSON pour la vue et elle est gérée automatiquement par le controleur Spring.

    Mon controleur est annoté avec l'annotation @RestController.

    Dedans j'ai 2 méthodes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Eleves[] getEleves(int classeId) {
      ... // récupération des données auprès de la couche service
      for (Eleves eleve : eleves) {
         eleve.setClasse(null);    //On efface la relation vers la classe pour alléger la sérialisation. Mauvaise idée???
      }
    }
     
    Classes[] getClasses() {
    ...  // récupération des données auprès de la couche service
    }
    Quand ma vue invoque getClasses() elle s'attend à avoir 1 tableau de Classe dont chacune possède une liste d'élèves.

    Quand ma vue invoque getEleves() elle s'attend à avoir 1 tableau d'élève mais pour alléger la sérialisation je voudrait mettre la backreference de chaque Eleve vers Classe à null (la vue sait déjà dans quelle classe on est puisqu'elle à passé le classeId).

    Que je mette ou pas l'annotation @Transactional ça fonctionne. Du coup je ne sais pas bien où l'objet est détaché (la transaction et la session sont ouvertes au niveau du contrôleur géré par Spring ???. Si c'est le cas pourquoi je ne vois pas passer de requête SQL quand je fais eleve.setClasse(null) puisque je suis encore dans le contrôleur?).

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Si c'est du JPA, la session a la durée de vie de la transaction, géré par le conteneur. Je ne connais pas assez spring et sa gestion transactionnelle pour savoir à quel moment elle est démarquée par rapport au conteneur ou si ça a le moindre rapport.


    Comme tu commence à le constater c'est une mauvaise idée de mapper directement tes entités sur la couche rest:

    tu expose éventuellement des clés privées sur la couche rest, pire quand tu va recevoir des données, tu va être obligé de vérifier que l'utilisateur n'utilise pas par exemple ton élève pour le changer de classe en catimini voir créerait tout un structure dans ton dos. Il faut que tu sépare en ayant des objet spécifiques à ta vue et ton controlleur rest se charge de transmettre ce qu'il y a à transmettre. Exemple: tu veux stocker une nouvelle note pour un élève, ta méthode devrait jsute accepter l'id de l'élève et la note.

Discussions similaires

  1. Plugin Week Calendar, j'ai quelques question sur l'utilisation !
    Par Cvbdev dans le forum Bibliothèques & Frameworks
    Réponses: 0
    Dernier message: 21/06/2010, 14h00
  2. Question sur l'utilisation de wget
    Par berry dans le forum Réseau
    Réponses: 7
    Dernier message: 24/05/2007, 22h46
  3. Quelques question sur Win 32 Appli
    Par lvdnono dans le forum Windows
    Réponses: 5
    Dernier message: 15/06/2004, 12h37
  4. Quelques questions sur le TWebBrowser...
    Par CorO dans le forum Web & réseau
    Réponses: 3
    Dernier message: 17/01/2003, 21h23

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