Henri Blog

Study and Share knowledge

Simple CRUD – SpringMVC & Hibernate3

with 6 comments

It’s been 5 months as I’ve been working with Java Technology. Yes, I’m just a newbie. I’ve been working as bug fixing support team for medical system which is built using struts 1, spring Ioc, and hibernate. It’s painful for me because the legacy code is huge and almost with no comment. In reality I almost never do coding with underlying framework but medical system framework itself. Although it’s painful it’s a good starting point for me to learn Java Technology.

In idle time I encourage myself to learn other java technology and try to put it in code at weekend. For this opportunity I want to share creating simple CRUD application using SpringMVC and Hibernate3. Simple CRUD application that we’re going to build only consist one entity class (Person). Actually what we’re going to build is similar to Simple CRUD – CodeIgniter. Let’s begin.

  1. Database schema (MySql 5). run this script.
    CREATE DATABASE crud;
    
    GRANT ALL ON crud.* TO crud@localhost IDENTIFIED BY 'password';
    
    USE crud;
    CREATE TABLE tbl_person
    (
      id bigint auto_increment PRIMARY KEY,
      name varchar(50),
      gender char(1),
      dob date
    );
    
    INSERT tbl_person (name,gender,dob) VALUES('henrihnr', 'm', '1985-09-09');
    INSERT tbl_person (name,gender,dob) VALUES('name_001', 'm', '1990-01-01');
    INSERT tbl_person (name,gender,dob) VALUES('name_002', 'f', '2000-01-01');
    INSERT tbl_person (name,gender,dob) VALUES('name_003', 'm', '2000-02-02');
    INSERT tbl_person (name,gender,dob) VALUES('name_005', 'm', '2000-04-04');
  2. web.xml
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/applicationContext.xml</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
    <!-- Front Controller -->
        <servlet>
            <servlet-name>dispatcher</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>2</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcher</servlet-name>
            <url-pattern>*.html</url-pattern>
        </servlet-mapping>
    <!-- end of Front Controller -->
  3. applicationContext.xml
        <bean id="propertyConfigurer"
              class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
              p:location="/WEB-INF/jdbc.properties" />
    
        <bean id="dataSource"
              class="org.apache.commons.dbcp.BasicDataSource"
              destroy-method="close"
              p:driverClassName="${jdbc.driverClassName}"
              p:url="${jdbc.url}"
              p:username="${jdbc.username}"
              p:password="${jdbc.password}" />
    
        <!-- ADD PERSISTENCE SUPPORT HERE (jpa, hibernate, etc) -->
        <bean id="sessionFactory"
              class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
              <property name="dataSource" ref="dataSource"/>
              <property name="mappingResources">
                  <list>
                      <value>training/springmvc/crud/model/person.hbm.xml</value>
                  </list>
              </property>
              <property name="hibernateProperties">
                  <value>hibernate.dialect=org.hibernate.dialect.MySQLDialect</value>
              </property>
        </bean>
    
        <!-- Transaction Manager -->
        <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
    
        <!-- Service -->
        <bean id="personService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="target">
                <bean class="training.springmvc.crud.service.PersonServiceImpl">
                    <property name="personDAO" ref="personDAO"/>
                </bean>
            </property>
            <property name="transactionAttributes">
                <props>
                    <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
                    <prop key="*">PROPAGATION_REQUIRED</prop>
                </props>
            </property>
        </bean>
    
        <!-- DAO -->
        <bean id="personDAO" class="training.springmvc.crud.dao.PersonDAOHib"
            p:sessionFactory="sessionFactory"
            p:sessionFactory-ref="sessionFactory"/>
  4. dispatcher-servlet.xml
    <!-- Action Handling -->
        <!-- BeanNameUrlHandlerMapping
            This configuration is optional because BeanNameUrlHandlerMapping is the default handler.
            In case no handler mapping is found in the web application context, SpringMVC will create an instance of BeanNameUrlHandlerMapping.
        -->
        <bean name="beanNameUrlHandlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!-- end of Action Handling -->
    
    <!-- View Handler -->
        <!-- InternalResourceViewResolver
        The InternalResourceViewResolver class can determine the physical view in the web application archive given the logical view name.
        -->
        <bean id="viewResolver"
              class="org.springframework.web.servlet.view.InternalResourceViewResolver"
              p:prefix="/WEB-INF/jsp/"
              p:suffix=".jsp" />
    <!-- end of View Handler -->
    
    <!-- Page Controller -->
        <bean name="/index.html"
              class="training.springmvc.crud.controller.IndexController"
              p:personService="personService"
              p:personService-ref="personService"/>
    
        <bean name="/view.html"
              class="training.springmvc.crud.controller.ViewPersonController"
              p:personService="personService"
              p:personService-ref="personService"/>
    
        <bean name="/add.html"
              class="org.springframework.web.servlet.mvc.ParameterizableViewController"
              p:viewName="personEdit"/>
    
        <bean name="/update.html"
              class="training.springmvc.crud.controller.UpdatePersonController"
              p:personService="personService"
              p:personService-ref="personService"/>
    
        <bean name="/save.html"
              class="training.springmvc.crud.controller.SavePersonController"
              p:personService="personService"
              p:personService-ref="personService"/>
    
        <bean name="/delete.html"
              class="training.springmvc.crud.controller.DeletePersonController"
              p:personService="personService"
              p:personService-ref="personService"/>
    <!-- end of Page Controller -->
  5. entity class (POJO)
    public class Person implements Serializable {
    
        private Long id;
        private String name;
        private Character gender;
        private Date dob;
    
        public Person(){}
    
        // tricky method to parse form object to POJO
        public void setDob_(String dob_) throws Exception{
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy");
            Date date = simpleDateFormat.parse(dob_);
            setDob(date);
        }
    
        // setters and getters
    
  6. hibernate mapping
    <class name="training.springmvc.crud.model.Person" schema="crud" table="tbl_person">
        <id column="id" name="id">
          <generator class="native"/>
        </id>
        <property column="name" name="name"/>
        <property column="gender" name="gender"/>
        <property column="dob" name="dob"/>
      </class>
  7. Page Controller.
    IndexController.java

    public class IndexController implements Controller {
    
        private PersonService personService;
        public void setPersonService(PersonService personService) {
            this.personService = personService;
        }
    
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            Map model = new HashMap();
            PagedListHolder pagedListHolder = (PagedListHolder) request.getSession().getAttribute("personList");
    
            if(pagedListHolder == null){
                pagedListHolder = new PagedListHolder(personService.getPersonList());
            }
            else{
                String page = (String) request.getParameter("page");
                if("next".equals(page)){
                    pagedListHolder.nextPage();
                }
                else if("previous".equals(page)){
                    pagedListHolder.previousPage();
                }
            }
    
            request.getSession().setAttribute("personList", pagedListHolder);
            model.put("personList", pagedListHolder);
            return new ModelAndView("index", model);
        }
    
    }

    ViewPersonController.java

    public class ViewPersonController implements Controller{
    
        private PersonService personService;
        public void setPersonService(PersonService personService) {
            this.personService = personService;
        }
    
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            Map model = new HashMap();
    
            Long id = Long.parseLong(request.getParameter("personId"));
            Person person = personService.getPerson(id);
    
            model.put("title", "Person Details");
            model.put("person", person);
            return new ModelAndView("personView", model);
        }
    
    }

    UpdatePersonController.java

    public class UpdatePersonController implements Controller{
    
        private PersonService personService;
        public void setPersonService(PersonService personService) {
            this.personService = personService;
        }
    
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            Map model = new HashMap();
    
            Long id = Long.parseLong(request.getParameter("personId"));
            Person person = personService.getPerson(id);
    
            model.put("title", "Update Person");
            model.put("person", person);
            return new ModelAndView("personEdit",model);
        }
    
    }

    SavePersonController.java

    public class SavePersonController extends AbstractCommandController{
    
        private PersonService personService;
        public void setPersonService(PersonService personService) {
            this.personService = personService;
        }
    
        public SavePersonController(){
            this.setCommandClass(Person.class);
        }
    
        @Override
        protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object form, BindException errors) throws Exception {
            Map model = new HashMap();
    
            Person person = (Person) form;
            personService.savePerson(person);
    
            request.getSession().setAttribute("personList", null);
    
            model.put("title","Update Person");
            model.put("person",person);
            return new ModelAndView("personEdit", model);
        }
    
    }

    DeletePersonController.java

    public class DeletePersonController implements Controller{
    
        private PersonService personService;
        public void setPersonService(PersonService personService) {
            this.personService = personService;
        }
    
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            Map model = new HashMap();
    
            Long id = Long.parseLong(request.getParameter("personId"));
            personService.deletePerson(id);
    
            PagedListHolder pagedListHolder = (PagedListHolder) request.getSession().getAttribute("personList");
    
            List personList = pagedListHolder.getSource();
            for(Iterator iterator = personList.iterator(); iterator.hasNext();){
                Person person = (Person) iterator.next();
                if(person.getId().equals(id)){
                    personList.remove(person);
                    break;
                }
            }
            pagedListHolder.setSource(personList);
    
            request.getSession().setAttribute("personList", pagedListHolder);
            model.put("personList", pagedListHolder);
            return new ModelAndView("index",model);
        }
    
    }
  8. Service (Facade).
    PersonService.java

    public interface PersonService {
    
        public List getPersonList();
    
        public Person getPerson(Long id);
    
        public void savePerson(Person person);
    
        public void deletePerson(Long id);
    }

    PersonServiceImpl.java

    public class PersonServiceImpl implements PersonService{
    
        private PersonDAO personDAO;
        public void setPersonDAO(PersonDAO personDAO) {
            this.personDAO = personDAO;
        }
    
        public List getPersonList() {
            return personDAO.getPersonList();
        }
    
        public Person getPerson(Long id){
            return personDAO.getPerson(id);
        }
    
        public void savePerson(Person person) {
            personDAO.savePerson(person);
        }
    
        public void deletePerson(Long id) {
            personDAO.deletePerson(id);
        }
    
    }
  9. DAO.
    PersonDAO.java

    public interface PersonDAO {
    
        public List getPersonList();
    
        public Person getPerson(Long id);
    
        public void savePerson(Person person);
    
        public void deletePerson(Long id);
    }

    PersonDAOHib.java

    public class PersonDAOHib extends HibernateDaoSupport implements PersonDAO{
    
        public List getPersonList(){
            return getHibernateTemplate().find("from Person");
        }
    
        public Person getPerson(Long id){
            return (Person) getHibernateTemplate().get(Person.class, id);
        }
    
        public void savePerson(Person person){
            this.getHibernateTemplate().saveOrUpdate(person);
        }
    
        public void deletePerson(Long id){
            getHibernateTemplate().delete(getPerson(id));
        }
    }
  10. JSP files
    index.jsp

    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <title>Simple CRUD - SpringMVC and Hibernate3</title>
        <link href="style/style.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <div class="content">
            <h1>Simple CRUD - SpringMVC and Hibernate3</h1>
            <div class="paging">
              <c:if test="${!personList.firstPage}">
                <a href="index.html?page=previous"><b>&lt;&lt; Prev</b></a>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
              </c:if>
              <c:if test="${!personList.lastPage}">
                <a href="index.html?page=next"><b>Next &gt;&gt;</b></a>
              </c:if>
            </div>
            <div class="data">
                <table border="0" cellpadding="4" cellspacing="0">
                    <tr>
                        <th>ID</th>
                        <th>Name</th>
                        <th>Gender</th>
                        <th>Date of Birth (dd-mm-yyyy)</th>
                        <th>Actions</th>
                    </tr>
                  <c:forEach var="person" items="${personList.pageList}">
                    <tr>
                        <td>${person.id}</td>
                        <td>${person.name}</td>
                        <td>
                            <c:choose>
                                <c:when test="${person.gender=='m'}">
                                    Male
                                </c:when>
                                <c:when test="${person.gender=='f'}">
                                    Female
                                </c:when>
                            </c:choose>
                        </td>
                        <td><fmt:formatDate dateStyle="full" pattern="dd-MM-yyyy" value="${person.dob}"/></td>
                        <td>
                            <a href="view.html?personId=${person.id}" class="view">view</a>
                            <a href="update.html?personId=${person.id}" class="update">update</a>
                            <a href="delete.html?personId=${person.id}" class="delete">delete</a>
                        </td>
                    </tr>
                  </c:forEach>
                  <c:if test="${personList.nrOfElements == 0}">
                    <tr><td colspan="5">No Person Data</td></tr>
                  </c:if>
                </table>
            </div>
            <br />
            <a href="add.html" class="add">add new person</a>
        </div>
    </body>
    </html>

    personView.jsp

    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <title>Simple CRUD - SpringMVC and Hibernate3</title>
        <link href="style/style.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <div class="content">
            <h1>${title}</h1>
            <div class="data">
                <table>
                    <tr>
                        <td width="30%">ID</td>
                        <td>${person.id}</td>
                    </tr>
                    <tr>
                        <td valign="top">Name</td>
                        <td>${person.name}</td>
                    </tr>
                    <tr>
                        <td valign="top">Gender</td>
                        <td>
                            <c:choose>
                                <c:when test="${person.gender=='m'}">
                                    Male
                                </c:when>
                                <c:when test="${person.gender=='f'}">
                                    Female
                                </c:when>
                            </c:choose>
                        </td>
                    </tr>
                    <tr>
                        <td valign="top">Date of birth (dd-mm-yyyy)</td>
                        <td><fmt:formatDate dateStyle="full" pattern="dd-MM-yyyy" value="${person.dob}"/></td>
                    </tr>
                </table>
            </div>
            <br />
            <a href="index.html" class="back">back</a>
        </div>
    </body>
    </html>

    personEdit.jsp

    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <title>Simple CRUD - SpringMVC and Hibernate3</title>
        <link href="style/style.css" rel="stylesheet" type="text/css" />
        <link href="style/calendar.css" rel="stylesheet" type="text/css" />
        <script type="text/javascript" src="script/calendar.js"></script>
    </head>
    <body>
        <div class="content">
            <h1><c:out value="${title}" default="Add New Person"/></h1>
            <form method="post" action="save.html">
            <div class="data">
                <table>
                    <tr>
                        <td width="30%">ID</td>
                        <td><input type="text" name="id" disabled="disable" class="text" value="${person.id}"/></td>
                            <input type="hidden" name="id" value="${person.id}"/>
                    </tr>
                    <tr>
                        <td valign="top">Name</td>
                        <td><input type="text" name="name" class="text" value="${person.name}"/>
                        </td>
                    </tr>
                    <tr>
                        <td valign="top">Gender</td>
                        <td><input type="radio" name="gender" value="m" <c:if test="${person.gender=='m'}">checked</c:if>/> Male
                            <input type="radio" name="gender" value="f" <c:if test="${person.gender=='f'}">checked</c:if>/> Female
                        </td>
                    </tr>
                    <tr>
                        <td valign="top">Date of birth (dd-mm-yyyy)</td>
                        <td><input type="text" name="dob_" onclick="displayDatePicker('dob_');" class="text" value="<fmt:formatDate dateStyle="full" pattern="dd-MM-yyyy" value="${person.dob}"/>"/>
                            <a href="javascript:void(0);" onclick="displayDatePicker('dob_');"><img src="style/images/calendar.png" alt="calendar" border="0"></a>
                        </td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                        <td><input type="submit" value="Save"/></td>
                    </tr>
                </table>
            </div>
            </form>
            <br />
            <a href="index.html" class="back">back</a>
        </div>
    </body>
    </html>
  11. Put resources such as css, script and images at Web Pages folder.

There are many workarounds needed to enhance this code such as:

  • No validation. we can use Programmatic validators (e.g. using Validator interface) or Declarative validators (e.g. Commons Validator and VALANG).
  • Using MultiActionController instead of Controller to group a logical set of actions into single controller implementation class.
  • Using annotations to create intuitive and lean code.
  • Using Property Editors instead of tricky setDob_() method to parse from form to pojo.
  • Use i18n for to support different locales.
  • There is no user messages.
  • could you please add??

That’s all for this earlier version. To preview the result please take a look this post at point 10 (as noted earlier, we are going to build similar application). I used netbeans 6.5 to create this simple application. Download Simple CRUD – SpringMVC & Hibernate3. Happy Programming!!

Written by Henri H.

May 25, 2009 at 2:04 pm

Posted in JAVA

6 Responses

Subscribe to comments with RSS.

  1. if you dont mind, please give explanation for every program you wrote..
    biar lebih jelas gitu om..
    Anyway good hen..

    hadi

    May 31, 2009 at 12:55 pm

  2. Cara jalaninnya gimana mas?
    gw kan backgroundnya PHP… kalo di PHP tinggal di taro di htdocs trus access di URL,, kalo ini ?

    imamiscool

    June 16, 2009 at 2:09 pm

  3. @imam
    find steps to run this code (also available at docs folder if you download complete code) at http://code.google.com/p/simple-crud-application/

    Henri H.

    June 16, 2009 at 6:57 pm

  4. Wah hebat bro.. Kalau dilihat dari tulisannya kayaknya udah faham betul nih ama Spring MVC. Bagus codingannya, bersih.

    @imam: cara nge-gunainnya tinggal di export jadi war, trus taroh di folder webapp nya Tomcat. Trus tinggal dijalanin deh Tomcatnya.

    andarasu

    July 14, 2009 at 10:17 pm

  5. Mas, thx bgt artikel nya…nice one,
    tapi boleh dijelasin per step ga….
    karena, itu file nya smua, kita create
    sendiri, atao ad yg auto create dari IDE nya..
    regards,
    deni

    deni

    July 26, 2009 at 2:11 pm

  6. @deni
    coba create web project pake netbeans, pilih spring & hibernate, dari situ bisa diliat file yang digenerate IDE. sisanya kudu dibuat sendiri :D

    Henri H.

    July 26, 2009 at 4:07 pm


Leave a Reply