Section 5.3. Using Hibernate with Spring

team bbl


5.3. Using Hibernate with Spring

Hibernate has long been the persistence framework of choice for Spring developers. Although the Spring team continues to improve the integration with other persistence frameworks, Hibernate remains the most widely used persistence framework with Spring. It's fitting that these two lightweight solutions helped each other succeed. They go quite well together. In this example, we'll show how to integrate Spring and Hibernate.

Hibernate is an outstanding persistence framework. It's popular, it's relatively fast, and it's free. It has rich mapping support and a convenient usage model that's made it popular with developers across the world. Hibernate holds up very well in small- and intermediate-size projects. In fact, though it's nonstandard, you could say that behind EJB, Hibernate is the most popular persistence framework in the world.

5.3.1. How do I do that?

Now that you've configured Spring with an ORM, you know the basic flow, with a persistent domain model and a façade. Since Spring ships with Hibernate dependencies, you can just copy them from Spring's /dist folder to your /lib folder: hibernate2.jar, aopalliance.jar, cglib-full-2.0.2.jar, dom4j.jar, ehcache-1.1.jar, and odmg.jar.

Since Hibernate uses reflection, there's no byte code enhancement step. All you've got to do to make the model persistent is to create the mappings, and refer to them in the context. Examples Example 5-12, Example 5-13, and Example 5-14 show the mappings.

Example 5-12. Bike.hbm.xml
<hibernate-mapping>    <class name="com.springbook.Bike" table="bikes">       <id name="bikeId" column="bikeid" type="java.lang.Integer"             unsaved-value="-1">         <generator ></generator>       </id>       <property name="manufacturer" column="manufacturer" type="string"/>       <property name="model" column="model" type="string"/>       <property name="frame" column="frame" type="int"/>       <property name="serialNo" column="serialno" type="string"/>       <property name="weight" column="weight" type="java.lang.Double"/>       <property name="status" column="status" type="string"/>       <set name="reservations">            <key column="bikeId"/>            <one-to-many />       </set>    </class> </hibernate-mapping>

Example 5-13. Customer.hbm.xml
<hibernate-mapping>    <class name="com.springbook.Customer" table="customers">       <id name="custId" column="custid" type="java.lang.Integer"             unsaved-value="-1">         <generator ></generator>       </id>       <property name="firstName" column="firstname" type="string"/>       <property name="lastName" column="lastname" type="string"/>       <set name="reservations">            <key column="custId"/>            <one-to-many />       </set>    </class> </hibernate-mapping>

Example 5-14. Reservation.hbm.xml
<hibernate-mapping>    <class name="com.springbook.Reservation" table="reservations">       <id name="reservationId" column="resid" type="java.lang.Integer"             unsaved-value="-1">         <generator ></generator>       </id>       <property name="reservationDate" column="resdate" type="date"/>       <many-to-one name="bike" column="bikeId"                      cascade="none"/>       <many-to-one name="customer" column="custId"                                  cascade="none"/>    </class> </hibernate-mapping>

In the context, you need to configure Hibernate properties, configure the session factory, and plug the session factory into the façade. The transaction strategies with the JDO context, the iBATIS context and the Hibernate context are the same, as they should be. That's part of what dependency injection is doing for you. Example 5-15 shows the changes to the context.

Example 5-15. RentABikeApp-servlet.xml
<bean name="rentaBike" >     <property name="storeName"><value>Bruce's Bikes</value></property>     <property name="sessionFactory">           <ref local="sessionFactory"/>     </property> </bean> <bean       >     <property name="dataSource"><ref local="dataSource"/></property>     <property name="mappingResources">            <list>                    <value>com/springbook/Bike.hbm.xml</value>                    <value>com/springbook/Customer.hbm.xml</value>                    <value>com/springbook/Reservation.hbm.xml</value>            </list>     </property>     <property name="hibernateProperties">            <props>                   <prop key="hibernate.dialect">                   net.sf.hibernate.dialect.MySQLDialect                   </prop>                   <prop key="hibernate.show_sql">true</prop>            </props>     </property> </bean>

Since you've already got a façade interface, you need only a Hibernate implementation. You can use templates, just as with JDO. For finders, specify a Hibernate query language (HQL) statement. For updates, all that you need to specify is the new object to be stored. Example 5-16 is the remarkably thin façade.

Example 5-16. HibRentABike.java
package com.springbook; import org.springframework.orm.hibernate.support.HibernateDaoSupport; import java.util.List; import java.util.Date; import java.util.Set; import net.sf.hibernate.Query; public class HibRentABike extends HibernateDaoSupport implements RentABike {     private String name;     public List getBikes( ) {         return getHibernateTemplate( ).find("from Bike");     }     public Bike getBike(String serialNo) {         Bike b = null;         List bikes = getHibernateTemplate( ).            find("from Bike where serialNo = ?", serialNo);         if(bikes.size( ) > 0) {             b = (Bike)bikes.get(0);         }         return b;     }     public Bike getBike(int bikeId) {         return (Bike)getHibernateTemplate( ).            load(Bike.class, new Integer(bikeId));     }     public void saveBike(Bike bike) {         getHibernateTemplate( ).saveOrUpdate(bike);     }     public void deleteBike(Bike bike) {         getHibernateTemplate( ).delete(bike);     }     public void setStoreName(String name) {         this.name = name;     }     public String getStoreName( ) {         return this.name;     }     public List getCustomers( ) {        return getHibernateTemplate( ).find("from Customer");     }     public Customer getCustomer(int custId) {        return (Customer)getHibernateTemplate( ).            load(Customer.class, new Integer(custId));     }     public List getReservations( ) {         return getHibernateTemplate( ).find("from Reservation");     }     public List getReservations(Customer customer) {         return getHibernateTemplate( ).            find("from Reservation where custId = ?", customer.getCustId( ));     }     public List getReservations(Bike bike) {         return getHibernateTemplate( ).         find("from Reservation where bikeId = ?", bike.getBikeId( ));     }     public List getReservations(Date date) {         return getHibernateTemplate( ).            find("from Reservation where resdate = ?", date);             }     public Reservation getReservation(int resId) {         return (Reservation)getHibernateTemplate( ).            load(Reservation.class, new Integer(resId));     } }

5.3.2. What just happened?

The Hibernate flow is pretty much the same as the JDO flow. The Spring JDO template represents a set of default DAO methods. All that you need to do is customize them, usually with a HQL query statement, and possibly the values for parameters to any HQL parameterized queries. Then Spring takes control, getting a session, firing the query, and managing any exceptions.

Once again, you see exceptional leverage. Example 5-17 gives the typical Hibernate method that you'd need to write without Spring.

Example 5-17. HibRentABike.java
public List getBikesOldWay( ) throws Exception {         // Relies on other static code for configuration         // and generation of SessionFactory.  Might look like:         // Configuration config = new Configuration( );         // config.addClass(Bike.class).addClass(Customer.class).         //        addClass(Reservation.class);         // SessionFactory mySessionFactory = Configuration.         //        buildSessionFactory( );         List bikes = null;         Session s = null;         try {             s = mySessionFactory.openSession( );             bikes = s.find("from Bike");         }catch (Exception ex) {             //handle exception gracefully         }finally {             s.close( );         }         return bikes;     }

Example 5-18 shows, again, the Spring counterpart.

Example 5-18. HibRentABike.java
    public List getBikes( ) {         return getHibernateTemplate( ).find("from Bike");     }

Strong typing is for weak programmers. Each building block of an application should strive do one thing well, and only once.

5.3.3. What about...

...alternatives to Hibernate? Hibernate is indeed free, fast, effective, and popular. It's been proven under fire, and has excellent performance and flexibility. Most tools have good Hibernate support, and Hibernate supports every database that matters. I still recommend Hibernate for small and intermediate applications.

So far, as an open source framework, the persistence community can't be quick enough to praise Hibernate or condemn the alternatives. Such blind worship leads to cultish religious decision making. There are some things that competitors do better. If your application has some of these characteristics, you might be best served to look elsewhere:


Standards

JDO and JDBC solutions conform to a standard. Although it's open source code, Hibernate does not conform to a standard. You have to trust the motivations of JBoss group and the founders to do the right thing for decades, and for any framework, that's proven to be a dicey proposition so far.


Management

Other solutions are easier to manage. For example, Kodo JDO and TopLink have management consoles that make it easier to manage caching scenarios, and eager or lazy-loading scenarios.


Mapping

Other frameworks have more powerful and flexible mapping support. If you do not control your schema, you may be best served with another solution. Also, if you prefer to map your schema with GUI tools, then something like JDO Genie or Cayenne may work best for you.

In general, using mainstream frameworks may be the right choice in the end, but often you can find a much better fit with a little digging. Hibernate certainly deserves consideration, but there are other good choices out there, too.

    team bbl



    Spring. A developer's Notebook
    Spring: A Developers Notebook
    ISBN: 0596009100
    EAN: 2147483647
    Year: 2005
    Pages: 90

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net