Categories: spring

Spring 4 + Hibernate 4 + MySQL+ Maven Integration example (Annotations+XML)

In this tutorial , we will integrate Spring 4 with Hibernate 4 using annotation based configuration. We will develop a simple CRUD java application, creating hibernate entities, saving data in MySQL database , performing database CRUD operations within transaction, and learn how different layers interacts with each-other in typical enterprise application, all using annotation based configuration. We will also see corresponding XML configuration side-by-side for comparison.

For Spring MVC based application, checkout Spring4 MVC Hibernate and MySQL integration. Let’s get going.


Following technologies being used:

  • Spring 4.0.6.RELEASE
  • Hibernate Core 4.3.6.Final
  • MySQL Server 5.6
  • Joda-time 2.3
  • Maven 3
  • JDK 1.6
  • Eclipse JUNO Service Release 2

Project directory structure

Let’s now add the content mentioned in above structure explaining each in detail.

Step 1: Update pom.xml to include required dependencies

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

 <modelVersion>4.0.0</modelVersion>
 <groupId>com.websystique.spring</groupId>
 <artifactId>Spring4HibernateExample</artifactId>
 <version>1.0.0</version>
 <packaging>jar</packaging>

 <name>Spring4HibernateExample</name>

 <properties>
  <springframework.version>4.0.6.RELEASE</springframework.version>
  <hibernate.version>4.3.6.Final</hibernate.version>
  <mysql.connector.version>5.1.31</mysql.connector.version>
  <joda-time.version>2.3</joda-time.version>
 </properties>

 <dependencies>

  <!-- Spring -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-tx</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-orm</artifactId>
   <version>${springframework.version}</version>
  </dependency>

  <!-- Hibernate -->
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>${hibernate.version}</version>
  </dependency>

  <!-- MySQL -->
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>${mysql.connector.version}</version>
  </dependency>

  <!-- Joda-Time -->
  <dependency>
   <groupId>joda-time</groupId>
   <artifactId>joda-time</artifactId>
   <version>${joda-time.version}</version>
  </dependency>

  <!-- To map JodaTime with database type -->
  <dependency>
   <groupId>org.jadira.usertype</groupId>
   <artifactId>usertype.core</artifactId>
   <version>3.0.0.CR1</version>
  </dependency>

 </dependencies>
 <build>
  <pluginManagement>
   <plugins>
    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-compiler-plugin</artifactId>
     <version>3.2</version>
     <configuration>
      <source>1.6</source>
      <target>1.6</target>
     </configuration>
    </plugin>
   </plugins>
  </pluginManagement>
 </build>

</project>

Spring, Hibernate & MySQL connector dependencies are pretty obvious. We have also included joda-time as we will use joda-time library for any date manipulation. usertype-core is included to provide the mapping between database date-type and joda-time LocalDate.

Step 2: Configure Hibernate

com.websystique.spring.configuration.HibernateConfiguration

package com.websystique.spring.configuration;

import java.util.Properties;

import javax.sql.DataSource;

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.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.websystique.spring.configuration" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {

    @Autowired
    private Environment environment;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[] { "com.websystique.spring.model" });
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
     }
 
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
        dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
        dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
        dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
        return dataSource;
    }
    
    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
        return properties;        
    }
    
 @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) {
       HibernateTransactionManager txManager = new HibernateTransactionManager();
       txManager.setSessionFactory(s);
       return txManager;
    }
}

@Configuration indicates that this class contains one or more bean methods annotated with @Bean producing beans manageable by spring container. In our case, this class represent hibernate configuration.
@ComponentScan is equivalent to context:component-scan base-package="..." in xml, providing with where to look for spring managed beans/classes.
@EnableTransactionManagement is equivalent to Spring’s tx:* XML namespace, enabling Spring’s annotation-driven transaction management capability.
@PropertySource is used to declare a set of properties(defined in a properties file in application classpath) in Spring run-time Environment, providing flexibility to have different values in different application environments.

Method sessionFactory() is creating a LocalSessionFactoryBean, which exactly mirrors the XML based configuration : We need a dataSource and hibernate properties (same as hibernate.properties). Thanks to @PropertySource, we can externalize the real values in a .properties file, and use Spring’s Environment to fetch the value corresponding to an item. Once the SessionFactory is created, it will be injected into Bean method transactionManager which may eventually provide transaction support for the sessions created by this sessionFactory.

Below is the properties file used in this post.

Below is the properties file used in this post.
/src/main/resources/application.properties

jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/websystique
jdbc.username = myuser
jdbc.password = mypassword
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = false
hibernate.format_sql = false

Corresponding XML based Hibernate configuration

<?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:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
             http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

 
 <context:property-placeholder location="classpath:application.properties" />
 
 <context:component-scan  base-package="com.websystique.spring" />
 
 <tx:annotation-driven transaction-manager="transactionManager"/>
 
 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="${jdbc.driverClassName}" />
  <property name="url" value="${jdbc.url}"/>
  <property name="username" value="${jdbc.username}" />
  <property name="password" value="${jdbc.password}"/>
  
   </bean>
 
 <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
  <property name="dataSource" ref="dataSource"/>
  <property name="packagesToScan">
   <list>
    <value>com.websystique.spring.model</value>
   </list>
  </property>
  <property name="hibernateProperties">
   <props>
     <prop key="hibernate.dialect">${hibernate.dialect}</prop>
    <prop key="hibernate.show_sql">${hibernate.show_sql:false}</prop>
    <prop key="hibernate.format_sql">${hibernate.format_sql:false}</prop>
   </props>
  </property>  
 </bean>

 <bean id="transactionManager"  class="org.springframework.orm.hibernate4.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory" />
    </bean>

 <bean id="persistenceExceptionTranslationPostProcessor"
     class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
     
</beans>

Step 3: Configure Spring

com.websystique.spring.configuration.AppConfig

package com.websystique.spring.configuration;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.websystique.spring")
public class AppConfig {

}

In our simple example, this class is empty and only reason for it’s existence is @ComponentScan which provides beans auto-detection facility. You may completely remove above configuration and put the component scan logic in application context level (in Main ). In full-fledged applications, you may find it handy to configure some beans (e.g. messageSource, PropertySourcesPlaceHolderConfigurer) in Configuration class.

Corresponding XML based Spring Configuration

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
 <context:component-scan base-package="com.websystique.spring" />
 
</beans>

As for as Annotation based configuration goes, this is all we need to do. Now to make the application complete, we will add service layer, dao layer, Domain object, sample database schema and run the application.

Step 4: Add DAO Layer

com.websystique.spring.dao.AbstractDao

package com.websystique.spring.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class AbstractDao {

 @Autowired
 private SessionFactory sessionFactory;

 protected Session getSession() {
  return sessionFactory.getCurrentSession();
 }

 public void persist(Object entity) {
  getSession().persist(entity);
 }

 public void delete(Object entity) {
  getSession().delete(entity);
 }
}

Notice above, that SessionFactory we have created earlier in step 2, will be auto-wired here.This class serve as base class for database related operations.

com.websystique.spring.dao.EmployeeDao

package com.websystique.spring.dao;

import java.util.List;

import com.websystique.spring.model.Employee;

public interface EmployeeDao {

 void saveEmployee(Employee employee);
 
 List<Employee> findAllEmployees();
 
 void deleteEmployeeBySsn(String ssn);
 
 Employee findBySsn(String ssn);
 
 void updateEmployee(Employee employee);
}

com.websystique.spring.dao.EmployeeDaoImpl

package com.websystique.spring.dao;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.websystique.spring.model.Employee;

@Repository("employeeDao")
public class EmployeeDaoImpl extends AbstractDao implements EmployeeDao{

 public void saveEmployee(Employee employee) {
  persist(employee);
 }

 @SuppressWarnings("unchecked")
 public List<Employee> findAllEmployees() {
  Criteria criteria = getSession().createCriteria(Employee.class);
  return (List<Employee>) criteria.list();
 }

 public void deleteEmployeeBySsn(String ssn) {
  Query query = getSession().createSQLQuery("delete from Employee where ssn = :ssn");
  query.setString("ssn", ssn);
  query.executeUpdate();
 }

 
 public Employee findBySsn(String ssn){
  Criteria criteria = getSession().createCriteria(Employee.class);
  criteria.add(Restrictions.eq("ssn",ssn));
  return (Employee) criteria.uniqueResult();
 }
 
 public void updateEmployee(Employee employee){
  getSession().update(employee);
 }
 
}

Step 5: Add Service Layer

com.websystique.spring.service.EmployeeService

package com.websystique.spring.service;

import java.util.List;

import com.websystique.spring.model.Employee;

public interface EmployeeService {

 void saveEmployee(Employee employee);

 List<Employee> findAllEmployees();

 void deleteEmployeeBySsn(String ssn);

 Employee findBySsn(String ssn);

 void updateEmployee(Employee employee);
}

com.websystique.spring.service.EmployeeServiceImpl

package com.websystique.spring.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.websystique.spring.dao.EmployeeDao;
import com.websystique.spring.model.Employee;

@Service("employeeService")
@Transactional
public class EmployeeServiceImpl implements EmployeeService{

 @Autowired
 private EmployeeDao dao;
 
 public void saveEmployee(Employee employee) {
  dao.saveEmployee(employee);
 }

 public List<Employee> findAllEmployees() {
  return dao.findAllEmployees();
 }

 public void deleteEmployeeBySsn(String ssn) {
  dao.deleteEmployeeBySsn(ssn);
 }

 public Employee findBySsn(String ssn) {
  return dao.findBySsn(ssn);
 }

 public void updateEmployee(Employee employee){
  dao.updateEmployee(employee);
 }
}

Most interesting part above is @Transactional which starts a transaction on each method start, and commits it on each method exit ( or rollback if method was failed due to an error). Note that since the transaction are on method scope, and inside method we are using DAO, DAO method will be executed within same transaction.

Step 6: Create Domain Entity Class(POJO)

Let’s create the actual Employee Entity itself whose instances we will be playing with in database.

com.websystique.spring.model.Employee

package com.websystique.spring.model;

import java.math.BigDecimal;

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

import org.hibernate.annotations.Type;
import org.joda.time.LocalDate;

@Entity
@Table(name="EMPLOYEE")
public class Employee {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private int id;

 @Column(name = "NAME", nullable = false)
 private String name;

 @Column(name = "JOINING_DATE", nullable = false)
 @Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
 private LocalDate joiningDate;

 @Column(name = "SALARY", nullable = false)
 private BigDecimal salary;
 
 @Column(name = "SSN", unique=true, nullable = false)
 private String ssn;

 public int getId() {
  return id;
 }

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

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public LocalDate getJoiningDate() {
  return joiningDate;
 }

 public void setJoiningDate(LocalDate joiningDate) {
  this.joiningDate = joiningDate;
 }

 public BigDecimal getSalary() {
  return salary;
 }

 public void setSalary(BigDecimal salary) {
  this.salary = salary;
 }

 public String getSsn() {
  return ssn;
 }

 public void setSsn(String ssn) {
  this.ssn = ssn;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + id;
  result = prime * result + ((ssn == null) ? 0 : ssn.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (!(obj instanceof Employee))
   return false;
  Employee other = (Employee) obj;
  if (id != other.id)
   return false;
  if (ssn == null) {
   if (other.ssn != null)
    return false;
  } else if (!ssn.equals(other.ssn))
   return false;
  return true;
 }

 @Override
 public String toString() {
  return "Employee [id=" + id + ", name=" + name + ", joiningDate="
    + joiningDate + ", salary=" + salary + ", ssn=" + ssn + "]";
 }
 
 
 

}

This is a standard Entity class annotated with JPA annotations @Entity, @Table, @Column along with hibernate specific annotation @Type which we are using to provide mapping between database date type and Joda-Time LocalDate

Step 7: Create Schema in database

CREATE TABLE EMPLOYEE(
    id INT NOT NULL auto_increment, 
    name VARCHAR(50) NOT NULL,
    joining_date DATE NOT NULL,
    salary DOUBLE NOT NULL,
    ssn VARCHAR(30) NOT NULL UNIQUE,
    PRIMARY KEY (id)
);

Please visit MySQL installation on Local PC in case you are finding difficulties in setting up MySQL locally.

Step 8: Create Main to run as Java Application

package com.websystique.spring;

import java.math.BigDecimal;
import java.util.List;

import org.joda.time.LocalDate;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

import com.websystique.spring.configuration.AppConfig;
import com.websystique.spring.model.Employee;
import com.websystique.spring.service.EmployeeService;

public class AppMain {

 public static void main(String args[]) {
  AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

  EmployeeService service = (EmployeeService) context.getBean("employeeService");

  /*
   * Create Employee1
   */  Employee employee1 = new Employee();
  employee1.setName("Han Yenn");
  employee1.setJoiningDate(new LocalDate(2010, 10, 10));
  employee1.setSalary(new BigDecimal(10000));
  employee1.setSsn("ssn00000001");

  /*
   * Create Employee2
   */  Employee employee2 = new Employee();
  employee2.setName("Dan Thomas");
  employee2.setJoiningDate(new LocalDate(2012, 11, 11));
  employee2.setSalary(new BigDecimal(20000));
  employee2.setSsn("ssn00000002");

  /*
   * Persist both Employees
   */  service.saveEmployee(employee1);
  service.saveEmployee(employee2);

  /*
   * Get all employees list from database
   */  List<Employee> employees = service.findAllEmployees();
  for (Employee emp : employees) {
   System.out.println(emp);
  }

  /*
   * delete an employee
   */  service.deleteEmployeeBySsn("ssn00000002");

  /*
   * update an employee
   */
  Employee employee = service.findBySsn("ssn00000001");
  employee.setSalary(new BigDecimal(50000));
  service.updateEmployee(employee);

  /*
   * Get all employees list from database
   */  List<Employee> employeeList = service.findAllEmployees();
  for (Employee emp : employeeList) {
   System.out.println(emp);
  }

  context.close();
 }
}

Note : In case you want to drop AppConfig altogether, in above main, you just have to replace

  AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

with

  AnnotationConfigApplicationContext  context = new AnnotationConfigApplicationContext();
  context.scan("com.websystique.spring"); 
  context.refresh();

Rest of code remains same. Run above program, you will see following output

Employee [id=1, name=Han Yenn, joiningDate=2010-10-10, salary=10000, ssn=ssn00000001]
Employee [id=2, name=Dan Thomas, joiningDate=2012-11-11, salary=20000, ssn=ssn00000002]
Employee [id=1, name=Han Yenn, joiningDate=2010-10-10, salary=50000, ssn=ssn00000001]

That’s it.

Download Source Code


References

View Comments

  • Thanks websystique for your great tutorial! Could you please show me how to integrate c3p0 in this example? Thank you very much.

  • Hello websystique.
    Thank you so much for your efforts.
    I've question here in this Spring4 Hibernate4 mysql tutorial. If i don't want to use MyApp and main method, instead Controller. Where should i configure below line.
    AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

    Thanks again.

  • Hi I have used same Xml configuration for my spring mvc project but it is giving it is giving nullPointerException when trying to use sessionFactory object for getSession().

    please find confgiuration file & source code.

    application-dao.xml

    com.edu.sms.entity

    org.hibernate.dialect.MySQL5Dialect
    true
    true

    @Repository
    @Transactional
    public class StudentDaoImpl implements StudentDao, InitializingBean {

    @Autowired
    private SessionFactory sessionFactory;

    protected Session getSession() {
    return sessionFactory.getCurrentSession();
    }

    public StudentBean save(StudentBean student) {
    getSession().persist(student);

    return student;
    }

    Please check.

  • Sir Thanks a lot of you.
    If I want to get user input from jsp form and insert more than one record to database like more than one Employee. How it enable? please known to me. Waiting for your response

  • Great tutorial - thanks for it! I also used the model here to create a similar small app that deals with the injection of beans responsible for creating a PDF and an Excel document - if interested, please let me know and I can e-mail you the source code.

  • Hi, websystique thank you for such a great tutorial.while deleting
    service.deleteEmployeeBySsn("ssn00000002");
    ends up with this
    exception"org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
    ERROR: Table 'websystique.Employee' doesn't exist". please help

  • Can you please explain the difference between @Service("employeeService") and @Repository("employeeDao")
    Thank you in Advance.

  • Hi,

    We have not define bean for EmployeeDao.
    But When you write
    @Autowired
    EmployeeDao employeeDao
    Then what is the mechanism to inject EmployeeDao dependency.Please help me.

    • Hello Avinash, It's more towards Spring promoting programming to interfaces. EmployeeDaoImpl Bean is an implementation of EmployeeDao which would eventulally be injected wherever asked. Eventually if you more than one implementation of that interface, then while injecting, you would need to specify which one Spring should be injecting using @Qualifier. Hope it helps.

  • Thanku very much, I have been looking for this kind of tutorial...It really helped me a lot...Thanks a lot...It works like a charm.....

Share
Published by

Recent Posts

Spring Boot + AngularJS + Spring Data + JPA CRUD App Example

In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…

7 years ago

Spring Boot Rest API Example

Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…

7 years ago

Spring Boot WAR deployment example

Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…

7 years ago

Spring Boot Introduction + hello world example

Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…

7 years ago

Secure Spring REST API using OAuth2

Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…

8 years ago

AngularJS+Spring Security using Basic Authentication

This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…

8 years ago