10
votes

Pourquoi hibernate renvoie-t-il un objet proxy?

J'ai une méthode de service qui appelle une DAO qui renvoie ensuite un objet de la base de données. Cette méthode est appelée à partir de nombreuses parties du système. Cependant, une méthode particulière consiste à obtenir un type de retour d'objetClass _ $$ _ Javassist_somenumber en tant que type. Qui lance des choses. J'appelle la méthode de service exactement la même que partout ailleurs, alors pourquoi hibernerait-elle renvoyer le proxy par opposition à l'objet naturel?

Je sais qu'il y a des moyens d'exposer l'objet "proxé", mais je n'ai pas l'impression d'avoir à le faire.

La requête est simplement xxx

J'utilise hibernate 3.3 BTW.


0 commentaires

3 Réponses :


2
votes

Hibernate renvoie des mandataires si tous les membres ne sont pas résolus, c'est-à-dire que l'objet n'est pas complet. Ceci est souvent une caractéristique souhaitée pour améliorer les performances et est (je pense) le paramètre par défaut dans Hibernate.

Si vous ne voulez pas de proxy, vous pouvez supprimer le chargement paresseux dans le fichier HBM.XML, c'est-à-dire. Utilisez le chargement impatient. Veuillez vérifier les documents hibernate pour la syntaxe exacte.

Pour utiliser l'objet proxy, n'accédez jamais à un membre directement mais uniquement via Getter, même au sein des fonctions membres. Hibernate Magic remplit dans le membre lorsque vous l'obtenez. De cette façon, vous ne devez jamais exposer l'objet. N'utilisez pas non plus l'instanceOf sur des objets proxy potentiels. Mais c'est une odeur de code quand même.


5 commentaires

L'instance de chèques fonctionnera toujours, car les mandataires sont toujours des cas de sous-classes de votre classe. Ce qui ne fonctionnerait pas, c'est un égal ou une comparaison d'identité de l'objet de classe (comme fourni par GetClass ()).


Je rencontre ce problème mais j'ai trouvé que la déclaration ci-dessus est incorrecte, ce qui était de savoir comment nous avons trouvé le problème. Nous parcourons une collection et vérifions «l'instance de» pour l'objet attendu qui échoue. Honnêtement, je ne sais pas exactement comment Java gère cela en interne mais nous mettons un imprimeur avec "instanceOf x =" + (instance OBJ de X) et il est imprimé de faux. L'hibernate.getclass (Obj) fonctionne bien, mais j'aimerais aller au fond des raisons pour lesquelles l'objet n'était pas complètement initialisé.


@WhisKeysierra - Désolé, j'ai oublié d'inclure votre identifiant pour la notification du commentaire ci-dessus.


À propos de l'instance de problème - Si vous utilisez un proxy paresseux dans un champ avec la classe A déclarée, alors même si vous avez une classe B de classe B, si vous récupérez l'objet dans le champ A, il ne sera jamais "instance de B". C'est parce que Hibernate ne sais pas quelle sera la véritable classe de l'entité avant de l'obtenir de la DB, et il ne peut pas l'obtenir car vous utilisez explicitement un proxy paresseux ici. Il utilise donc la classe déclarée (A) pour créer un proxy. Je l'ai décrit plus minutieusement ici Lifeinide.com / post / ...


InstanceOf Les chèques ne fonctionneront que si vous n'avez aucune héritage dans vos entités.



10
votes

C'est un objet proxé afin de supporter le chargement paresseux; Fondamentalement dès que vous faites référence à un objet enfant ou de recherche via les méthodes accessor / getter, si l'entité liée n'est pas dans le cache de session, le code proxy ira à la base de données et chargez l'objet lié. Il utilise Javassist pour générer efficacement de manière dynamique des implémentations sous-classées de votre Objets (bien que je pense qu'il puisse être configuré d'utiliser cglib aussi).

S'il n'étaient pas proxé de cette manière, il serait presque impossible de mettre en œuvre une chargement paresseux sans soudure.

Je ne me souviens pas du haut de la tête si vous utilisez un chargement impatient, si l'objet naturel serait renvoyé à la place. Je ne recommanderais généralement pas d'utiliser un chargement impatient, bien que surtout si vous avez de nombreuses entités d'enfants liées, car il peut bientôt être un goulot d'étranglement énorme de performance, car il sucer chaque objet lié à la mémoire.

De plus, si vous devez faire la discrimination sur le type de classe, plutôt que d'utiliser obj.getclass () , utilisez hibernate.getclass (obj) qui vous donnera La classe d'objet naturelle, que ce soit le proxé ou non: voir l'hibernate API Javadocs ici .


2 commentaires

Eh bien, l'objet est chargé avec impatience et car je reçois un objet proxy dans cet appel particulier, je suppose que vous ne pouvez pas garantir que l'objet sera soit. Fait intéressant, lorsque j'appelle Dao.Gettuser (Nom d'utilisateur String) de la méthode A, je reçois l'objet utilisateur mais à partir de la méthode B appelant la méthode dans le même manoir, je reçois le proxy.


Habituellement, le problème est que le proxy est retourné de cette manière n'est pas initialisé correctement; Sinon, s'il était rempli correctement, les choses auraient dû passer normalement. Tout le monde sait pourquoi la méthode de la recherche peut renvoyer un proxy non initialisé?



3
votes

À mon avis, cette expression:

@Entity
class X {
    @ManyToOne(fetch = FetchType.LAZY)
    private User user;
}


0 commentaires