Spring and Hibernate Integration....


Integrating Hibernate with Spring

I tried to learn how to integrate Hibernate with Spring and found very useful information in Spring in Action by Craig Walls.
Before getting started let me tell you about the example I have used in this article.

I am having a very basic table in database

CREATE TABLE  sample (
  id int(10) unsigned NOT NULL AUTO_INCREMENT,
  name varchar(45) NOT NULL,
  city varchar(45) NOT NULL,
  PRIMARY KEY (id)
) ;


and here is Sample.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping >
    <class name="hibernate.Sample" table="sample" lazy="false">
    
        <id name="id" column="id" type="java.lang.Long">
            <generator class="increment"/>
        </id>
        <property name="name" type="string"/>
        <property name="city" type="string"/>
        
    </class>
</hibernate-mapping>


and here is Sample bean.

public class Sample implements Serializable{
 
 private Long id;
 private String name;
 private String city;
 
 // getters and setters
}


Now let us get into detail... 

The standard way to get a reference to a Hibernate Session object is through an implementation of Hibernate’s SessionFactory interface. Among other things, SessionFactory is responsible for opening, closing, and managing Hibernate Sessions.

The first thing you’ll need to do is to configure a Hibernate session factory bean in Spring.

Spring’s HibernateTemplate provides an abstract layer over a Hibernate Session. HibernateTemplate’s main responsibility is to simplify the work of opening and closing Hibernate Sessions and to convert Hibernate-specific exceptions to one of the Spring ORM exceptions (In the case of Hibernate 2, this means converting a checked HibernateException to an unchecked Spring exception.)

The following XML shows how to configure a HibernateTemplate in Spring:

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
 <property name="sessionFactory" ref="sessionFactory" />
</bean>


The sessionFactory property takes a reference to an implementation of org.hibernate.SessionFactory. Here you have a few options, depending on
how you use Hibernate to map your objects to database tables.

-> If you are using Hibernate’s classic XML mapping files, you’ll want to use Spring’s LocalSessionFactoryBean.

LocalSessionFactoryBean is a Spring factory bean that produces a local Hibernate SessionFactory instance that draws its mapping metadata from one or more XML mapping files.

how to configure a LocalSessionFactory-Bean that loads the mapping files for the RoadRantz domain objects:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
 <property name="dataSource" ref="dataSource" />
 <property name="mappingResources">
  <list>
   <value>hibernate/Sample.hbm.xml</value> 
  </list>
 </property>
 <property name="hibernateProperties">
  <props>
   <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
   <prop key="show_sql">true</prop>
  </props>
 </property>
</bean>


-> For annotation-based Hibernate, Spring’s AnnotationSessionFactoryBean works much like LocalSessionFactoryBean, except that it creates a SessionFactory based on annotations in one or more domain classes.

The XML required to configure an AnnotationSessionFactoryBean in Spring is similar to the XML for LocalSessionFactoryBean:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
 <property name="dataSource" ref="dataSource" />
 <property name="annotatedClasses">
  <list>
   <value>hibernate.Sample</value>
  </list>
 </property>
 <property name="hibernateProperties">
  <props>
   <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
   <prop key="show_sql">true</prop>
  </props>
 </property>
</bean>


The dataSource and hibernateProperties properties serve the same purpose with AnnotationSessionFactoryBean as with LocalSessionFactoryBean. However, instead of configuring one or more mapping files, we must configure AnnotationSessionFactoryBean with one or more classes that are annotated for persistence with Hibernate.

With the HibernateTemplate bean declared and wired with a session factory, we’re ready to start using it to persist and retrieve objects from the database.

Injected HibernateTemplate into HibernateSampleDao. 

public class HibernateSampleDAO {
 
 private HibernateTemplate hibernateTemplate;

 public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
  this.hibernateTemplate = hibernateTemplate;
 } 

}


HibernateSampleDAO accepts a HibernateTemplate reference via setter injection. So configure it.

<bean id="hibSampleDAO" class="hibernate.HibernateSampleDAO">
 <property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>


saveSample() method that is used to persist a Sample object to the database:

public void saveSample(Sample sample) {
 hibernateTemplate.saveOrUpdate(sample);
}


The saveOrUpdate() method inspects the object to see if its ID field is null. If it is, it must be a new object and thus it is inserted into the database. If it’s not null, it is assumed that it is an existing object and its data is updated.


Now let us look at findSampleByCity() method that uses HibernateTemplate’s find() method to retrieve a Sample by querying by the cityName.

public Sample findSampleByCity(String city) {
 List<Sample> results = hibernateTemplate.find("from Sample sample"+
   " where city = ?",new Object[] {city});
  return results.size() > 0 ? (Sample) results.get(0) : null;
} 


And here’s how you might use HibernateTemplate’s load() method to load a specific instance of a Sample by the sample’s ID field:

public Sample getSampleById(Long id) {
 return (Sample)hibernateTemplate.load(Sample.class, id);
}


So far, the configuration of HibernateSampleDAO involves four beans. The datasource is wired into the session factory bean (either LocalSessionFactoryBean or AnnotationSessionFactoryBean). The session factory bean is wired into the HibernateTemplate. Finally, the HibernateTemplate is wired into HibernateSampleDAO, where it is used to access the database.

To simplify things slightly, Spring offers HibernateDaoSupport, a convenience DAO support class, that enables you to wire a session factory bean directly into the DAO class. Under the covers, HibernateDaoSupport creates a HibernateTemplate that the DAO can use.

Let’s rework HibernateSampleDAO to use HibernateDaoSupport. The first step is to change HibernateSampleDAO to extend HibernateDaoSupport:

public class HibernateSampleDAO extends HibernateDaoSupport {}


HibernateSampleDAO no longer needs a HibernateTemplate property as it did in previous example. Instead, you can use the getHibernateTemplate() method to get a HibernateTemplate that HibernateDaoSupport creates for you. So, the next step is to change all the data access methods in HibernateSampleDAO to use getHibernateTemplate().

For example, here’s the saveSample() method updated for the new HibernateDaoSupport-based HibernateSampleDAO:

public void saveSample(Sample sample) {
 getHibernateTemplate().saveOrUpdate(sample);
}


HibernateSampleDAO no longer needs a HibernateTemplate reference, so you can remove it. Instead of a Hibernate-Template, you can directly give reference of a Hibernate SessionFactory so that it can produce a HibernateTemplate internally.

<bean id="hibSampleDAO" class="hibernate.HibernateSampleDAO">
 <property name="sessionFactory" ref="sessionFactory"/>
</bean>


If you think of extending Spring specific class as an intrusion of Spring into your application code, then you can take advantage of Hibernate 3’s support for contextual sessions to remove Spring-specific dependencies from your DAOs.

Using Hibernate 3 contextual sessions:

Contextual sessions, introduced in Hibernate3, are a way in which Hibernate itself manages one Session per transaction.

There’s no need for HibernateTemplate to ensure this behavior. So, instead of wiring a HibernateTemplate into your DAO, you can wire a Hibernate Session-Factory.

public class HibernateSampleDAO{private SessionFactory sessionFactory;
 public void setSessionFactory(SessionFactory sessionFactory) {
  this.sessionFactory = sessionFactory;
 }
}


In this new HibernateSampleDAO, a SessionFactory reference is injected into the sessionFactory property. Since SessionFactory comes from the Hibernate API, HibernateSampleDAO no longer depends on the Spring Framework. Instead of using HibernateTemplate to perform persistence operations, you now ask the Session-Factory for the current session.

public void saveSample(Sample sample) {
 sessionFactory.getCurrentSession().saveOrUpdate(sample);
}


Configuring this HibernateRantDao is similar to that of HibernateDaoSupport-based version.

Both HibernateDaoSupport and our new pure-Hibernate version of HibernateSampleDao require a Hibernate SessionFactory to be wired into their sessionFactory property. In either case, the sessionFactory bean (which is a SessionFactory-producing LocalSessionFactoryBean or AnnotationSession-FactoryBean) is suitable

<bean id="hibSampleDAO" class="hibernate.HibernateSampleDAO">
 <property name="sessionFactory" ref="sessionFactory" />
</bean>


Note :
-> If you’re using Hibernate 2 then you have no other option than to use HibernateTemplate.

-> The main benefit of Hibernate contextual sessions is that they decouple your DAO implementations from Spring.

-> The primary drawback of contextual sessions is that they throw Hibernatespecific exceptions. Although HibernateException is a runtime exception, the exception hierarchy is specific to Hibernate and not as ORM-agnostic as Spring’s persistence exception hierarchy. This may hinder migration to a different ORM solution.

Hope it will be useful...

Comments

Popular posts from this blog

How to get the tweets using Kafka producer and Consume it using MongoDB

Monolithic vs Micro Services

AngularJS Flow