Spring JDBC with Hibernate

By lequangminh04

Introducing Spring’s ORM framework support
               When we were kids, riding a bike was fun, wasn’t it? We would ride to school in the mornings. When school let out we would cruise to our best friend’s house. When it got late and our parents were yelling at us for staying out past dark, we would peddle home for the night. Gee, those days were fun.But then we grew up and we needed more than a bike. Sometimes we have to travel quite a distance to work. Groceries have to be hauled and ours kids need to get to soccer practice. And if you live in Texas, air conditioning is a must! Our needs have simply outgrown our bike. JDBC is the bike of the persistence world. It is great for what it does, and for some jobs it works just fine. But as our applications become more complex, so do our persistence requirements. We need to be able to map object properties to database columns and have our statements and queries created for us, freeing us from typing an endless string of question marks. We also need more sophisticated features such as the following:
            ■ Lazy loading—As our object graphs become more complex, we sometimes don’t want to fetch entire relationships immediately. To use a typical example, suppose we are selecting a collection of PurchaseOrder objects, and each of these objects contains a collection of LineItem objects. If we are only interested in PurchaseOrder attributes, it makes no sense to grab the LineItem data. This could be quite expensive. Lazy loading allows us to grab data only as it is needed.
            ■ Eager fetching—This is the opposite of lazy loading. Eager fetching allows you to grab an entire object graph in one query. So if we know we need a PurchaseOrder object and its associated LineItems, eager fetching lets us get this from the database in one operation, saving us from costly round-trips.
           ■ Caching—For data that is read-mostly (used often but changed infrequently), we don’t want to fetch this from the database every time it is used.
Caching can add a significant performance boost.
            ■ Cascading—Sometimes changes to a database table should result in changes to other tables as well. Going back to our purchase order example, it is reasonable that a LineItem object has an association with a Product object. In the database, this is most likely represented as a many-to-many relationship. So when a LineItem object is deleted, we also want to disassociate this LineItem from its Product object in the database. Fortunately, there are frameworks out there that already provide these services. The general term for these services is object/relational mapping (ORM). Using an ORM tool for your persistence layer can save you literally thousands of lines of code and hours of development time. This lets you switch your focus from writing
error-prone SQL code to addressing your application requirements. Spring provides integration for Sun’s standard persistence API JDO, as well as
the open source ORM frameworks Hibernate, Apache OJB, and iBATIS SQL Maps. Spring’s support for each of these technologies is not as extensive as its JDBC support. This is not a poor reflection on Spring’s APIs, but rather a testament to how much work each of these ORM frameworks does. With the ORM tool doing most of the actual persistence, Spring provides integration points to these frameworks, as well as some additional services:
            ■ Integrated transaction management
            ■ Exception handling
            ■ Thread-safe, lightweight template classes
            ■ Convenience support classes
            ■ Resource management
        While we are going to cover Spring’s integration with all four of these ORM frameworks, we will not go into the details of each specific framework. We will give an explanation of their general behavior and some example configurations. If you want to explore any of these frameworks in detail, a wealth of resources is available.
4.4 Integrating Hibernate with Spring
Hibernate is a high-performance, open source persistence framework that has gained significant popularity recently. It provides not only basic object/relational mapping but also all the other sophisticated features you would expect from a full-featured ORM tool, such as caching, lazy loading, eager fetching, and distributed caching. You can learn more about it in Hibernate in Action from Manning or at the Hibernate web site http://www.hibernate.org.
4.4.1 Hibernate overview
You configure how Hibernate maps your objects to a relational database through XML configuration files. For an example of how this is done, let’s examine how we would map the Student class from our Spring Training application. First, let’s examine the Student class, shown in listing 4.12.   Student.java
import java.util.Set;
public class Student {
         private Integer id;
         private String firstName;
         private String lastName;
         private Set courses;
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() { return lastName; }
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Set getCourses() { return courses; }
public void setCourses(Set courses) { this.courses = courses; }
}

Typically, each persistent class will have a corresponding XML mapping file that ends with the extension “.hbm.xml.” Let’s take a look at the mapping file for the Student class. By convention, we would name this file Student.hbm.xml, which is shown in listing 4.13.

Listing 4.13 Student.hbm.xml Hibernate mapping file

<?xml version=”1.0″?>

<!DOCTYPE hibernate-mapping

PUBLIC “-//Hibernate/Hibernate Mapping DTD//EN”

“http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd”>

<hibernate-mapping>

      <class name=”org.springinaction.training.model.Student”>

             <id name=”id”>

            <generator class=”assigned”/>

 

              </id>

 

            

              <property name=”sex”/> 

 

             <property name=”weight”/>

             <set name=”courses” table=”transcript”>

                  <key column=”student_id”/>

                    <many-to-many column=”course_id”

                       class=”org.springinaction.training.model.Course”/>

             </set>

</class>

</hibernate-mapping>

 

 

       In a typical application, you will have several of these files. These configuration files are then read in to create a SessionFactory. A SessionFactory will last the lifetime of your application and you will use it to obtain (what else?) Session objects. It is with these Session objects that you will access the database. So assuming that we have a configured SessionFactory, here is how we would get a Student object by its primary key:
     public Student getStudent(Integer id) throw HibernateException {
            Session session = sessionFactory.openSession();
            Student student = (Student) session.load(Student.class, id);
             session.close();
             return student;
      }

      This is a trivial example of using Hibernate that excludes exception handling. But there is one thing you should take from this: Very little code is required to execute this operation. In fact, we actually load the Student object in one line of code. This is because Hibernate is doing all the work based on your mappings. Since Hibernate is taking care of making persistence easier, Spring focuses on making it easier to integrate with Hibernate. Let’s look at some of the ways Spring does this.

4.4.2 Managing Hibernate resources
As we said, you will keep a single instance of a SessionFactory throughout the life of your application. So it makes sense to configure this object through your Spring configuration file. You do so using the Spring class LocalSessionFactoryBean:

Of course the SessionFactory needs to know to which database to connect. The preferred way to do this is to wire a DataSource to the LocalSessionFactoryBean:

<bean id=”dataSource”

       class=”org.springframework.jndi.JndiObjectFactoryBean”>

        <property name=”jndiName”>

            <value>java:comp/env/jdbc/trainingDatasource</value>

        </property>

</bean>

<bean id=”sessionFactory” class=”org.springframework. orm.hibernate.LocalSessionFactoryBean”>

        <property name=”dataSource”>

            <ref bean=”dataSource”/>

         </property>

 

 

      You also manage how Hibernate is configured through the same LocalSession- FactoryBean bean. Hibernate itself has dozens of properties by which you can tweak its behavior. When used outside of Spring, Hibernate looks for a file named hibernate.properties somewhere on the application class path for its configurations. However, with Spring you do not have to manage these configurations in a separate properties file. Instead, you can wire them to the hibernateProperties property of the LocalSessionFactoryBean:

<bean id=”sessionFactory” class=”org.springframework. orm.hibernate.LocalSessionFactoryBean”>

         <property name=”hibernateProperties”>

            <props>

                   <prop key=”hibernate.dialect”>net.sf.hibernate.dialect.MySQLDialect</prop>

            </props>

         </property>

</bean>

 

 

One last thing you must configure is which mapping files Hibernate should read in. Remember when we created a Student.hbm.xml file? Well, we actuallyhave to tell Hibernate it needs to use this file. Otherwise it will not know how to
map the Student class to the database. Again, we can configure this through a property of the LocalSessionFactoryBean bean. In this case, we use the mapping- Resources property:

 

 

<bean id=”sessionFactory” class=”org.springframework. orm.hibernate.LocalSessionFactoryBean”>

       <property name=”mappingResources”>

 

 

           <list> 

 

               <value>Student.hbm.xml</value>

               <value>Course.hbm.xml</value>

           </list>

        </property>

</bean>

 

        This example works just fine for our small Spring Training application. But what  happens if your application grows and you have dozens, if not hundreds, of persistent classes? It would be cumbersome to configure them all in this fashion. Fortunately, Spring offers you an alternative. You can also configure the mapping- DirectoryLocations property with a path that is a subset of your application’s class path, and Spring will configure the SessionFactory with every *.hbm.xml it finds in this path. For example, assuming that all the persistent classes we want to configure are contained in the com.springinaction.training.model package, we would configure our SessionFactory like this:

 

 <bean id=”sessionFactory” class=”org.springframework.orm.hibernate.LocalSessionFactoryBean”> 

     <property name=”mappingDirectoryLocations”>

     <list>

           <value>classpath:/com/springinaction/training/model</value>

      </list>

</property>

</bean>

 

     Now we have a fully configured SessionFactory and we didn’t even need to create a second configuration file. Now all we need to do is create an object through which we will access Hibernate. Like all of Spring’s DAO frameworks, this will be a template class. In this case, it is the HibernateTemplate class. And because the HibernateTemplate class is thread-safe, we can share this template class with multiple DAO objects:

 

<bean id=”hibernateTemplate” class=”org.springframework.orm.hibernate.HibernateTemplate”>

      <property name=”sessionFactory”>

           <ref bean=”sessionFactory”/>

       </property>

</bean>

<bean id=”studentDao” class=”com.springinaction.training.dao.hibernate.StudentDaoHibernate”>

       <property name=”hibernateTemplate”>

            <ref bean=”hibernateTemplate”/> 

 

       </property> 

 

</bean>

<bean id=”courseDao” class=”com.springinaction.training.dao.hibernate.CourseDaoHibernate”>

      <property name=”hibernateTemplate”>

           <ref bean=”hibernateTemplate”/>

      </property>

</bean>

 

          And remember, if it becomes cumbersome to wire the template into each of your DAO beans, you can always use Spring’s autowire facility to implicitly wire your DAO beans. Now that you know how to wire a HibernateTemplate to your DAO objects, we are ready to start using Hibernate.

4.4.3 Accessing Hibernate through HibernateTemplate
           The template-callback mechanism in Hibernate is pretty simple. There is theHibernateTemplate and one callback interface: HibernateCallback. And the HibernateCallback interface has just one method:

           Object doInHibernate(Session session) throws HibernateException, SQLException;
          As you can see, the HibernateCallback interface is pretty straightforward. Now, let’s put the HibernateTemplate to use. We’ll begin by getting an object from the database:
         public Student getStudent(final Integer id) {
                  return (Student) hibernateTemplate.execute(
                                           new HibernateCallback() {
                                                   public Object doInHibernate(Session session)  throws HibernateException {
                    return session.load(Student.class, id);
                                                                                    }  });
          }
            Since we are using an inner class, a little more code is required and is not quite as clean as when we were not using Spring’s Hibernate support. But we can have it both ways—clean code and Spring Hibernate support. The HibernateTemplate class provides some convenience methods that implicitly create a HibernateCallback instance for you. All you have to do is call one of the convenience methods and Spring’s framework does the rest. For example, here is how you would take advantage of one of these methods to accomplish the exact same thing as we did earlier—get an object from the database:
        public Student getStudent(Integer id) {
                  return (Student) hibernateTemplate.load(Student.class, id);
         }
         Now we are getting somewhere! We now have the benefits of having Spring managing our resources, converting proprietary exceptions, and, if we choose, adding transactions. The previous example is how you will access Hibernate through the Hibernate template the majority of the time. The HibernateTemplate class contains a wealth of convenience methods for you to use. For example, to update a Student object, this is all that would be required:
       public void updateStudent(Student student) {
                    hibernateTemplate.update(student);
         }
         Executing queries is not that much different. All we need to do is specify the query (usually in Hibernate’s query language, HQL). Querying for students by last name would look something like this:
       public List findStudentsByLastName(String lastName) {
                return hibernateTemplate.find(“from Student student ” +  “where student.lastName = ?”,  lastName, Hibernate.STRING);
       }

        Pretty straightforward, right? Even if you have never seen HQL before, this
code should be easy to follow. As we said before, Spring’s framework makes for easy integration.

4.4.4 Subclassing HibernateDaoSupport :

          Spring’s Hibernate ORM framework also comes with the convenience class HibernateDaoSupport that your DAO classes can subclass:
           public class StudentDaoHibernate extends HibernateDaoSupport implements StudentDao {
              …
            }

          If you opt for this design, you need to wire in a SessionFactory—the Hibernate-DaoSupport class comes with this property. This class provides you with a convenience method, getHibernateTemplate(), to easily get an instance of a HibernateTemplate. It also has a getSession() and a closeSessionIfNecessary() method if, for some reason, you need to perform a Hibernate operation without using a Hibernate- Template. We are sure you will find these cases will be the exception (no pun intended). So now you can see how easily you can integrate an ORM tool like
Hibernate. We think you will find the JDO integration just as easy.

 

Tags:

One Response to “Spring JDBC with Hibernate”

  1. minhle Says:

    Do u experience about this topic . Pls shared with me .

Leave a Reply