HibernateSession refresh provoque UnresolvableObjectException

4 janvier 2009 par: Benoit Bonneville

HibernateSession Refresh() entraine org.hibernate.UnresolvableObjectException: No row with the given identifier exists: [MyObject#0], cette erreur vous ennuies ? Vous utilisez hibernate avec le mapping d’objet relationnel. Mais lorsque que vous raffraichissez un objet (refresh) vous obtenez cette Exception ?

Mise en situation

Vous utilisez le framework d’objet relationnel Hibernate.
Vous travaillez sur un objet qui à certainement été crée par

new MyObject()

l’erreur obtenue est la suivante :

[org.hibernate.UnresolvableObjectException|tag:org.hibernate.UnresolvableObjectException]: [No row with the given identifier exists|tag:No row with the given identifier exists]: [MyObject#0]
at org.hibernate.UnresolvableObjectException.throwIfNull(UnresolvableObjectException.java:65)
at org.hibernate.event.def.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:148)
at org.hibernate.event.def.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:62)
at org.hibernate.impl.SessionImpl.fireRefresh(SessionImpl.java:929)
at org.hibernate.impl.SessionImpl.refresh(SessionImpl.java:913)

Je dis cela car le #0 situé à la fin de la première ligne signifie que l’objet n’a pas encore d’identifiant (id = 0).
Si ce n’est pas votre cas, cette solution n’est peu être pas pour vous, mais je vous conseil de la lire quand même.

Vous utilisez la fonction refresh de la session hibernate sur cette objet.

Sachant que vous avez optez pour la stratégie la plus courante, de génération des identifiants des objets par incrémentions.

La non persistance (première solution)

Soit l’objet session, votre session hibernate (surement la classe :org.hibernate.impl.SessionImpl)
Soit l’objet myObject, un objet de la class MyObject, qui est un objet relationnel qui correspond à une table en base de donnée.

Vous n’avez pas utilisez :

   * session.save(myObject)
* session.saveOrUpdate(Myobjet)

Et donc votre objet n’est pas passez à l’état persistant.
Il n’est pas encore enregistré dans votre base de donnée.

Vous ne pouvez donc pas « refresh », ce qui signifie recharger les données de la base de donnée, vu que ces données n’y sont pas encore insérées.

L’identifiant de l’objet est mal généré (deuxième solution)

L’objet que vous avez « refresh » à bel et bien été sauvegardé et dans votre base de donnée, la ligne est bien insérée.
Si vous charger une autre page web, ou tout autre script, les données sont les bonnes.
Pourtant le refresh de l’objet bien sauvegarder provoque une erreur, c’est parce que :

Vous avez oublié dans votre mapping XML de votre objet.

<generator class="increment"/>

API de référence

ou dans votre mapping par annotation :

@GeneratedValue(strategy = GenerationType.AUTO)

API de référence

Quand vous sauvegarder votre objet dans votre base de donnée, qui elle est en « auto_increment ».

Donc quand Hibernate sauvegarde l’objet par une requette Mysql INSERT, il ne sait pas qu’il doit mettre à jour l’identifiant de l’objet après l’insertion! vous conservez donc un 0, qui n’est donc pas la bonne valeur actuellement stoquée.

Par contre tout les scripts exécutés ultérieurement, chargerons l’objet par une requête SELECT. Ce qui donnera un objet avec un identifiant correct, différent de 0.
Seul le code qui utilise la même session, que celle qui a créée l’objet, ne pourra pas le rafraichir.

Filed under: Non classé

Répondre