11
votes

Jpa2 / hibernate - arrêter le chargement paresseux?

J'ai un problème où JPA tente de charger paresseusement mes données lorsque je ne le veux pas. Essentiellement, ce qui se passe est que j'utilise un service pour récupérer certaines données, et lorsque je vais analyser les données dans JSON, la bibliothèque JSON déclenche des hibernes pour essayer de charger de manière paresseuse les données. Y a-t-il un moyen d'arrêter cela? J'ai donné un exemple ci-dessous

// Web Controller method
public String getEmployeesByQuery(String query) {

    Gson gson = new Gson();
    List<Employee> employees = employeeService.findEmployeesByQuery(query);

    // Here is where the problem is occurring - the gson.toJSON() method is (I imagine)
    // using my getters to format the JSON output, which is triggering hibernate to
    // try and lazily load my data...
    return gson.toJSON(employees);
}


4 commentaires

Pourriez-vous en informer davantage de votre question: Voulez-vous passer complètement de chargement paresseux au chargement impatient ou souhaitez-vous ne pas payer des employés de charge paresseux dans ce cas spécifique et pourquoi?


Mon problème est que je ne veux pas charger paresseusement les données. Bien sûr, je pourrais la marquer pour le chargement impatient - mais si je ne me soucie même pas de ces données en ce moment? Par exemple, si j'ai un employé qui a de nombreux postes, mais je ne veux pas que les données parce que c'est trop détaillé pour la vue que je veux rendre, comment puis-je dire JPA de ne pas essayer de chercher ces données?


Essayez ceci: Stackoverflow.com/Questtions/4802887/...


J'ai eu le même problème. Ce qui suit a fonctionné pour moi. Stackoverflow.com/Questtions/4802887/...


8 Réponses :


1
votes

Oui:

@*ToMany(fetch=FetchType.EAGER)


0 commentaires

0
votes

Vous pouvez toujours changer l'attribut extraire à fetchtype.eauger , mais il vaut également la peine d'être envisagé si vos transactions ont la bonne portée. Les collections seront correctement chargées si elles sont accessibles dans une transaction.


0 commentaires

6
votes

Il existe plusieurs options:

  • Si vous avez toujours besoin de charger votre collection avec impatience, vous pouvez spécifier fetch = fetchtype.eauger dans votre mappage, comme suggéré dans d'autres réponses.

  • sinon, vous pouvez activer la récupération désireuse pour une requête particulière:

    • à l'aide de Rejoindre la clause dans la requête HQL / JPQL: XXX

    • En utilisant Fetch Profils (en JPA Vous pouvez accéder à Hibernate session via em.unwrap (session.class) )

2 commentaires

La chose est que je ne veux pas que des données supplémentaires. Vraiment tout ce que je veux, ce sont des champs de base d'un seul employé (comme prénom, nom de famille, numéro de téléphone, etc.) et ne pas avoir d'hibernate essayer de récupérer plus de données quand je ne le veux pas!


@Brian: Si vous ne voulez pas inclure ces champs dans la représentation JSON, vous devez instruire votre sérialisateur JSON à ignorer ce champ, comme suggéré par Ruggs. Cela n'a rien à voir avec JPA et Hiberner.



1
votes

Je vous suggère de faire une copie extraire des entités que vous souhaitez utiliser en dehors d'une transaction. De cette façon, le chargement paresseux se produira d'une transaction et vous pouvez passer à GSON une plaine, non améliorée, pojo.

Vous pouvez utiliser doozer pour le faire. Il est très flexible et à travers une petite configuration (lire vous allez perdre vos cheveux en configuration ) Vous pouvez même récupérer uniquement partiellement les données que vous souhaitez envoyer à gson.


2 commentaires

C'est une option, mais j'aimerais vraiment éviter d'ajouter une autre bibliothèque si possible.


Vous pouvez le faire manuellement si vous souhaitez utiliser la réflexivité pour découvrir les getters et les setters, mais utiliser une bibliothèque vous permettra d'économiser des heures de développement sujette à erreurs d'ennui.



3
votes

Vous avez vraiment deux options:

  1. Vous pouvez copier les données de l'employé en un qui n'est pas proxé par Hibernate.
  2. Voir s'il y a un moyen de ne pas avoir la bibliothèque tojson reflète le graphique de l'objet entier. Je sais que certaines bibliothèques JSON vous permettent de sérialiser certaines propriétés d'un objet à JSON.

    Personnellement, je penserais que # 1 serait plus facile si votre bibliothèque utilise uniquement la réflexion.


2 commentaires

On dirait que ceux-ci peuvent être les seules options. Mais l'un d'eux n'est pas vraiment idéal. Vous penseriez que JPA spécifierait un moyen d'avoir des entités détachées et non d'essayer de récupérer plus de données ...


J'ai utilisé Hibernate et JPA et j'ai eu ce problème dans les deux. Je n'ai jamais trouvé de bon moyen de le résoudre.



0
votes

Votre problème est que vous sérigez les données. Nous avons rencontré le même genre de problème avec Flex et JPA / Hibernate. L'astuce est, en fonction de la quantité que vous voulez mangler des choses, soit

  1. Changez votre modèle de données pour ne pas poursuivre la poursuite des données que vous ne voulez pas.
  2. Copiez les données que vous souhaitez dans une sorte de DTO qui n'a aucune relation à vous inquiéter.
  3. En supposant que vous utilisiez Hibernate, ajoutez le filtre de session-in-View ... C'est quelque chose comme ça, il conservera la session ouverte pendant que vous serifiez toute la base de données. ;)

    Option On est ce que nous avons fait pour le premier grand projet que nous avons fait, mais il a ruiné la bibliothèque d'accès aux données que nous avons eue pour une utilisation à usage général. Depuis lors, nous avons tendance davantage vers l'option deux.

    ymmv


0 commentaires

2
votes

Comme d'autres ont déclaré, ce n'est pas un problème avec JPA / Hibernate, mais plutôt avec la bibliothèque de sérialisation JSON que vous utilisez. Vous devriez Instructeur Gson à Exclure les propriétés que vous ne voulez pas traverser.


0 commentaires

0
votes

La chose facile et simple à faire est de créer de nouvelles classes de données (quelque chose comme DTO) Utilisez hibernate.isInitialisé () pour vérifier si l'objet est initialisé par hibernate ou non. Je vérifie le gson si je peux remplacer quoi que ce soit. Je vais le poster ici si je trouve quelque chose de nouveau.


0 commentaires