Les requêtes avec Hibernate 4

Tuto : comment faire des requêtes avec Hibernate 4
Florent TRIPIERMis à jour le 2 Oct 2013

Hibernate 4 propose une syntaxe structurée qui permet dexploiter la plupart des fonctionnalités du SQLLangage permettant de communiquer avec une base de données.. Cette syntaxe sarticule autour de quelques classes clés.

Les classes clés pour construire une requête

EntityManager

LEntityManager vous donne accès à votre PersistenceUnit, cest-à-dire à votre base de données. Cest donc à partir de lui que seront construits tous les objets suivants. La configuration de la PersistenceUnit fera lobjet dun autre article.

CriteriaBuilder

Le CriteriaBuilder est généré par lEntityManager. Il ne correspond à aucun élément dune requête, mais cest une boîte à outil pour construire des requêtes.

CriteriaQuery

Il sagit de la requête à proprement parler. Elle est instanciée par le CriteriaBuilder. Notez quil sagit dune classe typée : son type doit être le type de retour de votre requête.

Root

Cest la clause FROM de votre requête SQL. Cest donc là encore un objet typé, à la différence que T doit impérativement être une @Entity, cest-à-dire que la classe indiquée doit correspondre à une table dans votre schéma de base de données.

TypedQuery

Il sagit dun objet qui encapsule lexécution de la requête. Son type doit donc impérativement être le même que celui de la CriteriaQuery (alors quil peut être différent de celui du Root).

La construction de la requête

Premier exemple

Prenons un exemple très simple : imaginons que jai une table utilisateur dans ma base de données, jai donc une @Entity Utilisateur. Je souhaite lister tous mes utilisateurs, je vais donc réaliser la requête « SELECT * FROM utilisateur; » avec Hibernate 4.

Ici, nous ne nous soucierons pas de comment obtenir lEntityManager. Cela fera lobjet dun autre article, nous admettrons que nous avons un objet EntityManager appelé entityManager. Le code pour réaliser notre requête est alors :

{{< highlight java >}} // Je cree une instance de CriteriaBuilder a partir de mon EntityManager CriteriaBuilder builder = entityManager.getCriteriaBuilder(); // Je cree une requete qui me retournera des objets Utilisateur CriteriaQuery< utilisateur> criteriaQuery = builder.createQuery(Utilisateur.class); // Je cree ma clause FROM sous forme d un objet Root Root< utilisateur> root = criteriaQuery.from(Utilisateur.class); // J indique la valeur de la clause SELECT criteriaQuery.select(root); // Je cree une TypedQuery pour l execution de ma requete TypedQuery< utilisateur> typedQuery = entityManager.createQuery(criteriaQuery); // J execute ma requete et je recupere le resultat dans une Collection List< utilisateur> result = typedQuery.getResultList();< /utilisateur>< /utilisateur>< /utilisateur>< /utilisateur>{{< /highlight >}}

Les 5 classes citées plus haut interviennent dans ce code. Quelques commentaires :

  • La requête retourne le type Utilisateur : cela correspond bien à toutes les colonnes de la table utilisateur, cest-à-dire « * FROM utilisateur » ;
  • lobjet Root est obtenu à partir de la CriteriaQuery : en effet, il sagit de la clause FROM de cette requête en particulier. Ce détail sera important lorsque vous aurez des sous-requêtes.
  • la TypedQuery est, elle, obtenue à travers lEntityManager : en effet, cet objet ne fait quexécuter la CriteriaQuery, or cette requête est bien exécutée sur le schéma représenté par lEntityManager.

Deuxième exemple

Reprenons lexemple précedent, mais cette fois nous ne voulons que le nom des utilisateurs. Notre requête SQL est donc « SELECT nom FROM utilisateur ».

Le code est le suivant :

{{< highlight java >}} CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery< string> criteriaQuery = builder.createQuery(String.class); Root< utilisateur> root = criteriaQuery.from(Utilisateur.class); criteriaQuery.select(root.get(Utilisateur_.nom)); TypedQuery< string> typedQuery = entityManager.createQuery(criteriaQuery); List< string> result = typedQuery.getResultList();< /string>< /string>< /utilisateur>< /string>{{< /highlight >}}

Il y a deux différences :

  • jindique en paramètre de la fonction select() le champ du metamodel de la classe Utilisateur qui correspond au champ que je veux récupérer ;
  • le type de la CriteriaQuery et de la TypedQuery ne sont plus Utilisateur mais String puisque cest bien un String que je souhaite obtenir.

Nous verrons dans dautres articles comment récupérer plusieurs champs ou encore comment utiliser des fonctions telles que sum() ou count() dans la clause SELECT.

 

[wp-simple-survey-1]