Hibernate : différence entre get() et load()
Par Masclet le mercredi 13 octobre 2010, 14:12 - Hibernate - Lien permanent
Si vous êtes un utilisateur d'Hibernate, que ce soit avec Spring ou pas,
vous êtes vous déjà posé la question de savoir quelles sont les différences
entre session.load() et session.get(). Comprendre les
différences permet souvent d'optimiser les accès à la base de données.
En effet les signatures des deux méthodes sont assez proches et permettent toutes les deux de récupérer une entité via sa clé. Voici donc les différences :
get()renvoienullsi l'objet n'existe pas, tandis queload()lève une objectNotFoundException. Ce qui veux dire que le fait que l'objet n'existe pas est considérer comme une erreur applicative. Il faut donc utiliserload()si tel est le cas. Par contre la javadoc est claire :You should not use this method to determine if an instance exists (use get() instead)
. en résumé n'en faites pas une utilisation détournée ;)
- La deuxième différence est structurelle. Lorsque vous faites un
get(), vous récupérez l'objet avec ses champs chargés (en fonction des attributslazy, cela va sans dire). En revanche lorsque vous faites unload, Hibernate vous renvoie un proxy que sera initialisé lors de l'appel à un champs ou a un getter. Si la session est fermé, vous aurez alors uneLazyInitializationException:
session.beginTransaction(); User user=(User) session.load(User.class, new Long(1)); session.getTransaction().commit(); user.getPassword();//=>LazyInitializationException
Vous n'auriez pas eu cette exception si vous auriez utilisé
get()
La question qui vient alors à l'esprit est "si on ne doit pas utiliser
load() pour tester l'existence d'un objet, et que les champs ne
sont pas initialisés, quand utilisez load()?"
En fait, la réponse découle du modèle relationnel du SQL : lorsque vous
avez une association OneToMany cela se traduit pas une relation de
clé primaire / étrangère. Chose qui n'existe pas dans le modèle Objet (d'où
l'intérêt d'Hibernate ;) ). pour associer un objet en SQL il suffit uniquement
de connaitre la clé primaire de l'objet associé. et c'est là qu'intervient
l'utilité de load(). Nous n'avons besoin que de sa clé, pas des
champs. voici un exemple de code :
Session session = getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); User owner = session.get( User.class, 1 );//un appel Car car = session.get( Car.class, 2 );//deux appel owner.setCar(car);//un save tx.commit(); session.close();
Cela fait deux appels à la database + un save (pas de cache dans notre exemple). En revanche :
Session session = getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); User owner = session.load( User.class, 1 ); Car car = session.get( Car.class, 2 );//un appel owner.setCar(car);//un update tx.commit(); session.close();
Nous avons économisé un appel à la base.
à vos refactoring :)