From hibernate-commits at lists.jboss.org Wed Jun 10 13:28:55 2009 Content-Type: multipart/mixed; boundary="===============7507922504910344565==" MIME-Version: 1.0 From: hibernate-commits at lists.jboss.org To: hibernate-commits at lists.jboss.org Subject: [hibernate-commits] Hibernate SVN: r16742 - core/branches/Branch_3_3/documentation/manual/src/main/docbook/en-US/content. Date: Wed, 10 Jun 2009 13:18:14 -0400 Message-ID: --===============7507922504910344565== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Author: steve.ebersole(a)jboss.com Date: 2009-06-10 13:18:13 -0400 (Wed, 10 Jun 2009) New Revision: 16742 Modified: core/branches/Branch_3_3/documentation/manual/src/main/docbook/en-US/con= tent/tutorial.xml Log: HHH-3953 - Update tutorial chapter Modified: core/branches/Branch_3_3/documentation/manual/src/main/docbook/en= -US/content/tutorial.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/branches/Branch_3_3/documentation/manual/src/main/docbook/en-US/co= ntent/tutorial.xml 2009-06-10 17:17:48 UTC (rev 16741) +++ core/branches/Branch_3_3/documentation/manual/src/main/docbook/en-US/co= ntent/tutorial.xml 2009-06-10 17:18:13 UTC (rev 16742) @@ -27,25 +27,17 @@ ]> = - - - Introduction to Hibernate - = - - Preface + Tutorial = - - Intended for new users, this chapter provides an introduction = to Hibernate - The chapter provides a step-by-step tutorial, starting with a simple - application using an in-memory database. The tutorial is - based on an earlier tutorial developed by Michael Gloegl. All - code is contained in the tutorials/web di= rectory - of the project source. - + + Intended for new users, this chapter provides an step-by-step intr= oduction + to Hibernate, starting with a simple application using an in-memor= y database. The + tutorial is based on an earlier tutorial developed by Michael Gloe= gl. All + code is contained in the tutorials/web direct= ory of the project + source. + = - - This tutorial expects the user have knowledge of both Java and @@ -57,11 +49,9 @@ = - There is another tutorial/example application in the - /tutorials/eg directory of the project so= urce. - That example is console-based and, as such, would not have the - dependency on a servlet container to execute. The basic setup= is - the same as the instructions below. + The distribution contains another example application under + the tutorial/eg project source + directory. = @@ -70,34 +60,56 @@ = For this example, we will set up a small database application = that can store - events we want to attend, and information about the host(s) of - these events. Although you can use whatever database you feel= comfortable using, we will use an in-memory, Java database named HSQLDB - to avoid describing installation/setup of any particular datab= ase - servers. = + events we want to attend and information about the host(s) of = these events. - = - - The first thing we need to do is set up the development enviro= nment, - including all the required dependencies to Hibernate, - as well as other libraries. Hibernate is built using Maven wh= ich, = - amongst other features, provides dependency managemen= t; - moreover it provides transitive - dependency management, which simply means t= hat by using - Hibernate we can define our dependency on Hibernate. Hibernate - itself defines the dependencies it needs which then become tra= nsitive - dependencies of our project. - = - + + Although you can use whatever database you feel comfortabl= e using, we + will use HSQLDB = (an in-memory, + Java database) to avoid describing installation/setup of a= ny particular + database servers. + + + + + Setup + + + The first thing we need to do is to set up the development= environment. We + will be using the "standard layout" advocated by alot of b= uild tools such + as Maven. Maven, = in particular, has a + good resource describing this layout. + As this tutorial is to be a web application, we will be cr= eating and making + use of src/main/java, src/m= ain/resources + and src/main/webapp directories. + + + + We will be using Maven in this tutorial, taking advantage = of its + transitive dependency management capabilities as well as t= he ability of + many IDEs to automatically set up a project for us based o= n the maven descriptor. + + + = - ... + 4.0.0 = + org.hibernate.tutorials + hibernate-tutorial + 1.0.0-SNAPSHOT + First Hibernate Tutorial + + + + ${artifactId} + + - ${groupId} + org.hibernate hibernate-core = @@ -106,34 +118,52 @@ javax.servlet servlet-api + + + + org.slf4j + slf4j-simple + + + + + javassist + javassist + = ]]> = - - - Essentially we are describing here the - /tutorials/web/pom.xml file. See the - Maven site for mor= e information. - - + + + It is not a requirement to use Maven. If you wish to = use something else to + build this tutoial (such as Ant), the layout will rema= in the same. The only + change is that you will need to manually account for a= ll the needed + dependencies. If you use something like Ivy + providing transitive dependency management you would s= till use the dependencies + mentioned below. Otherwise, you'd need to grab all + dependencies, both explicit and transitive, and add th= em to the project's + classpath. If working from the Hibernate distribution= bundle, this would mean + hibernate3.jar, all artifacts in = the + lib/required directory and all fi= les from either the + lib/bytecode/cglib or l= ib/bytecode/javassist + directory; additionally you will need both the servlet= -api jar and one of the slf4j + logging backends. + + = - - While not strictly necessary, most IDEs have integration w= ith Maven - to read these POM files and automatically set up a project= for you. + Save this file as pom.xml in the proj= ect root directory. - + = - - Next, create a class that represents the event you want to sto= re in the database. - - = + The first class = - The first persistent class is a simple JavaBean class with= some properties: + Next, we create a class that represents the event we want = to store in the + database; it is a simple JavaBean class with some properti= es: = This class uses standard JavaBean naming conventions for p= roperty - getter and setter methods, as well as private visibility f= or the fields. Although this is - a recommended design, it is not required. Hibernate can al= so access fields directly, - the benefit of accessor methods is robustness for refactor= ing. The no-argument - constructor is required to instantiate an object of this c= lass through reflection. + getter and setter methods, as well as private visibility f= or the + fields. Although this is the recommended design, it is no= t required. + Hibernate can also access fields directly, the benefit of= accessor + methods is robustness for refactoring. = - The id property holds a unique identifi= er value for a particular event. - All persistent entity classes (there are less important de= pendent classes as well) will need - such an identifier property if we want to use the full fea= ture set of Hibernate. In fact, - most applications, especially web applications, need to di= stinguish objects by identifier, so you - should consider this a feature rather than a limitation. H= owever, we usually do not manipulate - the identity of an object, hence the setter method should = be private. Only Hibernate will assign - identifiers when an object is saved. Hibernate can access = public, private, - and protected accessor methods, as well as public, private= and protected fields directly. The - choice is up to you and you can match it to fit your appli= cation design. + The id property holds a unique identifi= er value + for a particular event. All persistent entity classes (th= ere are + less important dependent classes as well) will need such a= n identifier + property if we want to use the full feature set of Hiberna= te. In fact, + most applications, especially web applications, need to di= stinguish + objects by identifier, so you should consider this a featu= re rather + than a limitation. However, we usually do not manipulate = the identity + of an object, hence the setter method should be private. = Only Hibernate + will assign identifiers when an object is saved. Hibernat= e can access + public, private, and protected accessor methods, as well a= s public, + private and protected fields directly. The choice is up t= o you and + you can match it to fit your application design. = - The no-argument constructor is a requirement for all persi= stent classes; Hibernate - has to create objects for you, using Java Reflection. The = constructor can be - private, however, package visibility is required for runti= me proxy generation and - efficient data retrieval without bytecode instrumentation. + The no-argument constructor is a requirement for all persi= stent + classes; Hibernate has to create objects for you, using Ja= va + Reflection. The constructor can be private, however packa= ge or public + visibility is required for runtime proxy generation and ef= ficient data + retrieval without bytecode instrumentation. = - Place the Java source file in a directory called = src in the - development folder, and in its correct package. The direct= ory should now look like this: + Save this file to the src/main/java/org/hibernat= e/tutorial/domain + directory. - - -+src - +events - Event.java]]> - - - In the next step, we tell Hibernate about this persistent = class. - - = = The mapping file = - Hibernate needs to know how to load and store objects of t= he persistent class. - This is where the Hibernate mapping file comes into play. = The mapping file - tells Hibernate what table in the database it has to acces= s, and what columns - in that table it should use. + Hibernate needs to know how to load and store objects of t= he + persistent class. This is where the Hibernate mapping file + comes into play. The mapping file tells Hibernate what tab= le in + the database it has to access, and what columns in that ta= ble + it should use. = @@ -237,25 +260,28 @@ "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> = - + [...] ]]> = - Hibernate DTD is sophisticated. You can use it for - auto-completion of XML mapping elements and attributes in = your editor or - IDE. Opening up the DTD file in your text editor is the - easiest way to get an overview of all elements and attribu= tes, and to view - the defaults, as well as some comments. Hibernate will not - load the DTD file from the web, but first look it up from = the classpath - of the application. The DTD file is included in h= ibernate3.jar - as well as in the src/ directory of the= Hibernate distribution. + Hibernate DTD is sophisticated. You can use it for auto-c= ompletion + of XML mapping elements and attributes in your editor or I= DE. + Opening up the DTD file in your text editor is the easiest= way to + get an overview of all elements and attributes, and to vie= w the + defaults, as well as some comments. Hibernate will not lo= ad the + DTD file from the web, but first look it up from the class= path of + the application. The DTD file is included in + hibernate-core.jar (it is also includ= ed in the + hibernate3.jar, if using the distribu= tion bundle). = - - We will omit the DTD declaration in future examples to sho= rten the code. It is, - of course, not optional. - + + + We will omit the DTD declaration in future examples to= shorten the code. It is, + of course, not optional. + + = Between the two hibernate-mapping tags,= include a @@ -264,25 +290,27 @@ a mapping to a table in the SQL database: = - + = - + = = ]]> = - So far we have told Hibernate how to persist and load obje= ct of class Event - to the table EVENTS. Each instance is n= ow represented by a row in that table. - Now we can continue by mapping the unique identifier prope= rty to the tables primary key. - As we do not want to care about handling this identifier, = we configure Hibernate's + So far we have told Hibernate how to persist and load obje= ct of + class Event to the table + EVENTS. Each instance is now represente= d by a + row in that table. Now we can continue by mapping the uni= que + identifier property to the tables primary key. As we do n= ot want + to care about handling this identifier, we configure Hiber= nate's identifier generation strategy for a surrogate primary key= column: = - + = - + @@ -291,29 +319,43 @@ ]]> = - The id element is the declaration of th= e identifier property, - name=3D"id" declares the name of the Ja= va property. - Hibernate will use the getter and setter methods to access= the property. - The column attribute tells Hibernate which column of the - EVENTS table to use for this primary ke= y. The nested - generator element specifies the identif= ier generation strategy. - = - In this case you used native, which selects the best = strategy depending - on the configured database dialect. Hibernate supports dat= abase generated, globally - unique, as well as application assigned, identifiers. Hibe= rnate supports any strategy you have written - an extension for. + The id element is the declaration of the + identifier property. The name=3D"id" m= apping + attribute declares the name of the JavaBean property and t= ells + Hibernate to use the getId() and + setId() methods to access the property.= The + column attribute tells Hibernate which column of the + EVENTS table holds the primary key valu= e. = - Finally, include declarations for the persistent propertie= s of the class in - the mapping file. By default, no properties of the class a= re considered + The nested generator element specifies = the + identifier generation strategy (aka how are identifier val= ues + generated?). In this case we choose native, + which offers a level of portability depending on the confi= gured + database dialect. Hibernate supports database generated, = globally + unique, as well as application assigned, identifiers. Ide= ntifier + value generation is also one of Hibernate's many extension= points + and you can plugin in your own strategy. + + + + + native is no longer consider the be= st strategy in terms of portability. for further + discussion, see + + + + + Lastly, we need to tell Hibernate about the remaining enti= ty class + properties. By default, no properties of the class are co= nsidered persistent: = + = - + @@ -324,27 +366,31 @@ ]]> = - Similar to the id element, the name - attribute of the property element tells= Hibernate which getter - and setter methods to use. In this case, Hibernate will s= earch for - getDate()/setDate(), as well as getTitle()/setTitle(). + Similar to the id element, the + name attribute of the + property element tells Hibernate which = getter + and setter methods to use. In this case, Hibernate will s= earch + for getDate(), setDate(), + getTitle() and setTitle() + methods. = - - Why does the date property mapping incl= ude the - column attribute, but the titl= e - does not? Without the column attribute,= Hibernate - by default uses the property name as the column name. This= works for - title, however, date= is a reserved - keyword in most databases so you will need to map it to a = different name. - + + + Why does the date property mapping = include the + column attribute, but the = title + does not? Without the column attrib= ute, Hibernate + by default uses the property name as the column name. = This works for + title, however, date is a reserved + keyword in most databases so you will need to map it t= o a different name. + + = - The title mapping also lacks - a type attribute. The types declared an= d used in the mapping - files are not, as you might expect, Java data types. They = are also not SQL - database types. These types are called Hibernate= mapping types, - converters which can translate from Java to SQL data types= and vice versa. Again, + The title mapping also lacks a type attribute. The + types declared and used in the mapping files are not Java = data types; they are not SQL + database types either. These types are called H= ibernate mapping types, + converters which can translate from Java to SQL data types= and vice versa. Again, Hibernate will try to determine the correct conversion and= mapping type itself if the type attribute is not present in th= e mapping. In some cases this automatic detection using Reflection on the Java class mig= ht not have the default you @@ -355,59 +401,64 @@ timestamp converter. = + + + Hibernate makes this mapping type determination using = reflection when the mapping files + are processed. This can take time and resources, so i= f startup performance is important + you should consider explicitly defining the type to us= e. + + + - Save the mapping file as Event.hbm.xml = in - the directory next to the Event Java cl= ass source file. - The naming of mapping files can be arbitrary, however, the= hbm.xml - suffix is a convention in the Hibernate developer communit= y. The directory structure - should now look like this: + Save this mapping file as + src/main/resources/org/hibernate/tutorial/domain= /Event.hbm.xml. = - -+src - +events - Event.java - Event.hbm.xml]]> - - - The next section continues with the main configuration of= Hibernate. - - = Hibernate configuration = - You should have a persistent class and its mapping file in= place. It is now time to configure - Hibernate. Before you do this, you will need a database. H= SQL DB, a java-based SQL DBMS, - can be downloaded from the HSQL DB website(http://hsqldb.o= rg/). You only need the hsqldb.jar - from this download. Place this file in the lib/ directory of the - development folder. + At this point, you should have the persistent class and it= s mapping + file in place. It is now time to configure Hibernate. Fir= st let's set up + HSQLDB to run in "server mode" = + + + We do this do that the data remains between runs. + + + - Create a directory called data in the r= oot of the development directory. - This is where HSQL DB will store its data files. Start the= database by running - java -classpath ../lib/hsqldb.jar org.hsqldb.Serv= er in this data directory. - You will see it start up and bind to a TCP/IP socket; this= is where our application - will connect later. If you want to start with a fresh data= base during this tutorial, - shutdown HSQL DB (press CTRL + C in the= window), delete all files in the - data/ directory, and start HSQL DB agai= n. + We will utilize the Maven exec plugin to launch the HSQLDB= server + by running: + mvn exec:java -Dexec.mainClass=3D"org.hsqldb.Ser= ver" -Dexec.args=3D"-database.0 file:target/data/tutorial" + You will see it start up and bind to a TCP/IP socket; this= is where + our application will connect later. If you want to start + with a fresh database during this tutorial, shutdown HSQLD= B, delete + all files in the target/data director= y, + and start HSQLDB again. = - Hibernate is the layer in your application that connects t= o this database, so it needs - connection information. The connections are made through a= JDBC connection pool, which you - will also have to configure. The Hibernate distribution con= tains several open source JDBC connection - pooling tools, but you will use the Hibernate built-in con= nection pool for this tutorial. - You will have to copy the required library into your class= path and use different - connection pooling settings if you want to use a productio= n-quality third party - JDBC pooling software. + Hibernate will be connecting to the database on behalf of = your application, so it needs to know + how to obtain connections. For this tutorial we will be u= sing a standalone connection + pool (as opposed to a javax.sql.DataSource<= /interfacename>). Hibernate comes with + support for two third-party open source JDBC connection po= ols: + c3p0<= /ulink> and + proxool. However, we will be using the + Hibernate built-in connection pool for this tutorial. = + + + The built-in Hibernate connection pool is in no way in= tended for production use. It + lacks several features found on any decent connection = pool. + + + For Hibernate's configuration, we can use a simple hibernate.properties file, a more sophisticated hibernate.cfg.xml fi= le, or even complete @@ -445,19 +496,22 @@ true = - create + update = - + = = ]]> = + + Notice that this configuration file specifies a diff= erent DTD + + - This XML configuration uses a different DTD. You configure - Hibernate's SessionFactory. SessionFact= ory is a global factory responsible - for a particular database. If you have several databases, = for easier startup you should use several - <session-factory> configurations = in + You configure Hibernate's SessionFactory. SessionFactory is a global + factory responsible for a particular database. If you have= several databases, for easier + startup you should use several <session-factor= y> configurations in several configuration files. = @@ -465,9 +519,18 @@ The first four property elements contai= n the necessary configuration for the JDBC connection. The dialect property element specifies the particular SQL variant Hibernate gen= erates. - Hibernate's automatic session management for persistence c= ontexts is particularly useful in this context. + = - The hbm2ddl.auto option turns on automa= tic generation of + + + In most cases, Hibernate is able to properly determine= which dialect to use. See + for mo= re information. + + + + + Hibernate's automatic session management for persistence c= ontexts is particularly useful + in this context. The hbm2ddl.auto opti= on turns on automatic generation of database schemas directly into the database. This can also= be turned off by removing the configuration option, or redirected to= a file with the help of the SchemaExport Ant task. Finally, add= the mapping file(s) @@ -475,116 +538,83 @@ = - Copy the file into the source directory, so it will end up= in the - root of the classpath. On startup, Hibernate automatically= searches for a file called - hibernate.cfg.xml in the root of the cl= asspath. + Save this file as hibernate.cfg.xml i= nto the + src/main/resources directory. = = - - Building with Ant + + Building with Maven = - We will now build the tutorial with Ant. You will need to = have Ant installed. - It is available from the Ant download page. - Installation instructions for Ant, however, are not be cov= ered here. Please refer to the - Ant= manual for further information. After you - have installed Ant, you can start to create the buildfile.= It will be called - build.xml and placed directly in the de= velopment directory. + We will now build the tutorial with Maven. You will need = to + have Maven installed; it is available from the + Maven= download page. + Maven will read the /pom.xml file we = created + earlier and know how to perform some basic project tasks. = First, + lets run the compile goal to make sure = we can compile + everything so far: = - - A basic build file looks like this: - + = - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - This will tell Ant to add all files in the library directo= ry ending with .jar - to the classpath used for compilation. It will also copy a= ll non-Java source files to the - target directory, configuration and Hibernate mapping file= s, for example. If you now run Ant, you - will get this output: - - - ant -Buildfile: build.xml - -copy-resources: - [copy] Copying 2 files to C:\hibernateTutorial\bin - -compile: - [javac] Compiling 1 source file to C:\hibernateTutorial\bin - -BUILD SUCCESSFUL -Total time: 1 second ]]> - = Startup and helpers = - It is time to load and store some Event= objects, but first - you have to complete the setup with some infrastructure co= de. You have to startup - Hibernate by building a global SessionFactory - object and storing it somewhere for easy access in applica= tion code. - A SessionFactory can open up new Sessions. - A Session represents a single-threaded = unit of work. The - SessionFactory is a thread-safe global = object, that is instantiated once. + It is time to load and store some Event + objects, but first you have to complete the setup with some + infrastructure code. You have to startup Hibernate by buil= ding + a global org.hibernate.SessionFactory + object and storing it somewhere for easy access in applica= tion code. A + org.hibernate.SessionFactory is used to + obtain org.hibernate.Session instances. + A org.hibernate.Session rep= resents a + single-threaded unit of work. The + org.hibernate.SessionFactory is a + thread-safe global object that is instantiated once. = - Create a HibernateUtil helper class tha= t takes care - of startup and makes accessing a SessionFactory convenient. - The following example illustrates the implementation: + We will create a HibernateUtil helper c= lass that + takes care of startup and makes accessing the + org.hibernate.SessionFactory more convenient. = - = - This class not only produces the global SessionFa= ctory in - its static initializer that is called once by the JVM when= the class is loaded. It also - hides the fact that it uses a static singleton. It might a= s well lookup the - SessionFactory from JNDI in an applicat= ion server. + Save this code as + src/main/java/org/hibernate/tutorial/util/Hibern= ateUtil.java = - If you give the SessionFactory a name i= n your configuration - file, Hibernate will try to bind it to JNDI after it has b= een built. - To avoid this code completely you could also use JMX deplo= yment and let the - JMX-capable container instantiate and bind a Hibe= rnateService - to JNDI. These advanced options are discussed in the Hiber= nate reference - documentation. + This class not only produces the global + org.hibernate.SessionFactory reference in + its static initializer; it also hides the fact that it use= s a + static singleton. We might just as well have looked up the + org.hibernate.SessionFactory reference from + JNDI in an application server or any other location for th= at matter. = - Place HibernateUtil.java in the develop= ment source directory in - a package next to events: + If you give the org.hibernate.SessionFactor= y + a name in your configuration, Hibernate will try to bind i= t to + JNDI under that name after it has been built. Another, be= tter option is to + use a JMX deployment and let the JMX-capable container ins= tantiate and bind + a HibernateService to JNDI. Such advanc= ed options are + discussed later. = - -+src - +events - Event.java - Event.hbm.xml - +util - HibernateUtil.java - hibernate.cfg.xml -+data -build.xml]]> - You now need to configure a logging system. Hibernate uses commons logging and provides two c= hoices: Log4j and @@ -652,16 +671,19 @@ Loading and storing objects = - You can use Hibernate to load and store objects. Write an - EventManager class with a main= () method: + We are now ready to start doing some real worjk with Hiber= nate. + Let's start by writing an EventManager = class + with a main() method: = - = - You can create a new Event object and h= and it over to Hibernate. - Hibernate takes care of the SQL and executes INSE= RT - on the database. We will explain the Session and - Transaction-handling code before we run= this. + In createAndStoreEvent() we created a n= ew + Event object and handed it over to Hibe= rnate. + At that point, Hibernate takes care of the SQL and execute= s an + INSERT on the database. = - A Session is a single unit of work. For= now we will keep things - simple and assume a one-to-one granularity between a Hiber= nate Session - and a database transaction. To shield our code from the ac= tual underlying transaction - system we use the - Transaction API that is available on th= e Hibernate Session. = - In this case plain JDBC, but it could also run with JTA. + A org.hibernate.Session is designed= to + represent a single unit of work (a single atmoic piece of = work + to be performed). For now we will keep things simple and = assume + a one-to-one granularity between a Hibernate + org.hibernate.Session and a database + transaction. To shield our code from the actual underlying + transaction system we use the Hibernate + org.hibernate.Transaction A= PI. + In this particular case we are using JDBC-based transactio= nal + semantics, but it could also run with JTA. = - What does sessionFactory.getCurrentSession() do? First, you can call it - as many times and anywhere you like, once you get hold of = your SessionFactory. - This is easy thanks to HibernateUtil). = The getCurrentSession() - method always returns the "current" unit of work. Remember= that we switched the configuration - option for this mechanism to "thread" in hibernat= e.cfg.xml? The current unit of work is bound to the current Java = thread that executes the application. - However, you also have to consider when a unit of work - begins and when it ends. + What does sessionFactory.getCurrentSession() do? + First, you can call it as many times and anywhere you like + once you get hold of your + org.hibernate.SessionFactory. + The getCurrentSession() method always r= eturns + the "current" unit of work. Remember that we switched + the configuration option for this mechanism to "thread" in= our + src/main/resources/hibernate.cfg.xml? + Due to that setting, the context of a current unit of work= is bound + to the current Java thread that executes the application. = + + + Hibernate offers three methods of current session trac= king. + The "thread" based method is not intended for producti= on use; + it is merely useful for prototyping and tutorials such= as this + one. Current session tracking is discussed in more de= tail + later on. + + + - A Session begins when the first call to - getCurrentSession() is made. It is then= bound by Hibernate to the current - thread. When the transaction ends, either through commit o= r rollback, Hibernate automatically - unbinds the Session from the thread and= closes it for you. If you call - getCurrentSession() again, you get a ne= w Session and can - start a new unit of work. This thread-bound programming model is the most - popular way of using Hibernate, as it allows flexible laye= ring of your code. Transaction - demarcation code can be separated from data access code. T= his will be covered later in this tutorial. + A org.hibernate.Session begins when= the + first call to getCurrentSession() is ma= de for + the current thread. It is then bound by Hibernate to the = current + thread. When the transaction ends, either through commit = or + rollback, Hibernate automatically unbinds the + org.hibernate.Session from the thre= ad + and closes it for you. If you call + getCurrentSession() again, you get a new + org.hibernate.Session and can start= a + new unit of work. = - Related to the unit of work scope, should the Hibernate Session be used to - execute one or several database operations? The above exam= ple uses one Session - for one operation. This is pure coincidence, the example i= s just not complex enough to show any - other approach. The scope of a Hibernate Session<= /literal> is flexible but you should - never design your application to use a new Hibernate Session for - every database operation. Even though= it is used in - the following examples, consider session-per-ope= ration - an anti-pattern. A real web application is shown later in = the tutorial. + Related to the unit of work scope, should the Hibernate + org.hibernate.Session be used to ex= ecute + one or several database operations? The above example use= s one + org.hibernate.Session for one opera= tion. + However this is pure coincidence; the example is just not = complex + enough to show any other approach. The scope of a Hibernate + org.hibernate.Session is flexible b= ut you + should never design your application to use a new Hibernate + org.hibernate.Session for + every database operation. Even though= it is + used in the following examples, consider + session-per-operation an anti-pattern. + A real web application is shown later in the tutorial whic= h will + help illustrate this. = See for more information - about transaction handling and demarcation. The previous e= xample also skipped any error handling and - rollback. + about transaction handling and demarcation. The previous + example also skipped any error handling and rollback. = - To run this first routine we have to add a callable target= to the Ant build file: + To run this, we will make use of the Maven exec plugin to = call our class + with the necessary classpath setup: + mvn exec:java -Dexec.mainClass=3D"org.hibernate.t= utorial.EventManager" -Dexec.args=3D"store" = - - - - - -]]> + + + You may need to perform mvn compile= first. + + = - The value of the action argument is set= on the command line when - calling the target: + You should see Hibernate starting up and, depending on you= r configuration, + lots of log output. Towards the end, the following line wi= ll be displayed: = - ant run -Dactio= n=3Dstore]]> - - - After compilation, you should see Hibernate starting up an= d, depending on your - configuration, lots of log output. At the end, the followi= ng line will be displayed: - - = - This is the INSERT executed by Hibernat= e. The question marks - represent JDBC bind parameters. To view the values bound a= s arguments, or to reduce - the verbosity of the log, check your log4j.proper= ties. + This is the INSERT executed by Hibernat= e. = To list stored events an option is added to the main metho= d: = - + = A new listEvents() method is also added: = - = - Session session =3D HibernateUtil.getSessionFactory().getCurrentSessio= n(); - - session.beginTransaction(); - - List result =3D session.createQuery("from Event").list(); - - session.getTransaction().commit(); - - return result; -}]]> - - Use an HQL (Hibernate Query Language) query to load all ex= isting + Here, we are using a Hibernate Query Language (HQL) query = to load all existing Event objects from the database. Hibern= ate will generate the appropriate SQL, send it to the database and populate Event objects - with the data. You can create more complex queries with HQ= L. + with the data. You can create more complex queries with HQ= L. See + for more information. = - To execute and test all of this, follow these steps: + Now we can call our new functionality, again using the Mav= en exec plugin: + mvn exec:java -Dexec.mainClass=3D"org.hibernate.t= utorial.EventManager" -Dexec.args=3D"list" = - - - - Run ant run -Daction=3Dstore to= store something in the database - and, of course, to generate the database schema be= fore through hbm2ddl. - - - - - Disable hbm2ddl by commenting out the property in = your hibernate.cfg.xml - file. It is only turned on in continuous unit test= ing. Another - run of hbm2ddl would drop eve= rything you have stored. The - create configuration setting tr= anslates into "drop all - tables from the schema, then re-create all tables,= when the SessionFactory is built". - - - - - - If you can call Ant with -Daction=3Dlist, you will be able to view the events - you have stored so far. You can also call the sto= re action. - - - - Most new Hibernate users fail at this point and we regular= ly receive questions relating to - Table not found error messages. Howev= er, if you follow the - steps outlined above you will not have this problem, as hb= m2ddl creates the database - schema on the first run, and subsequent application restar= ts will use this schema. If - you change the mapping and/or database schema, you will ha= ve to re-enable hbm2ddl. - - = @@ -860,8 +863,10 @@ Part 2 - Mapping associations = - You have mapped a persistent entity class to a table. You can = now build on this by adding some class associations. - First you will add people to your application, and store a lis= t of events they participate in. + So far we have mapped a single persistent entity class to a ta= ble in + isolation. Let's expand on that a bit and add some class asso= ciations. + We will add people to the application and store a list of even= ts in + which they participate. = @@ -871,7 +876,7 @@ The first cut of the Person class looks= like this: = - = - Create a new mapping file called Person.hbm.xml. Do not forget the - DTD reference at the top: + Save this to a file named + src/main/java/org/hibernate/tutorial/domain/Pers= on.java = - + + Next, create the new mapping file as + src/main/resources/org/hibernate/tutorial/domain= /Person.hbm.xml + = - + + + @@ -924,17 +934,16 @@ A unidirectional Set-based association = - By adding a collection of events to the Person class, you can - easily navigate to the events for a particular person, wit= hout executing an explicit query - - by calling aPerson.getEvents(). A Java = collection, a Set, is used - because the collection will not contain duplicate elements= and the ordering is not relevant to our examples. + By adding a collection of events to the Person + class, you can easily navigate to the events for a particu= lar person, + without executing an explicit query - by calling + Person#getEvents. Multi-valued associa= tions + are represented in Hibernate by one of the Java Collection= Framework + contracts; here we choose a java.util.Set + because the collection will not contain duplicate elements= and the ordering + is not relevant to our examples: = - - We need unidirectional, many-valued associations, implemen= ted with a Set. - Write the code for this in the Java classes and then map i= t: - - = - Before you map this association, consider the other side. = You could just keep this - unidirectional. Or, you could create another collection on= the Event, if you - want to be able to navigate it bi-directional, i.e., anEvent.getParticipants(). - This is not necessary, from a functional perspective. You = can always execute an explicit query - to retrieve the participants for a particular event. This = is a design choice left to you, but what - is clear from this discussion is the multiplicity of the a= ssociation: "many" valued on both sides - is called a many-to-many association.= Hence, we use Hibernate's - many-to-many mapping: + Before mapping this association, let's consider the other = side. + We could just keep this unidirectional or create another + collection on the Event, if we wanted t= o be + able to navigate it from both directions. This is not nec= essary, + from a functional perspective. You can always execute an e= xplicit + query to retrieve the participants for a particular event.= This + is a design choice left to you, but what is clear from this + discussion is the multiplicity of the association: "many" = valued + on both sides is called a many-to-many + association. Hence, we use Hibernate's many-to-many mappin= g: = - + @@ -969,20 +980,24 @@ = - + = ]]> = - Hibernate supports a broad range of collection mappings, a= <set> being most - common. For a many-to-many association, or n:m entity relationship, an - association table is required. Each row in this table repr= esents a link between a person and an event. - The table name is configured with the table attribute of the set - element. The identifier column name in the association, fo= r the person side, is defined with the - <key> element, the column name fo= r the event's side with the - column attribute of the <ma= ny-to-many>. You also - have to tell Hibernate the class of the objects in your co= llection (the class on the + Hibernate supports a broad range of collection mappings, a + set being most common. For a many-to-m= any + association, or n:m entity relationsh= ip, an + association table is required. Each row in this table rep= resents + a link between a person and an event. The table name is + decalred using the table attribute of t= he + set element. The identifier column nam= e in + the association, for the person side, is defined with the + key element, the column name for the ev= ent's + side with the column attribute of the + many-to-many. You also have to tell Hib= ernate + the class of the objects in your collection (the class on = the other side of the collection of references). = @@ -1013,73 +1028,77 @@ Now we will bring some people and events together in a new= method in EventManager: = - = - aPerson.getEvents().add(anEvent); - - session.getTransaction().commit(); -}]]> - - After loading a Person and an = Event, simply - modify the collection using the normal collection methods.= There is no explicit call - to update() or save(); Hibernate automatically - detects that the collection has been modified and needs to= be updated. This is called automatic - dirty checking. You can also try it by modifyin= g the name or the date property of - any of your objects. As long as they are in pers= istent state, that is, bound - to a particular Hibernate Session (i.e.= they have been just loaded or saved in - a unit of work), Hibernate monitors any changes and execut= es SQL in a write-behind fashion. The - process of synchronizing the memory state with the databas= e, usually only at the end of a unit of - work, is called flushing. In our code= , the unit of work ends with a commit, - or rollback, of the database transaction. This is defined = by the thread configuration - option for the CurrentSessionContext cl= ass. + After loading a Person and an + Event, simply modify the collection usi= ng the + normal collection methods. There is no explicit call to + update() or save(); + Hibernate automatically detects that the collection has be= en modified + and needs to be updated. This is called + automatic dirty checking. You can als= o try + it by modifying the name or the date property of any of yo= ur + objects. As long as they are in persistent + state, that is, bound to a particular Hibernate + org.hibernate.Session, Hibe= rnate + monitors any changes and executes SQL in a write-behind fa= shion. + The process of synchronizing the memory state with the dat= abase, + usually only at the end of a unit of work, is called + flushing. In our code, the unit of w= ork + ends with a commit, or rollback, of the database transacti= on. = - You can load person and event in different units of work. = Or you can modify an object - outside of a Session, when it is not in= persistent state (if it was persistent - before, this state is called detached= ). You can even modify a collection when - it is detached: + You can load person and event in different units of work. = Or + you can modify an object outside of a + org.hibernate.Session, when= it + is not in persistent state (if it was persistent before, t= his + state is called detached). You can e= ven + modify a collection when it is detached: = - = - Session session2 =3D HibernateUtil.getSessionFactory().getCurrentSessi= on(); - session2.beginTransaction(); - - session2.update(aPerson); // Reattachment of aPerson - - session2.getTransaction().commit(); -}]]> - - The call to update makes a detached obj= ect persistent again by binding it to a new unit of work, so any modificati= ons you made to it while detached - can be saved to the database. This includes any modificati= ons (additions/deletions) you - made to a collection of that entity object. + The call to update makes a detached obj= ect + persistent again by binding it to a new unit of work, so a= ny + modifications you made to it while detached can be saved to + the database. This includes any modifications + (additions/deletions) you made to a collection of that ent= ity + object. = @@ -1090,29 +1109,35 @@ returns it (you might have to modify some of the previous = methods to return that identifier): = - + = - This is an example of an association between two equally i= mportant classes, two entities. - As mentioned earlier, there are other classes and types in= a typical model, usually "less - important". Some you have already seen, like an i= nt or a String. - We call these classes value types, an= d their instances depend - on a particular entity. Instances of these types do not ha= ve their own identity, nor are they - shared between entities. Two persons do not reference the = same firstname - object, even if they have the same first name. Value types= cannot only be found in - the JDK , but - you can also write dependent classes yourself (Ad= dress or MonetaryAmount, - for example). In fact, in a Hibernate application all JDK = classes are considered value types. + This is an example of an association between two equally i= mportant + classes : two entities. As mentioned earlier, there are o= ther + classes and types in a typical model, usually "less import= ant". + Some you have already seen, like an int= or a + java.lang.String. We call these cl= asses + value types, and their instances + depend on a particular entity. Insta= nces of + these types do not have their own identity, nor are they s= hared + between entities. Two persons do not reference the same + firstname object, even if they have the= same + first name. Value types cannot only be found in the JDK ,= but + you can also write dependent classes yourself + such as an Address or + MonetaryAmount class. In fact, in a Hi= bernate + application all JDK classes are considered value types. = - You can also design a collection of value types. This is c= onceptually different from a - collection of references to other entities, but looks almo= st the same in Java. + You can also design a collection of value types. This is + conceptually different from a collection of references to = other + entities, but looks almost the same in Java. = @@ -1121,37 +1146,44 @@ Collection of values = - You can add a collection of value typed objects to the Person entity. If you want to - store email addresses, the type you use is String= , and the collection is - again a Set: + Let's add a collection of email addresses to the + Person entity. This will be represente= d as a + java.util.Set of + java.lang.String instances: - + public void setEmailAddresses(Set emailAddresses) { + this.emailAddresses =3D emailAddresses; + }]]> = The mapping of this Set is as follows: = - - - -]]> + + + + ]]> = - The difference compared with the earlier mapping is the element part which tells Hibernate that the collection - does not contain references to another entity, but a colle= ction of elements of type - String. The lowercase name tells you it= is a Hibernate mapping type/converter. - Again the table attribute of the set element determines - the table name for the collection. The key element defines the foreign-key column - name in the collection table. The column attribute in the element - element defines the column name where the String<= /literal> values will actually be stored. + The difference compared with the earlier mapping is the us= e of + the element part which tells Hibernate = that the + collection does not contain references to another entity, = but is + rather a collection whose elements are values types, here = specifically + of type string. The lowercase name tel= ls you + it is a Hibernate mapping type/converter. Again the + table attribute of the set + element determines the table name for the collection. The + key element defines the foreign-key col= umn + name in the collection table. The column + attribute in the element element define= s the + column name where the email address values will actually + be stored. = @@ -1183,24 +1215,21 @@ linking persons and events. It is the same code in Java: = - = - // The getEmailAddresses() might trigger a lazy load of the collection - aPerson.getEmailAddresses().add(emailAddress); - - session.getTransaction().commit(); -}]]> - - This time we did not use a fetch quer= y to initialize the collection. - Hence, the call to its getter method will trigger an addit= ional select to initialize - it, so we can add an element to it. Monitor the SQL log an= d try to optimize this with - an eager fetch. + This time we did not use a fetch quer= y to + initialize the collection. Monitor the SQL log and try to + optimize this with an eager fetch. = @@ -1209,35 +1238,44 @@ Bi-directional associations = - Next you will map a bi-directional association. You will m= ake the association between - person and event work from both sides in Java. The databas= e schema does not - change, so you will still have many-to-many multiplicity. = A relational database is more flexible - than a network programming language, so it does not need a= navigation - direction; data can be viewed and retrieved in any possibl= e way. + Next you will map a bi-directional association. You will = make + the association between person and event work from both si= des + in Java. The database schema does not change, so you will= still + have many-to-many multiplicity. = + + + A relational database is more flexible than a network + programming language, in that it does not need a navig= ation + direction; data can be viewed and retrieved in any pos= sible + way. + + + - First, add a collection of participants to the Ev= ent Event class: + First, add a collection of participants to the + Event class: = - + public void setParticipants(Set participants) { + this.participants =3D participants; + }]]> = Now map this side of the association in Event.hbm= .xml. = - - - -]]> + + + + ]]> = These are normal set mappings in both m= apping documents. @@ -1273,23 +1311,23 @@ correctly set both sides (for example, in Person<= /literal>): = - + public void removeFromEvent(Event event) { + this.getEvents().remove(event); + event.getParticipants().remove(this); + }]]> = The get and set methods for the collection are now protect= ed. This allows classes in the @@ -1309,7 +1347,6 @@ and in many-to-many association you can select either side. = - In the next section we will turn this into a small web application.= = @@ -1328,50 +1365,51 @@ Writing the basic servlet = - Create a new class in your source directory in the events - package: + First we need create our basic processing servlet. Since = our + servlet only handles HTTP GET requests,= we + will only implement the doGet() method: = - + protected void doGet( + HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOExcep= tion { = - - The servlet handles HTTP GET requests o= nly. It is for this reason that the method - we implement is doGet(): - + SimpleDateFormat dateFormatter =3D new SimpleDateFormat( "dd.MM.yy= yy" ); = - = + Save this servlet as + src/main/java/org/hibernate/tutorial/web/EventMa= nagerServlet.java + + + The pattern applied here is called session-per-r= equest. When a request hits the servlet, a new Hibernate = Session is opened through the first call to getCurrentSessio= n() on the @@ -1412,32 +1450,33 @@ Now you can implement the processing of the request and th= e rendering of the page. = -Event Manager"); +Event Manager= "); = -// Handle actions -if ( "store".equals(request.getParameter("action")) ) { + // Handle actions + if ( "store".equals(request.getParameter("action")) ) { = - String eventTitle =3D request.getParameter("eventTitle"); - String eventDate =3D request.getParameter("eventDate"); + String eventTitle =3D request.getParameter("eventTitle"); + String eventDate =3D request.getParameter("eventDate"); = - if ( "".equals(eventTitle) || "".equals(eventDate) ) { - out.println("Please enter event title and date."); - } else { - createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate)); - out.println("Added event."); - } -} + if ( "".equals(eventTitle) || "".equals(eventDate) ) { + out.println("Please enter event title and date.<= /b>"); + } + else { + createAndStoreEvent(eventTitle, dateFormatter.parse(eventD= ate)); + out.println("Added event."); + } + } = -// Print page -printEventForm(out); -listEvents(out, dateFormatter); + // Print page + printEventForm(out); + listEvents(out, dateFormatter); = -// Write HTML footer -out.println(""); -out.flush(); -out.close();]]> + // Write HTML footer + out.println(""); + out.flush(); + out.close();]]> = This coding style, with a mix of Java and HTML, would not = scale @@ -1448,14 +1487,14 @@ trivial and only outputs HTML: = - Add new event:"); - out.println("
"); - out.println("Title:
"); - out.println("Date (e.g. 24.12.2009):
"); - out.println(""= ); - out.println("
"); -}]]>
+ Add new event:"); + out.println("
"); + out.println("Title:
"); + out.println("Date (e.g. 24.12.2009):
"); + out.println(""); + out.println("
"); + }]]>
= The listEvents() method uses the Hibern= ate @@ -1463,27 +1502,28 @@ a query: = - 0) { - out.println("

Events in database:

"); - out.println(""); - out.println(""); - out.println(""); - out.println(""); - out.println(""); - for (Iterator it =3D result.iterator(); it.hasNext();) { - Event event =3D (Event) it.next(); + List result =3D HibernateUtil.getSessionFactory() + .getCurrentSession().createCriteria(Event.class).list(); + if (result.size() > 0) { + out.println("

Events in database:

"); + out.println("
Event titleEvent date
"); out.println(""); - out.println(""); - out.println(""); + out.println(""); + out.println(""); out.println(""); + Iterator it =3D result.iterator(); + while (it.hasNext()) { + Event event =3D (Event) it.next(); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + } + out.println("
" + event.getTitle() + "" + dateFormatter.format(event.getDate()) + "= Event titleEvent date
" + event.getTitle() + "" + dateFormatter.format(event.getDate())= + "
"); } - out.println(""); - } -}]]>
+ }]]> = Finally, the store action is dispatched= to the @@ -1491,14 +1531,14 @@ the Session of the current thread: = - + HibernateUtil.getSessionFactory() + .getCurrentSession().save(theEvent); + }]]> = The servlet is now complete. A request to the servlet will= be processed @@ -1517,26 +1557,11 @@ Deploying and testing = - To deploy this application you have to create a web archiv= e, or what is known as a WAR. Add the - following Ant target to your build.xml: + To deploy this application for testing we must create a + Web ARchive (WAR). First we must define the WAR descriptor + as src/main/webapp/WEB-INF/web.xml = - - - - - - - - -]]> - - - This target creates a file called hibernate-tutor= ial.war - in your project directory. It packages all libraries and t= he web.xml - descriptor, which is expected in the base directory of you= r project: - - Event Manager - events.EventManagerServlet + org.hibernate.tutorial.web.EventManagerServlet = @@ -1555,20 +1580,19 @@ ]]> = - Before you compile and deploy the web application, an addi= tional library - is required: jsdk.jar. This is the Java= servlet development kit. - If you do not have this library already, get it from the S= un website and copy it to - your library directory. However, it will be only used for = compilation and excluded - from the WAR package. + To build and deploy call mvn package in= your + project directory and copy the hibernate-tutoria= l.war + file into your Tomcat webapps directo= ry. = - - To build and deploy call ant war in you= r project directory - and copy the hibernate-tutorial.war fil= e into your Tomcat - webapp directory. If you do not have To= mcat installed, download - it and follow the installation instructions. You do not ha= ve to change any Tomcat - configuration to deploy this application though. - + + + If you do not have Tomcat installed, download it from + and follow = the + installation instructions. Our application requires + no changes to the standard Tomcat configuration. + + = Once deployed and Tomcat is running, access the applicatio= n at @@ -1587,21 +1611,10 @@ = This tutorial covered the basics of writing a simple standalon= e Hibernate application - and a small web application. + and a small web application. More tutorials are available fro= m the Hibernate + website. = - - If you already feel confident with Hibernate, continue browsin= g through the reference - documentation table of contents for topics you find interestin= g. The most popular are - transactional processing (), f= etch - performance (), or the usage of= the API () - and the query features (). - - - - More tutorials are available from the Hibernate website. - - =
--===============7507922504910344565==--