Saturday 21 September 2013

Spring MVC 3.x, Hibernate3.2 Annotations, MySQL Integration, Using HibernateDaoSupport and Maven

Posted by Kanhaiya

Simple CRUD application using SpringMVC3, Hibernate and MySQL through Maven. Our Application is UsersManagements where you can view or search users, create new users, edit or delete existing users.

Step#1: Create the BLOG_USER Table:-
drop table if exists `blog_user`;
CREATE TABLE blog_user (
    id int NOT NULL AUTO_INCREMENT,
    name varchar(50) DEFAULT NULL,
      username varchar(50) NOT NULL,
      first_name varchar(50) DEFAULT NULL,
      last_name varchar(50) DEFAULT NULL,
      password varchar(50) DEFAULT NULL,
      created_on datetime DEFAULT NULL,
      createdBy varchar(50),
    updatedBy varchar(50),
    createdDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
    updatedDate TIMESTAMP  NOT NULL,
      PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Step#2: Copy the SpringMVC, Hibernate and their dependent jars into WEB-INF/lib folder. If you are using Maven you can mention the following dependencies.

 4.0.0
 TestSpring3Hibernate4Annotation
 TestSpring3Hibernate4Annotation
 0.0.1-SNAPSHOT
 war
 TestSpring3Hibernate4Annotation
 TestSpring3Hibernate4Annotation sample app
 http://maven.apache.org

 
  3.2.1.RELEASE
  3.1.2.RELEASE
  1.6.1
 

 
  
   org.springframework
   spring-web
   ${org.springframework.version}
  
  
   org.springframework
   spring-webmvc
   ${org.springframework.version}
  
  
   org.springframework
   spring-context
   ${org.springframework.version}
  
  
   org.springframework
   spring-orm
   ${org.springframework.version}
  
  
   org.springframework
   spring-test
   ${org.springframework.version}
  
  
   org.springframework
   spring-jdbc
   ${org.springframework.version}
  
  
   org.springframework.security
   spring-security-core
   3.1.2.RELEASE
  

  
   org.springframework.security
   spring-security-web
   3.1.2.RELEASE
  

  
   org.springframework.security
   spring-security-config
   3.1.2.RELEASE
  

  
   javax.servlet
   javax.servlet-api
   3.0.1
  
  
  
   javax.persistence
   persistence-api
   1.0
   compile
  
  
   org.hibernate
   hibernate
   3.2.2.ga
  
  
   org.hibernate
   hibernate-entitymanager
   3.2.1.ga
  
  
   org.hibernate
   hibernate-annotations
   3.2.1.ga
  
  
   org.hibernate
   hibernate-core
   3.3.2.GA
  
  
   org.hibernate
   hibernate-validator
   4.2.0.Final
  

  
   org.slf4j
   slf4j-api
   1.5.8
  
  
   org.slf4j
   slf4j-log4j12
   1.5.8
  
  
   org.slf4j
   jcl-over-slf4j
   1.5.8
  
  
   log4j
   log4j
   1.2.12
  

  
   junit
   junit
   4.8.2
  

  
   mysql
   mysql-connector-java
   5.1.9
  
  
   javax.servlet
   jstl
   1.2
  
 
 
  Spring3Hibernate4Annotation
  
   
    maven-compiler-plugin
    3.1
    
     1.7
     1.7
    
   
   
    maven-war-plugin
    2.3
    
     webapp
     false
    
   
  
 


Step#3: Configure SpringMVC:- Configure DispatcherServlet in web.xml

 Spring3Hibernate4Annotation


 
  org.springframework.web.context.ContextLoaderListener
 
 
  contextConfigLocationclasspath:/spring/applicationContext.xml, classpath:/spring/hibernateContext.xml

 
  appServlet
  org.springframework.web.servlet.DispatcherServlet
  
   contextConfigLocation
  1
 

 
  appServlet
  /
 



Step#4: Configure JDBC connection parameters and Hibernate properties in src/main/resources/database.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb
jdbc.user=root
jdbc.password=root

Step#5: Configure DataSource, SessionFactory, TransactionManagement support in applicationContext.xml, hibernateContext.xml.

a) applicationContext.xml -


 
 
 
 

 
  
  
 


b) hibernateContext.xml -


    
        
            
                classpath:database.properties
            
        
    

    
        
        
        
        
    
    
    
  
  
   
    com.kanha.entity.User
   
  
  
   
    org.hibernate.dialect.MySQLDialect
    true
   
  
 
    

    

    
        
    



Step#6: Create the Entity BaseObject.java
package com.kanha.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;


/**
 * This is a base class for all the models
 * @author Kanhaiya
 *
 */
@MappedSuperclass
public class BaseDataObject implements Serializable {
 
 private static final long serialVersionUID = -4055465505216919579L;
 
 /**
  * Primary Id of the object
  */
 @Id  
 @GeneratedValue(strategy=GenerationType.AUTO)  
  @Column(name = "id")  
 private Long id;
 /**
  * Name of the model
  */
 @Column(name = "name")  
 private String name;
 /**
  * Who created the object
  */
 @Column(name="createdBy")
 private String createdBy;
 /**
  * Who updated the object
  */
 @Column(name="updatedBy")
 private String updatedBy;
 /**
  * When object is created
  */
 @Column(name="createdDate")
 private Date createdDate;
 /**
  * When object is updated
  */
 @Column(name="updatedDate")
 private Date updatedDate;
 
 public Long getId() {
  return id;
 }
 public void setId(Long id) {
  this.id = id;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getCreatedBy() {
  return createdBy;
 }
 public void setCreatedBy(String createdBy) {
  this.createdBy = createdBy;
 }
 public String getUpdatedBy() {
  return updatedBy;
 }
 public void setUpdatedBy(String updatedBy) {
  this.updatedBy = updatedBy;
 }
 public Date getCreatedDate() {
  return createdDate;
 }
 public void setCreatedDate(Date createdDate) {
  this.createdDate = createdDate;
 }
 public Date getUpdatedDate() {
  return updatedDate;
 }
 public void setUpdatedDate(Date updatedDate) {
  this.updatedDate = updatedDate;
 }
}

Step#7: Create the Entity class User.java which extend BaseObject.java
package com.kanha.entity;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Transient;

@Entity
@Table (name = "blog_user")
public class User extends BaseDataObject{

 private static final long serialVersionUID = -3815918313758350342L;

    @Column (name = "username")
    private String userName;

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

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

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

    @Column (name = "created_on", nullable = false)
    private Date createdOn;

    @Transient
    private Date lastLoginOn;

    public User() {
    }

    public User(String userName, String firstName, String lastName, String password) {
        this.userName = userName;
        this.firstName = firstName;
        this.lastName = lastName;
        this.password = password;
    }

 public String getUserName() {
  return userName;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
 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 getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 public Date getCreatedOn() {
  return createdOn;
 }
 public void setCreatedOn(Date createdOn) {
  this.createdOn = createdOn;
 }
 public Date getLastLoginOn() {
  return lastLoginOn;
 }
 public void setLastLoginOn(Date lastLoginOn) {
  this.lastLoginOn = lastLoginOn;
 }
}

Step#8: Create the GenericDao.java which performs CRUD operations on BLOG_USER table
package com.kanha.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * This is a generic interface which has all the base methods defined for all the data access objects
 * @author Kanhaiya
 *
 * @param 
 * @param 
 */
public interface GenericDao {
 
 public T findById(ID id);
 public List findAll();
 public List findByExample(T exampleInstance, String[] excludeProperty);
 public List findByExample(T exampleInstance);
 public List findByExampleOrdered(T exampleInstance, String[] excludeProperty, Map orders);
 public T saveOrUpdate(T entity) throws Exception;
 public List saveOrUpdateAll(List entities) throws Exception ;
 public void delete(T entity);
 public void delete(Collection entities);
}

Step#9: Create the UserDao
package com.kanha.dao;

import java.util.List;

import com.kanha.entity.User;

public interface UserDao extends GenericDao {
 List findUsersByUserName(String userName);
}

Step#10: Create the GenericHibernateDAO for Impl of GenericDao.java
package com.kanha.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import com.kanha.dao.GenericDao;
import com.kanha.entity.BaseDataObject;
import com.kanha.utils.StringUtils;


/**
 * This class acts as the super class for all the DAO classes. It provides all
 * the basic functionality needed by a DAO class.
 * 
 * @author Kanhaiya
 * 
 * @param 
 * @param 
 */
public class GenericHibernateDAO extends
  HibernateDaoSupport implements GenericDao {

 private Class persistentClass;

 @Autowired
 public void init(SessionFactory factory) {
     setSessionFactory(factory);
 }
 
 @SuppressWarnings("unchecked")
 public GenericHibernateDAO() {
  this.persistentClass = (Class) ((ParameterizedType) getClass()
    .getGenericSuperclass()).getActualTypeArguments()[0];
 }

 public Class getPersistentClass() {
  return persistentClass;
 }

 @SuppressWarnings("unchecked")
 public T findById(ID id) {
  return (T) getHibernateTemplate().get(getPersistentClass().getName(),
    id);
 }

 public List findAll() {
  return findByCriteria();
 }

 /**
  * Finds entities by example
  * 
  * @param exampleInstance
  * @param excludeProperty
  */
 @SuppressWarnings("unchecked")
 public List findByExample(T exampleInstance, String[] excludeProperty) {

  DetachedCriteria crit = DetachedCriteria.forClass(getPersistentClass());
  crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
  Example example = Example.create(exampleInstance);
  for (String exclude : excludeProperty) {
   example.excludeProperty(exclude);
  }
  crit.add(example);
  return getHibernateTemplate().findByCriteria(crit);
 }
 /**
  * Finds entities by example
  * 
  * @param exampleInstance
  * @param excludeProperty
  */
 @SuppressWarnings("unchecked")
 public List findByExample(T exampleInstance) {

  DetachedCriteria crit = DetachedCriteria.forClass(getPersistentClass());
  crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
  Example example = Example.create(exampleInstance);
  crit.add(example);
  return getHibernateTemplate().findByCriteria(crit);
 }

 /**
  * Finds ordered entities list by example, default sorting is ascending
  * 
  * @param exampleInstance
  * @param excludeProperty
  * @param orders
  * @return
  */
 @SuppressWarnings("unchecked")
 public List findByExampleOrdered(T exampleInstance,
   String[] excludeProperty, Map orders) {

  DetachedCriteria crit = DetachedCriteria.forClass(getPersistentClass());
  crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
  Example example = Example.create(exampleInstance);
  for (String exclude : excludeProperty) {
   example.excludeProperty(exclude);
  }
  crit.add(example);

  if (null != orders) {
   for (String string : orders.keySet()) {
    Boolean isDesc = orders.get(string);
    if (null == isDesc || !isDesc)
     crit.addOrder(Order.asc(string)); // Default sorting is
              // Ascending
    else
     crit.addOrder(Order.desc(string));
   }
  }
  return getHibernateTemplate().findByCriteria(crit);
 }

 public T saveOrUpdate(T entity) throws Exception{
  BaseDataObject baseObject = (BaseDataObject)entity;
  Authentication auth = SecurityContextHolder.getContext().getAuthentication();
  String username = "System";
  if(auth != null){
   username = auth.getName();
     }
  //Updating createdBy, updatedBy, createdDate,updatedDate
  if(StringUtils.isNull(baseObject.getCreatedBy())){
   baseObject.setCreatedBy(username);
  }
  if(StringUtils.isNull(baseObject.getUpdatedBy())){
   baseObject.setUpdatedBy(username);
  }
  if(baseObject.getCreatedDate() == null){
   baseObject.setCreatedDate(new Date(System.currentTimeMillis()));
  }
  if(baseObject.getUpdatedDate() == null){
   baseObject.setUpdatedDate(new Date(System.currentTimeMillis()));
  }
  try{
   getHibernateTemplate().saveOrUpdate(entity);
  }catch(Exception e){
   getHibernateTemplate().evict(entity);
   throw e;
  }
  return entity;
 }

 public void delete(T entity) {
  getHibernateTemplate().delete(entity);
 }

 public void delete(Collection entities) {
  getHibernateTemplate().deleteAll(entities);
 }

 /**
  * Find the Entity by given criterions
  * 
  * @param criterion
  * @return List
  */
 protected List findByCriteria(Criterion... criterion) {
  return findByCriteriaOrdered(null, criterion);
 }

 /**
  * 
  * @param criterion
  * @return List
  */
 @SuppressWarnings("unchecked")
 protected List findByCriteria(DetachedCriteria criteria) {
  criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
  return getHibernateTemplate().findByCriteria(criteria);
 }

 /**
  * Finds and orders entity by criteria
  * 
  * @param criterion
  * @return List
  */
 @SuppressWarnings("unchecked")
 protected List findByCriteriaOrdered(List orders,
   Criterion... criterion) {
  DetachedCriteria crit = DetachedCriteria.forClass(getPersistentClass());
  crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
  for (Criterion c : criterion) {
   crit.add(c);
  }
  if (null != orders) {
   for (Order order : orders) {
    crit.addOrder(order);
   }
  }
  return getHibernateTemplate().findByCriteria(crit);
 }

 public List saveOrUpdateAll(List entities) throws Exception {
  if (entities == null || entities.size() == 0)
   return null;
  for (T entity : entities) {
   BaseDataObject baseObject = (BaseDataObject) entity;
   Authentication auth = SecurityContextHolder.getContext().getAuthentication();
   String username = "System";
   if(auth != null){
    username = auth.getName();
   }
   //Updating createdBy, updatedBy, createdDate,updatedDate
   if(StringUtils.isNull(baseObject.getCreatedBy())){
    baseObject.setCreatedBy(username);
   }
   if(StringUtils.isNull(baseObject.getUpdatedBy())){
    baseObject.setUpdatedBy(username);
   }
   if(baseObject.getCreatedDate() == null){
    baseObject.setCreatedDate(new Date(System.currentTimeMillis()));
   }
   if(baseObject.getUpdatedDate() == null){
    baseObject.setUpdatedDate(new Date(System.currentTimeMillis()));
   }
  }
  getHibernateTemplate().saveOrUpdateAll(entities);
  return entities;
 }
}

Step#11: Create the UserDaoImpl.java which extends GenericHibernateDAO and implements UserDao

package com.kanha.dao.impl;

import java.util.List;

import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.kanha.dao.UserDao;
import com.kanha.entity.User;

@Repository
public class UserDaoImpl extends GenericHibernateDAO implements UserDao {

    @Override
    public List findUsersByUserName(String userName) {
        return findByCriteria(Restrictions.like("userName", userName, MatchMode.START));
    }
}

Step#12: Now create a service UserService.java
package com.kanha.service;

import java.util.List;

import com.kanha.entity.User;
/**
 * @author Kanhaiya
 *
 */
public interface UserService {
 
 User saveOrUpdateUser(User user) throws Exception;
    void deleteUser(User user)throws Exception;
    List findAllUsers();
    User findByUserId(Long id);
    List findUsersByUserName(String userName);
    
}

Step#13: Now create a Impl of service UserServiceImpl.java
package com.kanha.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.kanha.dao.UserDao;
import com.kanha.entity.User;
import com.kanha.service.UserService;

@Service("userService")
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService {

 @Autowired
 private UserDao userDao;

 @Override
 @Transactional(readOnly = false)
 public User saveOrUpdateUser(User user) throws Exception {
  return userDao.saveOrUpdate(user);
 }

 @Override
 @Transactional(readOnly = false)
 public void deleteUser(User user) throws Exception {
  userDao.delete(user);
 }

 @Override
 public List findAllUsers() {
  return userDao.findAll();
 }

 @Override
 public User findByUserId(Long id) {
  return userDao.findById(id);
 }

 @Override
 public List findUsersByUserName(String userName) {
  return userDao.findUsersByUserName(userName);
 }

}

Step#14: Now create a StringUtils.java for check Object or String value is empty or null
package com.kanha.utils;

import java.util.Date;

/**
 * Utility class for String related operations
 * 
 * @author Kanhaiya
 * 
 */
public class StringUtils {

 /**
  * Checks whether a String value is empty or null
  * 
  * @param value
  */
 public static boolean isNull(Object value) {
  String strValue = null;
  if (value instanceof Integer || value instanceof Long
    || value instanceof String || value instanceof Date) {
   strValue = value.toString();
  }
  if ((strValue == null)
    || (strValue != null && ("".equals(strValue.trim())
      || "null".equals(strValue.trim()) || strValue.trim()
      .length() == 0)))
   return true;
  else
   return false;
 }

 /**
  * Checks whether a String value is empty or null
  * 
  * @param value
  */
 public static boolean isNotNull(Object value) {
  return !isNull(value);
 }

}

Step#15: Now create a controller UserController.java
package com.kanha.controller;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
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.kanha.entity.User;
import com.kanha.service.UserService;

@Controller
public class UserController {
 
 @ModelAttribute(value="user")
 public User getUser(){
  return new User();
 }

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String showUserForm(Model model) {
     System.out.println("showUserForm is called...");
        model.addAttribute("user",new User());
        return "index";
    }

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public String saveUser( Model model, User user) {
     System.out.println("saveUser is called...");
     if(user.getId() !=null){
      User existing = userService.findByUserId(user.getId());
      if (existing != null) {
                model.addAttribute("status", "exist");
                return "index";
            }
     }
     user.setName(user.getFirstName());
        user.setCreatedOn(new Date());
        try {
         User user1 = userService.saveOrUpdateUser(user);
  } catch (Exception e) {
   // Do nothing
   e.printStackTrace();
  }
        model.addAttribute("saved", "success");
        return "index";
    }

    @RequestMapping(value = "/search", method = RequestMethod.POST)
    public String searchUser(Model model, User user) {
        List users = userService.findUsersByUserName(user.getUserName());
        model.addAttribute("users", users);
        model.addAttribute("search", true);
        return "index";
    }

    @RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
    public String updateUser(Model model, @PathVariable Long id) {
        User user = userService.findByUserId(id);
        model.addAttribute("user", user);
        return "update";
    }

    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public String updateUser( Model model, User user) {
     User dbUser = userService.findByUserId(user.getId());
     dbUser.setUserName(user.getUserName());
     dbUser.setName(user.getName());
     dbUser.setFirstName(user.getFirstName());
     dbUser.setLastName(user.getLastName());
     dbUser.setCreatedOn(user.getCreatedOn());
     dbUser.setPassword(user.getPassword());
     
        try {
   userService.saveOrUpdateUser(dbUser);
  } catch (Exception e) {
   // Do nothing...
   e.printStackTrace();
  }
        model.addAttribute("saved", "success");
        return "update";
    }
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
    public String deleteUser(Model model, @PathVariable Long id) {
     User user = userService.findByUserId(id);
        try {
   userService.deleteUser(user);
  } catch (Exception e) {
   // Do nothing...
   e.printStackTrace();
  }
        model.addAttribute("deleted", "success");
        model.addAttribute("user", new User());
        return "index";
    }
}

Step#16: Create the JSPs in WEB-INF folder as given directory structure.
a)/WEB-INF/jsp/common - header.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>







 


Spring 3 and Hibernate 4


b)/WEB-INF/jsp/common - footer.jsp

b)/WEB-INF/jsp - index.jsp
<%@ include file="common/header.jsp" %>

 
 

User Name First Name Last Name Actions
No results found!
${current.userName} ${current.firstName} ${current.lastName} Edit Delete
<%@ include file="common/footer.jsp" %>

b)/WEB-INF/jsp - update.jsp
<%@ include file="common/header.jsp" %>

 <%@ include file="common/footer.jsp" %>

Overall Project Directory Structure:-


Run Application:
Right click on project->run as->run on server.
copy http://localhost:8080/TestSpring3Hibernate4Annotation/ link to browser and press enter.


Fill the form with User Name, First Name, Last Name & Password then click save User button


After that when click Search User button then it will show all created users list


If you want to search User by username then it will also show all users list by username. When you click Edit button then it open users data in edit mode now then you can update User. And delete button perform is own action.

Download Source code
SrcCodes :Click here


3 comments:

  1. Hi Kanhaiya,
    Can you please share some directory structure for the files, because I am bit confused, which file should be where???

    ReplyDelete
    Replies
    1. Dear Robin,
      I have updated project directory structure for the same... so now can see it..!!

      Delete