In our earlier post we saw how Spring can be integrated with JDBC. Spring also provides a similar template class for use with Hibernate - org.springframework.orm.hibernate3.HibernateTemplate.
The class provides us with the following main advantages:
I decided to implement the IPersonDAO using this template.
The hbm file and the Model class is as below:
Note: In the above code no transaction support has been added as such. I have been dependent on the auto-commit behavior provided by the HibernateTemplate So if a load call were to be made then I would end with a lazy load exception.
Also there is an additional setting in the sessionFactory implementation that I came across. Certain blogs advised setting it to false.
The code to test the DAO is as follows:
The class provides us with the following main advantages:
- Converts HibernateExceptions into DataAccessExceptions
- Provides Hibernate Session handling such as retrieving/closing Hibernate Sessions.
- Its capability to fall back to 'auto-commit' style behavior when used outside of transactions.
- Provides a host of convenience methods
I decided to implement the IPersonDAO using this template.
public class PersonTemplateDAO implements IPersonDAO { private HibernateTemplate hibernateTemplate; public final void setHibernateTemplate(HibernateTemplate hibernateTemplate) { this.hibernateTemplate = hibernateTemplate; } public final HibernateTemplate getHibernateTemplate() { return this.hibernateTemplate; } //other methods }In the above case we need to create the HbernateTemplate bean and wire it into our DAO class. The other option is to extend the DAO Support class provided by Spring.
public class PersonTemplateDAO extends HibernateDaoSupport implements IPersonDAO {In this case we can either directly wire the class with HibernateTemplate bean (like above) or we wire the class with a sessionFactory. The DAO Support class will then automatically create the Hibernate Template internally.
<bean id="PersonDAO" class="com.data.dao.PersonTemplateDAO" > <property name="sessionFactory" ref="sessionFactory" /> </bean>The SessionFactory implementation we use here is a Spring implementation.
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <!-- The dataSource property is wired with a reference to a DataSource bean. --> <property name="dataSource" ref="c3pDataSource" /> <!-- The mappingResources property lists one or more Hibernate mappings --> <property name="mappingResources"> <list> <value>com/data/model/Person.hbm.xml </value> </list> </property> <!-- hibernateProperties is where we configure the details of Hibernate working --> <property name="hibernateProperties"> <props> <prop key="dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">create</prop> </props> </property> </bean>This is an example of a FactoryBean. The above implementation is used if we are working with hbm files.The object takes a reference to the data source in operation.
The hbm file and the Model class is as below:
<?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 package="com.data.model"> <class name="Person"> <meta attribute="class-description">This is a person table</meta> <id name="id" type="long" column="ID"> <generator class="identity" /> </id> <property name="name" type="string" column="NAME" /> <property name="age" type="integer" column="AGE" /> </class> </hibernate-mapping>The Model class:
public class Person { private String name; private Long id; private Integer age; //getter, setters }The DAO class is as below:
public class PersonTemplateDAO extends HibernateDaoSupport implements IPersonDAO { private static final Logger logger = Logger .getLogger(PersonTemplateDAO.class); @SuppressWarnings("unchecked") @Override public List<Person> getAllPersons() { logger.debug("getAllPersons from system"); List<Person> persons = new ArrayList<Person>(0); persons = this.getHibernateTemplate().find("from Person"); logger.debug("Total Retrieved items : " + persons.size()); return persons; } @Override public int findTotalPersons() { logger.debug("findTotalPersons: fetching record count "); return this.getHibernateTemplate().find("from PERSON").size(); } @Override public Person getPersonById(final long personId) { logger.debug("fetching record with id : " + personId); return (Person) this.getHibernateTemplate() .get(Person.class, personId); } @Override public void updatePerson(final Person person) { this.getHibernateTemplate().update(person); } @Override public void save(Person person) { this.getHibernateTemplate().save(person); } @Override public void delete(Person person) { this.getHibernateTemplate().delete(person); } }In the above code there is no open session or close session code. All that is internally manged by the HibernateTemplate. We in fact have a reduced need to work with Hibernate directly using the Hibernate API. We have the find method that can work with HQL. Also the template exposes utility methods for save, get, delete etc.
Note: In the above code no transaction support has been added as such. I have been dependent on the auto-commit behavior provided by the HibernateTemplate So if a load call were to be made then I would end with a lazy load exception.
Also there is an additional setting in the sessionFactory implementation that I came across. Certain blogs advised setting it to false.
<property name="exposeTransactionAwareSessionFactory"><value>false</value></property>I wen through the Spring code and came across the documentation for the setter method for above property:
Set whether to expose a transaction-aware current Session from the SessionFactory's <code>getCurrentSession()</code> method, returning the Session that's associated with the current Spring-managed transaction, if any. <p>Default is "true", letting data access code work with the plain Hibernate SessionFactory and its <code>getCurrentSession()</code> method, while still being able to participate in current Spring-managed transactions: with any transaction management strategy, either local or JTA / EJB CMT, and any transaction synchronization mechanism, either Spring or JTA. Furthermore, <code>getCurrentSession()</code> will also seamlessly work with a request-scoped Session managed by OpenSessionInViewFilter/Interceptor. <p>Turn this flag off to expose the plain Hibernate SessionFactory with Hibernate's default <code>getCurrentSession()</code> behavior, supporting plain JTA synchronization only. Alternatively, simply override the corresponding Hibernate property "hibernate.current_session_context_class".I did not use it nor did I use the current_session_context_class property.
<prop key="current_session_context_class">thread</prop>
The code to test the DAO is as follows:
public static void main(String[] args) { //final XmlBeanFactory beanFactory =
//new XmlBeanFactory(new ClassPathResource("spring-hib-template.xml")); final ApplicationContext beanFactory =
new ClassPathXmlApplicationContext("spring-hib-template.xml"); IPersonDAO personDAO = (IPersonDAO) beanFactory.getBean("personDAO"); System.out.println(personDAO); testPersonLifeCycle(personDAO); } public static void testPersonLifeCycle(final IPersonDAO personDAO) { Person person = new Person(); person.setName("Vinod"); person.setAge(26); personDAO.save(person); final Long personId = person.getId(); System.out.println("Person was saved with id " + personId); person = personDAO.getPersonById(personId); person.setName("Raja"); personDAO.updatePerson(person); System.out.println("Person with id " +personId + " was updated"); person = personDAO.getPersonById(personId); System.out.println("Person with id " + personId + " is "
+ person.getName() + " and age is " + person.getAge()); personDAO.delete(person); System.out.println("person with id " + personId
+ " has been deleted successfully");
}
In the next post we shall used at the new and recommended style of integrating Spring and Hibernate.
Thanks Robin very nice blog. nice explanation.
ReplyDeletecan you explain like how to pass parameter in getHibernateTemplate
for example : how to add 2-3 joins in query in getHibernateTemplate().find method.