Spring MVC Hibernate MySQL Integration CRUD Example Tutorial
Spring MVC Hibernate MySQL Integration CRUD Example Tutorial
Example Tutorial
We learned how to integrate Spring and Hibernate in our last tutorial. Today we will move forward and
integrate Spring MVC and Hibernate frameworks in a web application CRUD example.
Our final project structure looks like below image, we will look into each of the components one by one.
Note that I am using Spring 4.0.3.Release and Hibernate 4.3.5.Final versions for our example, the same program is also
compatible for Spring 4 and Hibernate 3, however you need to make small changes in spring bean configuration
file discussed in the last tutorial.
Maven Dependencies
Let’s look at all the maven dependencies are required for hibernate and spring MVC framework integration.
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
</project>
Some of the dependencies above are included by STS (Spring Tool Suite) when I create Spring MVC project.
Important dependencies above are spring-context, spring-webmvc, spring-tx, hibernate-core, hibernate-
entitymanager and spring-orm. I am using Apache Commons DBCP for connection pooling, but in real life
situations, most probably you have connection pooling done by the container and all we need is to provide the
JNDI reference details to use.
NOTE: I noticed that some of the readers are getting database connection issues. Notice that in my pom.xml, there
is no database driver. That works for me because I have MySQL driver in tomcat lib directory and some DataSource
connections configured with it. For any database connection related issues, either put the database driver in
container lib or include that in pom.xml dependencies.
Deployment Descriptor
We need to plugin the spring framework in our web application, that is done by configuring Spring
framework DispatcherServlet as the front controller. Our web.xml file looks like below.
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Most of the part is boilerplate code, most important part is the spring context file location where we will configure
our spring beans and services. If you want, you can change them according to your project requirements.
We are using JPA annotations in our entity bean class, however, we can also have a simple java bean and mapping
details in the XML file. In that case, we need to provide mapping file details while configuring Hibernate
SessionFactory in spring bean configurations.
package com.journaldev.spring.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Entity bean with JPA annotations
* Hibernate provides JPA implementation
* @author pankaj
*
*/
@Entity
@Table(name="PERSON")
public class Person {
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Override
public String toString(){
return "id="+id+", name="+name+", country="+country;
}
}
Our entity bean maps to PERSON table in MySQL database, notice that I have not annotated “name” and “country”
fields with @Column annotation because they are of the same name. Below SQL script shows the table details.
We will create PersonDAO interface to declare the methods that we will use in our project. Next, we will provide
hibernate specific implementation for it.
package com.journaldev.spring.dao;
import java.util.List;
import com.journaldev.spring.model.Person;
package com.journaldev.spring.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import com.journaldev.spring.model.Person;
@Repository
public class PersonDAOImpl implements PersonDAO {
@Override
public void addPerson(Person p) {
Session session = this.sessionFactory.getCurrentSession();
session.persist(p);
logger.info("Person saved successfully, Person Details="+p);
}
@Override
public void updatePerson(Person p) {
Session session = this.sessionFactory.getCurrentSession();
session.update(p);
logger.info("Person updated successfully, Person Details="+p);
}
@SuppressWarnings("unchecked")
@Override
public List<Person> listPersons() {
Session session = this.sessionFactory.getCurrentSession();
List<Person> personsList = session.createQuery("from Person").list();
for(Person p : personsList){
logger.info("Person List::"+p);
}
return personsList;
}
@Override
public Person getPersonById(int id) {
Session session = this.sessionFactory.getCurrentSession();
Person p = (Person) session.load(Person.class, new Integer(id));
logger.info("Person loaded successfully, Person details="+p);
return p;
}
@Override
public void removePerson(int id) {
Session session = this.sessionFactory.getCurrentSession();
Person p = (Person) session.load(Person.class, new Integer(id));
if(null != p){
session.delete(p);
}
logger.info("Person deleted successfully, person details="+p);
}
}
Notice that I am not using Hibernate Transaction, that is because it will be taken care by Spring framework.
Here are our service classes that are using Hibernate DAO classes to work with Person objects.
package com.journaldev.spring.service;
import java.util.List;
import com.journaldev.spring.model.Person;
package com.journaldev.spring.service;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.journaldev.spring.dao.PersonDAO;
import com.journaldev.spring.model.Person;
@Service
public class PersonServiceImpl implements PersonService {
@Override
@Transactional
public void addPerson(Person p) {
this.personDAO.addPerson(p);
}
@Override
@Transactional
public void updatePerson(Person p) {
this.personDAO.updatePerson(p);
}
@Override
@Transactional
public List<Person> listPersons() {
return this.personDAO.listPersons();
}
@Override
@Transactional
public Person getPersonById(int id) {
return this.personDAO.getPersonById(id);
}
@Override
@Transactional
public void removePerson(int id) {
this.personDAO.removePerson(id);
}
}
Notice that spring declarative transaction management is applied by using @Transactional annotation.
Our DAO and Service classes are ready, it’s time to write our controller class that will take care of client requests
and uses service classes to perform database specific operations and then returns the view pages.
package com.journaldev.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.journaldev.spring.model.Person;
import com.journaldev.spring.service.PersonService;
@Controller
public class PersonController {
@Autowired(required=true)
@Qualifier(value="personService")
public void setPersonService(PersonService ps){
this.personService = ps;
}
if(p.getId() == 0){
//new person, add it
this.personService.addPerson(p);
}else{
//existing person, call update
this.personService.updatePerson(p);
}
return "redirect:/persons";
@RequestMapping("/remove/{id}")
public String removePerson(@PathVariable("id") int id){
this.personService.removePerson(id);
return "redirect:/persons";
}
@RequestMapping("/edit/{id}")
public String editPerson(@PathVariable("id") int id, Model model){
model.addAttribute("person", this.personService.getPersonById(id));
model.addAttribute("listPersons", this.personService.listPersons());
return "person";
}
}
Notice that I am using @Controller annotation, so that Spring framework will treat it as a Controller class to handle
client requests. Also I am using @Autowired and @Qualifier annotations for injecting PersonService, we could have done
it in the spring context xml file too.
Recommended Read: Spring Bean Autowiring
Our services are ready, all we need is to wire them through spring bean configurations. Our root-context.xml file is
empty, so we will look only into the servlet-context.xml file.
<beans:bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</beans:bean>
</beans:beans>
dataSource bean is defined for org.apache.commons.dbcp.BasicDataSource class for basic connection pooling.
org.springframework.orm.hibernate4.LocalSessionFactoryBean bean is used for Hibernate 4 SessionFactory. For Hibernate 3,
you will find similar classes
as org.springframework.orm.hibernate3.LocalSessionFactoryBean and org.springframework.orm.hibernate3.AnnotationSessionFactoryBean.
One important point is that when we are depending on Spring framework for Hibernate Session management, we
should not define hibernate.current_session_context_class, otherwise, you will get a lot of session transaction-related
issues.
personDAO and personService beans are self understood.
transactionManager bean definition for org.springframework.orm.hibernate4.HibernateTransactionManager is required for
Spring ORM to support hibernate session transaction management. For Hibernate 3, you will find similar class
as org.springframework.orm.hibernate3.HibernateTransactionManager. Spring uses AOP for transaction management, you can
now relate it with @Transactional annotation.
Recommended Read: Spring AOP and Spring Transaction Management
View Page
Our last part of the application is the view page, notice the attributes added to Model in Controller handler
methods, we will use them to create our view page. We will also use JSTL tags, spring core and spring form tags.
Just build and deploy the project into any servlet container of your choice, for example, Tomcat. Below
screenshots shows the view pages for our application.
You will also find similar logs in the server log file.