XML Free Spring Hibernate Configuration

Introduction

After a lot of digging on the web I couldn't find any complete tutorial or example for an XML free Spring Hibernate Configuration tutorial to integrate Spring 3.X with Hibernate 4.X. So here I present a fully working simple tutorial for those who want to get rid of the XML configurations for Hibernate and Spring integration. Here is a link to my latest post, which develops a spring application from scratch, using annotation based spring, and hibernate.

Purpose of the Article

This article is to explain in the easiest possible manner the ways to integrate Hibernate 4.x with Spring 3.x without XML configurations. I will write another article for the XML lovers later.

Precaution

I always emphasize on using the compatible jars for all the possible technologies and frameworks. So I would recommend you to download hibernate distribution from here and download spring distribution from here Now after including both the distributions you might need some more jars listed below:
  • mysql-connector-java-5.1.6.jar - for database driver of MySQL
  • commons-dbcp.jar - database connectivity pool
  • commons-pool.jar
  • commons-logging-1.1.1.jar
  • aopalliance-1.0.jar

The Domain Model

CREATE TABLE `person` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `FIRST_NAME` varchar(45) NOT NULL, `LAST_NAME` varchar(45) NOT NULL, `AGE` int(11) NOT NULL, PRIMARY KEY (`ID`) ) If possible populate it with some values.

Model class corresponding to Domain Model

package com.test.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "PERSON")
public class Person implements Serializable {

	private static final long serialVersionUID = -329211977029380182L;

	@Id
	@GeneratedValue
	@Column(name = "ID")
	private Long id;

	@Column(name = "FIRST_NAME")
	private String firstName;

	@Override
	public String toString() {
		return "Person [id=" + id + ", firstName=" + firstName + ", lastName="
				+ lastName + ", age=" + age + "]";
	}

	@Column(name = "LAST_NAME")
	private String lastName;

	@Column(name = "AGE")
	private String age;

	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 String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}
}

The Annotated Application Configuration

This will be the equavalent to the traditional spring-context.xml files in the older generation of Spring. Below is the code for the same and we will try and revisit the meaning of each line here:
package com.test.config;

import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.test.service.TestService;
import com.test.service.TestServiceImpl;

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:app.properties")
@ComponentScan(basePackages = "com.test", excludeFilters = { @ComponentScan.Filter(Configuration.class) })
public class AppConfig {
	@Autowired
	Environment env;

	@Bean(name = "dataSource")
	public DataSource getDataSource() {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
		dataSource.setUrl(env.getProperty("jdbc.databaseurl"));
		dataSource.setUsername(env.getProperty("jdbc.username"));
		dataSource.setPassword(env.getProperty("jdbc.password"));
		return dataSource;
	}

	@Bean(name = "sessionFactory")
	public SessionFactory getSessionFactory() throws Exception {
		Properties properties = new Properties();
		properties.put("hibernate.dialect", env.getProperty("jdbc.dialect"));
		properties.put("hibernate.show_sql", "true");
		properties.put("current_session_context_class", "thread");
		LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
		factory.setPackagesToScan(new String[] { "com.test.model" });
		factory.setDataSource(getDataSource());
		factory.setHibernateProperties(properties);
		factory.afterPropertiesSet();
		return factory.getObject();
	}

	@Bean(name = "transactionManager")
	public HibernateTransactionManager getTransactionManager() throws Exception {
		return new HibernateTransactionManager(getSessionFactory());
	}
		
	@Bean(name="service")
	public TestService service(){
		return new TestServiceImpl();
	}
}

@Configuration - is equivalent to and it tells that this class should be considered as one of the configuration classes. @EnableTransactionManagement - this is the alternative to in spring xml. @PropertySource("classpath:app.properties") - means load a properties file app.properties which is present in the classpath. @ComponentScan(basePackages = "com.test", excludeFilters = { @ComponentScan.Filter(Configuration.class) }) - is equivalent to which means it will scan all the packages whose base package is com.test
@Autowired
Environment env;
the Environment class serves as the property holder and stores all teh properties loaded by the @PropertySource
	@Bean(name = "dataSource")
	public DataSource getDataSource() {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
		dataSource.setUrl(env.getProperty("jdbc.databaseurl"));
		dataSource.setUsername(env.getProperty("jdbc.username"));
		dataSource.setPassword(env.getProperty("jdbc.password"));
		return dataSource;
	}
this configures the dataSource for the SessionFactory.
	@Bean(name = "sessionFactory")
	public SessionFactory getSessionFactory() throws Exception {
		Properties properties = new Properties();
		properties.put("hibernate.dialect", env.getProperty("jdbc.dialect"));
		properties.put("hibernate.show_sql", "true");
		properties.put("current_session_context_class", "thread");
		LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
		factory.setPackagesToScan(new String[] { "com.test.model" });
		factory.setDataSource(getDataSource());
		factory.setHibernateProperties(properties);
		factory.afterPropertiesSet();
		return factory.getObject();
	}
This configures the session factory and also serves as the alternative to hibernate's hibernat.cfg.xml file. The line factory.setPackagesToScan(new String[] { "com.test.model" }); serves as an alternative to the hbm mapping file.
@Bean(name = "transactionManager")
	public HibernateTransactionManager getTransactionManager() throws Exception {
		return new HibernateTransactionManager(getSessionFactory());
	}
This creates a transactionManager bean of type HibernateTransactionManager and sets the sessionFactory to it.
@Bean(name="service")
	public TestService service(){
		return new TestServiceImpl();
	}
Creates a bean for the service layer, this can be later fetched in any class to subsequently invoke the DAO layer methods.

Service Layer

As this is not a complete application and the motive is to enable the reader to udnerstand and bring up a simple application running, we create a service layer interface with just one method to fetch the records.
package com.test.service;

import java.util.List;

import com.test.model.Person;

public interface TestService {
	public List getPersons();
}
The implementation for the above interface follows:
package com.test.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.test.dao.TestDAO;
import com.test.model.Person;

@Service
public class TestServiceImpl implements TestService {

	@Autowired
	TestDAO testDAO;

	@Override
	@Transactional
	public List getPersons() {
		return testDAO.fetchPersons();
	}
}
Please note the @Transactional annotation, nothing specific about it, if you do not put this annotation you might face some errors. ONe of them is below:
org.hibernate.HibernateException: No Session found for current thread

The DAO layer

The DAO layer just fetches the list of persons and returns as it is to the service layer. THe interface for the DAO layer is defined below:
package com.test.dao;

import java.util.List;

import com.test.model.Person;

public interface TestDAO {
	public List fetchPersons();
}

The implementation of the above interface is provided below:
package com.test.dao;

import java.util.List;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.test.model.Person;

@Repository
public class TestDAOImpl implements TestDAO {

	@Autowired
	SessionFactory sessionFactory;

	@SuppressWarnings("unchecked")
	@Override
	public List fetchPersons() {
		return sessionFactory.getCurrentSession().createQuery("from Person")
				.list();
	}

}

Bootstrapping the application

Lets write a class with a main method which will initiate the whole process
package com.test.main;

import java.util.List;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.test.config.AppConfig;
import com.test.model.Person;
import com.test.service.TestService;

public class Bootstrap {
	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
				AppConfig.class);
		List persons = ((TestService) context.getBean("service"))
				.getPersons();
		System.out.println(persons);
	}
}

Explanation: Get the instance of AnnotationConfigApplicationContext created by the AppConfig configuration class, then fetch the service bean from the context and invoke the getPersons() method to fetch the list of persons.

Application properties file

Below is the app.properties file. You can place it in the src folder of your project, it will automatically get into the classpath. You can place it whereever you want, please make sure it is in the classpath.
jdbc.driverClassName= com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.databaseurl=jdbc:mysql://localhost:3306/dms
jdbc.username=root
jdbc.password=password

Source Code

Please find the source code attached here. This doesn't include any jar file. Source Code

Conclusion

You can actually use this whole setup in a REST web-service , a web applcaition or any other setup. THe purpose is to show the basic setup and if you run the Bootstrap class you will see the list of persons displayed on the console. Thank to the spring blog here which helped me complete this article. Stay connected and stay Subscribed