La première chose à savoir c'est que l'unité de travail dans Hibernate, ce qui nous sert à accéder à la base de données, c'est la « Session ». Une Session dans Hibernate et le « Persistence Manager », nous l'utilisons pour mettre et récupérer des données depuis la base. Pour récupérer une Session, nous le faisons grâce à la SessionFactory comme cela :
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Une SessionFactory ne devrait être généralement construite qu'une seule fois, par exemple avec une servlet chargée au démarrage, grâce à un « load-on-startup » dans le Web.xml, et elle doit aussi être un genre de « singleton ». Nous allons créer une classe utilitaire qui va résoudre les deux problèmes, elle vient directement de la documentation de Hibernate.
Faites un clic-droit sur votre projet, puis « new » et « java class.. » et recopiez le code ci dessous :
package com.bourzeix.hibernate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.*; import org.hibernate.cfg.*; public class HibernateUtil { private static Log log = LogFactory.getLog(HibernateUtil.class); private static final SessionFactory sessionFactory; static { try { // Create the SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed log.error("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static final ThreadLocal session = new ThreadLocal(); public static Session currentSession() { Session s = (Session) session.get(); // Open a new Session, if this Thread has none yet if (s == null) { s = sessionFactory.openSession(); session.set(s); } return s; } public static void closeSession() { Session s = (Session) session.get(); if (s != null) s.close(); session.set(null); } }
Voilà, maintenant nous allons pouvoir utiliser Hibernate dans une servlet, afin de manipuler directement des objets contenant les données de notre base.
Faites « New -> Servlet ... » dans Netbeans, et créez une servlet « TestServlet » avec un mapping dans la configuration (le Web.xml) tel que « /testservlet ». Vérifiez qu'elle fonctionne et qu'elle affiche quelque chose (dé-commentez le passage « TODO output your page here » créé par défaut).
Importez en suite les packages suivants, nous en aurons besoin :
import com.bourzeix.hibernate.HibernateUtil; import com.bourzeix.hibernate.User; import java.io.*; import java.util.Iterator; import javax.servlet.*; import javax.servlet.http.*; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
Ensuite déclarez votre Session et votre Transaction Hibernate, ce sont les objets dont nous allons nous servir pour accéder à nos données :
Session session; Transaction tx;
La première étape maintenant va donc être d'ajouter quelque chose dans notre base afin de pouvoir le lire par le suite, nous allons donc créer un utilisateur avec l'ajout du code suivant à notre servlet :
//Creation de notre objet Session grace à notre HibernateUtil session = HibernateUtil.currentSession(); //Ouverture de notre transaction avec Hibernate grace // a la session tx = session.beginTransaction(); // Ajout d'un utilisateur en utilisant notre bean User // préalablement configuré dans Hibernate User toto = new User(); toto.setNom("lateteatoto"); toto.setPrenom("toto"); // On sauve, on renvoi, notre bean à la session Hibernate session.save(toto); // Nous commitons la transaction vers la base tx.commit(); //Enfin on ferme la session HibernateUtil.closeSession();
Appelez ensuite plusieurs fois votre servlet dans votre navigateur préféré, Firefox au hasard, et si tout se passe bien ouvrez votre BDD pour voir si vos utilisateur sont bien là.
Normalement vous devriez en avoir autant que de « refresh » tous avec le même nom et le même prénom, mais l'identifiant lui est bien différent et a bien été géré automatiquement par Hibernate grâce à la configuration de notre objet « User », souvenez vous, c'est là, dans le fichier « user.hbm.xml » :
<id name="id" type="int" column="id" unsaved-value="0"> <generator class="identity"/> </id>
Voilà, maintenant que nous avons des utilisateurs dans notre base nous allons pouvoir les sélectionner et les afficher grâce à notre servlet. Commencez par commenter le code précédent, celui qui a servi à la création des utilisateurs puis copiez le code ci dessous :
session = HibernateUtil.currentSession(); tx = session.beginTransaction(); Query query = session.createQuery("from User u"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>Servlet TestServlet</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Servlet TestServlet at " + request.getContextPath() + "</h1>"); for (Iterator it = query.iterate(); it.hasNext();) { User user = (User) it.next(); out.println("<p>"); out.println("Id : " + user.getId() ); out.println("Nom : " + user.getNom() ); out.println("Prénom : " + user.getPrenom() ); out.println("</p>"); } out.println("</body>"); out.println("</html>"); tx.commit(); HibernateUtil.closeSession(); out.close();
Ici, comme dans l'exemple précédent nous récupérons notre « session » puis nous commençons notre « transaction ». Ensuite nous créons un objet « Query » grâce auquel nous faisons notre requête, notez d'ailleurs qu'Hibernate supporte des requêtes simplifiées à l'extrême, nous aurions pu écrire « select * from User u » c'est pareil. Pour plus d'informations voyez le chapitre « Querying » de la documentation Hibernate.
Ensuite nous utilisons une itération pour boucler sur les résultats de notre requête, nous créons un objet User à chaque passage et nous utilisons simplement ses « getters » pour lire et afficher les valeurs. Nous fermons ensuite notre page HTML ainsi que toutes les connections et objets ouverts. Si tout c'est passé selon le plan vous devriez avoir, en fonction des données entrées dans la base quelque chose comme cela :
Servlet TestServlet at /test Id : 1 Nom : lateteatoto Prénom : toto Id : 2 Nom : lateteatoto Prénom : toto Id : 3 Nom : lateteatoto Prénom : toto Id : 4 Nom : lateteatoto Prénom : toto Id : 5 Nom : lateteatoto Prénom : toto Id : 6 Nom : lateteatoto Prénom : toto
Et voilà vous devriez maintenant en savoir assez sur Hibernate pour pouvoir continuer à explorer, la prochaine fois nous ajouterons la dernière brique à l'édifice : Struts !
A suivre ...
1 De Laurent Forêt -
Bon on le met quand en pratique ce savoir faire? L'idée d'une webapp de blog est partie ? Je vais avoir un peu de temps en Août pour un projet, pourquoi pas celui là !
2 De Da Bourz -
Je commence maintenant !!
Aller c'est parti !! Si il y a d'autre volontaires ...
3 De Laurent Forêt -
Je te propose que l'on commence à en discuter par mail !
spammed@laurentforet.org
4 De DealWith -
salut, j'ai fait par deux fois ton tutorial, très clair et précis (j'ai hibernate 3 et netbeans 4.1). J'ai néanmoins un problème qui se répète à chaque fois: quand je lance ma servlet (Run File), il s'affiche l'erreur suivante :
java.lang.ExceptionInInitializerError
Et si je fais un refresh sur le browser j'ai :
java.lang.NoClassDefFoundError
Qu'est-ce que j'ai manqué ?
Merci
5 De DealWith -
Bon, Ok... Mon fichier User.hbm.xml était mal branlé par rapport à la définition de ma table users. Faire une classe Test.java m'a permis de débuggué plus facilement qu'avec la servlet. A part cela encore bravo pour le tuto.
6 De Da Bourz -
Top que tu ai trouvé tout seul !
Désolé de ne pas avoir aidé, j'étais un peu débordé et pas là ....
Tu nous l'envoi ta classe "Test" que je la rajoute à l'article ?
7 De jsl1 -
merci pour ces tutos très clair.
j'attends avec impatience l'intégration avec struts
bon courage
8 De PG -
Bonjour, j ai exactement le mem probleme que DealWith. Mais j'arrive pas a le corriger.
Je cree donc une classe ou je mets les instructions de la servlet dans un main.
je run et j'obtiens l erreur :
java.lang.ExceptionInInitializerError
at User_hibernate.HibernateUtil.<clinit>(HibernateUtil.java:26)
at Test.main(Test.java:21)
Caused by: org.hibernate.HibernateException: Could not find datasource
Si quelqun pouvait m'aider parce que j aimerai bien aller au bout de ce tutorial
9 De PG -
Bon j ai trouver, mon id champ dans mysql table n avait pas l option auto-increment.
Du coup ca faisait tout planter.
10 De Scavenger -
Ah non je proteste... Pourquoi pas JSF à la place de struts pour la suite ?!?
11 De Scavenger -
Et avec des JSP à la place des servlets c'est possible ? Comment doit-on alors configurer le tout ?
12 De Da Bourz -
"Mettre la couche applicative dans les JSP c'est Mal" (tm) !
13 De Scavenger -
Oui, ma question était mal formulée : peut-on créer des JSP, qui généreront elles-mêmes les servlets, à la manière de Sun Java Studio Creator ? Si oui, comment doit-on configurer la chose ?
14 De Scavenger -
La réponse est sur le site de Sun. On y parle de couche Web, et de couche client, ainsi que du rôle propre aux servlets et aux JSP :
java.sun.com/blueprints/g...
15 De Scavenger -
Pour ma part j'y préfère le paragraphe 4.2.6.2 ....
16 De dolphline -
super ce que tu fais. Bon courage et continue
17 De mitso -
ton article est tres tres supppper...
stp pour le 'u' signifie koi ici "from User u"...??
et pour la suite tu peux resaliser deux exo un avec struts et l'autre avec JSF, merci d'avance
18 De Scavenger -
J'ai également l'erreur de DealWith, mais lorsque je debugge mon programme, il apparaît que c'est l'ouverture de session Hibernate qui plante... Le fait d'utiliser JSF change-t-il quelque chose par rapport à la façon de procéder pour accéder à la BD ?
Merci
19 De Scavenger -
Problème de PlainSocket apparemment... Pourtant j'ai suivi les directives de la partie I, mon pool est correctement configuré, puisque je peux accéder à la base directement par le biais d'une JSP...
20 De ziko -
bon;mais dois-t-on mettre ca avec servlets?
il faux informer les autres que ca ne marche pas sauf si on veux apprendre les premiers pas vers hiberate!
21 De seb -
Bonjour,
Tout d'abord merci pour le tuto qui est génial (je débute un stage de 3 mois dans lequel je dois faire une appli JEE, donc là je teste les différentes méthodes).
J'ai par contre une erreur que je n'arrive pas à résoudre, elle se passe au moment ou on execute le code situé dans la servlet, qui sert à créer les Users dans la table.
J'ai une première exception dans le browser :
javax.servlet.ServletException: L'exécution de la servlet a lancé une exception
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)
cause mère
java.lang.ExceptionInInitializerError
com.seb.hibernate.HibernateUtil.<clinit>(HibernateUtil.java:33)
TestServlet.processRequest(TestServlet.java:42)
TestServlet.doGet(TestServlet.java:85)
et elle change un peu si je refresh le browser :
javax.servlet.ServletException: L'exécution de la servlet a lancé une exception
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)
cause mère
java.lang.NoClassDefFoundError
TestServlet.processRequest(TestServlet.java:42)
TestServlet.doGet(TestServlet.java:85)
à en croire la première exception, cela viens de cette ligne dans HibernateUtil.java :
sessionFactory = new Configuration().configure().buildSessionFactory();
J'éspère que vous pourrez m'aider, merci d'avance.
22 De kaikai -
salut,
merci pour ce tuto. Mais on reste sur notre faim. On attends l'étape avec struts...
23 De da Bourz -
Ca va viendre, ca va viendre, c'est juste qu'en ce moment je fais pas trop de Java à la maison, je m'y met cette semaine !
Patience !!
24 De chamalow -
salut,
super ce tuto, mais j'attends vraiment la suite
c'est ce qui m'interesse et il n'y a pas d'autre site qui en parle
alors s'iouplait
25 De jo -
bravo! e merci!
26 De sawal -
Salut,
où doit-on mettre EXACTEMENT (c'est à dire dans quelle méthode) le code permettant d'écrire dans la base. je suis bloqué depuis des jours.
27 De da Bourz -
Dans la servlet testServlet :
//Creation de notre objet Session grace à notre HibernateUtil
session = HibernateUtil.currentSession();
//Ouverture de notre transaction avec Hibernate grace
// a la session
tx = session.beginTransaction();
// Ajout d'un utilisateur en utilisant notre bean User
// préalablement configuré dans Hibernate
User toto = new User();
toto.setNom("lateteatoto");
toto.setPrenom("toto");
// On sauve, on renvoi, notre bean à la session Hibernate
session.save(toto);
// Nous commitons la transaction vers la base
tx.commit();
//Enfin on ferme la session
HibernateUtil.closeSession();
Voir plus haut ...
28 De Toon -
Bonjour,
J'aimerais bien savoir comment faire avec HibernateUtil pour se connecter à deux bases de données différentes...?
Merci
29 De Toon -
Je précise:
J'ai trouvé deux choses pour l'utilisation de multiples bases de données (sur www.hibernate.org):
- "Si vous avez plusieurs base de données, utilisez plusieurs configurations <session-factory>, généralement dans des fichiers de configuration différents"
- " Une SessionFactory est responsable d'une base de données et n'accepte qu'un seul fichier de configuration XML (hibernate.cfg.xml)"
Comment dois-je gérer les multiples fichiers xml de confs de mes bases de données alors que la sessionFactory n'en accepte qu'un seul ?!
30 De Toon -
Trouvé:
En fait il suffit de passer le nom du fichier xml dans
new Configuration().configure("monfichier.cfg.xml").build...
31 De mirela -
c'est pour bientôt la partie struts???!!!
32 De Da Bourz -
Oui !!!
33 De jemil -
continuer c'est interessant, Merci pour vos efforts
34 De maxime -
Très bonne série de Tutos, Félicitations!!
35 De le fou -
juste pour le plaisir, 3 ans et demi plus tard
PS : Du code HTMl dans une servlet !!! même en 2005 ça passe pas :-S
36 De Da Bourz -
@le Fou : C'est pour la démo !
37 De Seliwa -
salut por tou le monde,
j'ai un prob dans l'hibernate ne s'exucute pas ilya des erreus et le session je ne pas bien comprendre .svp est ce que quelqu'un me aider j'ai trrrrrrop perdu .je travail par netbeans 6.7.1 et bd postgres
les erreus :
Deployment error:
Tomcat configuration file C:\Program Files\NetBeans 6.7.1\Projects\test\web\META-INF\context.xml seems to be broken. Please make sure it is parseable and valid.
See the server log for details.
at org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment.deploy(Deployment.java:224)
at org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment.deploy(Deployment.java:132)
at org.netbeans.modules.j2ee.ant.Deploy.execute(Deploy.java:103)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor423.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
at org.apache.tools.ant.module.bridge.impl.BridgeImpl.run(BridgeImpl.java:278)
at org.apache.tools.ant.module.run.TargetExecutor.run(TargetExecutor.java:497)
at org.netbeans.core.execution.RunClassThread.run(RunClassThread.java:151)
Caused by: org.netbeans.modules.j2ee.deployment.common.api.ConfigurationException: Tomcat configuration file C:\Program Files\NetBeans 6.7.1\Projects\test\web\META-INF\context.xml seems to be broken. Please make sure it is parseable and valid.
at org.netbeans.modules.tomcat5.config.TomcatModuleConfiguration.getContext(TomcatModuleConfiguration.java:173)
at org.netbeans.modules.tomcat5.config.TomcatModuleConfiguration.getDatasources(TomcatModuleConfiguration.java:198)
at org.netbeans.modules.j2ee.deployment.config.ConfigSupportImpl.getDatasources(ConfigSupportImpl.java:341)
at org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider.getModuleDatasources(J2eeModuleProvider.java:201)
at org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment.deploy(Deployment.java:160)
... 17 more
Caused by: java.lang.RuntimeException: DOM graph creation failed: org.netbeans.modules.schema2beans.Schema2BeansRuntimeException: Failed to create the XML-DOM Document. Check your XML to make sure it is correct.
The markup in the document following the root element must be well-formed.
at org.netbeans.modules.tomcat5.config.gen.Context.createGraph(Context.java:3177)
at org.netbeans.modules.tomcat5.config.gen.Context.createGraph(Context.java:3161)
at org.netbeans.modules.tomcat5.config.TomcatModuleConfiguration.getContext(TomcatModuleConfiguration.java:166)
... 21 more
BUILD FAILED (total time: 2 seconds)
cet l'erreur du TestServlet ....Merci bien de me repondre ....MERCi de m'aider. C urgent je suis en pfe jusqu'a maitenant cava pas des tou j'ai pas reussit de execute une jsp ,hibernate ,servlet.....