7
votes

Comment puis-je implémenter Tostring () dans une classe qui est mappée avec hibernate?

J'ai une instance d'une classe que j'ai obtenue d'une session hibernate. Cette session est longue. Maintenant, j'appelle tostring () et je reçois l'attendu LazyinitializationException: impossible d'initialiser le proxy - aucune session puisque j'essaie d'accéder à une référence qui hibernate n'a pas été résolu lors du chargement de l'instance (chargement paresseux).

Je ne veux pas vraiment faire le chargement impatient car il changerait la requête d'environ 120 caractères à plus de 4 Ko (avec huit jointures). Et je n'ai pas à: tout ce que je veux afficher dans Tostring () est l'identifiant de l'objet référencé; C'est-à-dire que quelque chose que l'hibernation a besoin de savoir à ce stade de temps (ou cela ne pouvait pas faire le chargement paresseux).

Donc ma question: comment gérez-vous ce cas? N'essayez jamais d'utiliser des références dans Tostring () ? Ou appelez-vous tostring () dans le code de chargement au cas où? Ou existe-t-il une fonction utilitaire dans l'hibernate qui reviendra quelque chose d'utile lorsque je transmettais une référence qui pourrait être paresseux? Ou évitez-vous les références dans Tostring () Au total?


4 commentaires

Si Java avait une fermeture, vous pouviez faire: String X = Lazytostring ({=> Ceci.Gety ()}) + Lazytostring ({=> Ceci.getz ()}); et attraper l'expection dans la méthode lazytostring. Les frais généraux avec des classes intérieures (ou essayer / attraper) sont trop élevés pour le faire.


Oui, mais cela ne me donnerait pas une session non plus.


C'est vrai. Vous pouvez uniquement imprimer que la valeur n'est pas chargée. Je pensais que c'était l'intention. Vous ne pourrez pas démarrer une session et associer l'objet sur l'appel de la méthode de tostring.


Mon point est que ces informations doivent être disponibles quelque part (voir ma réponse ci-dessous) :)


4 Réponses :


0
votes

Si tout ce que vous voulez revenir est l'identifiant de l'objet, j'imagine appeler getid (), puis analyser l'int / long comme une valeur de chaîne au moment où vous le souhaitez que l'affichage fonctionnerait bien. Au moins c'est comme ça que cela semble basé sur la question.

modifier

Comment résoudre la lazymisationException en utilisant jpa et hibernate

Après avoir visionné le commentaire et effectuez des recherches, je pense que cela peut être le plus bénéfique pour votre scénario.


6 commentaires

Cela jettera la lazyinitialisationExceptionException car la référence n'a pas encore été résolue.


Aaron, après avoir lu ce commentaire, j'ai édité mon message. S'il vous plaît voir les nouvelles informations et laissez-moi savoir si cela résout le problème.


@Woot - Les réponses ne vous aideront pas. Les valeurs initialisées paresseuses ne seront jamais lues. Le TX est commis. La connexion fermée.


Oui, je vois que la transaction est déjà commise. Toutefois, dans le poste, il est possible de refroidir le code existant pour utiliser le modèle OpenSessionInview recherché ici: hibernate. org / 43.html si cela n'est pas faisable dans l'environnement d'Aaron que ce n'est pas le cas.


@Woot: Je suis d'accord avec Thomas.


À l'époque, j'appelle Tostring (), je n'ai aucune session et je ne veux pas en créer un. La question est vraiment: comment puis-je faire des travaux de Tostring () à l'intérieur et à l'extérieur d'une session?



1
votes

J'ai trouvé une solution de contournement:

class Parent {
    DBObject child;
    public String toString () {
        return "Parent (id=..., child=" + getId(child)+")");
    }
}


0 commentaires

6
votes

Il est possible de le faire en définissant l'accélérateur du champ ID sur "Propriété". Comme: XXX

Il est expliqué ici . De cette façon, le champ ID est toujours peuplé lors de la création d'un proxy.


3 commentaires

+1 j'aime ça; Il n'y a qu'une prise mineure: j'utilise la syntaxe DSL, alors mon getter est appelé "ID ()", pas "getid ()". Je suppose que je pourrais ajouter une deuxième getter pour ce cas particulier, mais il est peut-être possible de dire hibernate le nom de la getter?


Eh bien, il est possible en créant votre propre implémentation d'org.hibernate.property.propertyAccessor et déclarez le nom pleinement qualifié comme valeur pour @AccessType. D'autre part, vous pouvez créer le setter (vous aurez besoin de cela aussi) et de les getter et de les rendre privés, de sorte que vous ne les verrez pas du reste de votre application.


@Ejb: Est-ce que cela fonctionnait vraiment? J'ai une situation où la classe A ------> (comporte une autre à plusieurs rel) avec la classe B. A et B ont plusieurs propriétés. Ainsi, lorsque je fais une méthode de tostring () appel à la classe A, il échoue avec une exception lazymatisation (identique que ci-dessus) malgré la définition du @accessype ("propriété") pour le champ d'identification de la classe A.



1
votes

J'ai trouvé la façon dont la meilleure pratique est une modification de la solution trouvée sur ce blog: http://www.nonfunc.com/2016/02/05/jpa-performance-gotcha-tostring-really/ . Il a besoin de modification des champs nullables et des objets de collections.

public toString() {
  return String.format("FuBar [id=%d" +  
      + ", fu=%s" // fu is a lazy non-nullable field
      + ", bar=%s" // bar is a nullable lazy field
      + ", borks=%s]", // borks is a lazy collection of Bork objects
      id,
      fu instanceof HibernateProxy ? "[null]" : bar.toString(),
      bar == null || bar instanceof HibernateProxy ? "[null]" : bar.toString(),
      borks instanceof PersistentSet ? "[null]" : borks.toString());
}


2 commentaires

Je vois ce que tu fais là-bas. Quelques commentaires: Mélange string.format () et + est mauvais pour la performance. Vous devez également remplacer [null] avec parce que le proxy n'est pas nul - il n'est tout simplement pas chargé. Une approche encore meilleure serait de retourner type est le type d'entité et ID est la clé primaire.


Code édité pour la performance. L'exemple n'était pas exactement ce que j'ai et la concaténation d'une variable et de chaîne effectue des performances d'effet (la chaîne de format doit être compilée dans une chaîne statique), mais je pense que la transpiration sur une performance de Tostring n'est pas super importante, Comme il serait utilisé pour le débogage ou la déclaration d'erreur et ne devrait pas être appelé super fréquemment dans des situations de production. J'aime bien la suggestion de spécifier les paresseux vs null, cependant.