It is actually quite easy to get Spring to manage your Hibernate sessions and inject them into your web handlers. There's just some config files that need some hard-to-find values. Here i'll show you the basics, from the perspective of a Struts2 application, although it'll be mostly the same for whichever web framework you use. Your WebContent\WEB-INF\applicationContext.xml file will look like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

  <!-- The singleton hibernate session factory -->
  <bean id="sessionFactory" scope="singleton"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="configLocation" value="classpath:hibernate.cfg.xml" />
  </bean>

  <!-- Spring's hibernate transaction manager, in charge of making hibernate sessions/txns -->
  <bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
  </bean>

  <!-- So classes/functions with @Transactional get a hibernate txn -->
  <tx:annotation-driven />
  
  <!-- The singleton business services class, to be given to the actions -->
  <bean id="services" class="services.Services" scope="singleton">
    <property name="sessionFactory" ref="sessionFactory" />
  </bean>
  
</beans>
You'll then want a singleton business services class (or more than one) that looks like this. The idea is that spring passes it the session factory, and the @Transactional annotation tells spring to create hibernate sessions and transactions accordingly, so that the sessionFactory.getCurrentSession() always returns the appropriate session. In my case, this is named src\services\Services.java:
package services;
import org.springframework.transaction.annotation.Transactional;
import org.hibernate.SessionFactory;
import org.hibernate.Session;
import data.Event; // An example of a hibernate data class

// This class is the business services tier in the application.
// @Transactional is needed so that a Hibernate transaction is set up,
//  otherwise updates won't have an affect
@Transactional
public class Services {
  // So Spring can inject the session factory
  protected SessionFactory sessionFactory;
  public void setSessionFactory(SessionFactory value) {
    sessionFactory = value;
  }

  // Shortcut for sessionFactory.getCurrentSession()
  protected Session sess() {
    return sessionFactory.getCurrentSession();
  }

  // Example of a typical business service function
  public Event getEventById(long id) {
    return (Event) sess().load(Event.class, id);
  }
}
Your WebContent\WEB-INF\web.xml will need these lines in your <web-app> section:
<!-- Spring -->
  <listener> <!-- Required for the struts2 spring plugin to work -->
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <filter> <!-- Get spring to keep the session open for the whole request, so hibernate's lazy loads work -->
    <filter-name>openSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>openSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern> 
  </filter-mapping>
Your src\hibernate.cfg.xml should look like this (in this case, i'm using jtds to access a sql server):
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <!-- Database connection settings -->
    <property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
    <property name="connection.url">jdbc:jtds:sqlserver://DATABASE-SERVER-NAME/DATABASE-SCHEMA</property>
    <property name="connection.username">USERNAME</property>
    <property name="connection.password">PASSWORD</property>
    <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>

    <!--
      Enable c3p0 connection pooling, because hibernate pooling is not
      prod-ready. Apparently connection.provider_class is needed in
      hibernate 3+
    -->
    <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
    <property name="c3p0.max_size">100</property>
    <property name="c3p0.min_size">1</property>
    <property name="c3p0.idle_test_period">30</property>

    <!-- Echo all executed SQL to stdout for debugging -->
    <property name="show_sql">true</property>

    <!-- All the entity classes for hibernate to check for annotations here -->
    <mapping class="data.Whatever" />
  </session-factory>
</hibernate-configuration>
And in your Struts2 actions (or whatever is appropriate for your web framework of choice), you'll need a setter to receive the business services class:
package actions.base;

import services.Services;
import com.opensymphony.xwork2.ActionSupport;

public class SomeAction extends ActionSupport {
  // So that spring can inject the business singleton
  protected Services services;
  public void setServices(Services value) {
    services=value;
  }
  
  public String execute() {
    Event event = services.getEventById(1); // Just an example
    return "success";
  }
}
Also, if you're using Struts2, you'll need the struts2-spring-plugin-2.*.jar in your WebContent\WEB-INF\lib folder. Other frameworks will probably need something else done so that they use Spring to create and pass the business services to their actions/request handlers. That should be it! I'll have to leave it up to you to figure out what JARs you need, but if you're a Java person, that's half the fun of it ;) Any questions on the specifics here, feel free to fire away in the comments section!

Thanks for reading! And if you want to get in touch, I'd love to hear from you: chris.hulbert at gmail.

Chris Hulbert

(Comp Sci, Hons - UTS)

Software Developer (Freelancer / Contractor) in Australia.

I have worked at places such as Google, Cochlear, Assembly Payments, News Corp, Fox Sports, NineMSN, FetchTV, Coles, Woolworths, Trust Bank, and Westpac, among others. If you're looking for help developing an iOS app, drop me a line!

Get in touch:
[email protected]
github.com/chrishulbert
linkedin



 Subscribe via RSS