SelimSql

Database Management System

Main Page User Guide Download Java Code Android Contact

Spring MVC + Hibernate JPA + CRUD Example

By Zülkif Güven | May 1, 2018
In this tutorial, Spring MVC, ORM, JPA and Hibernate techniques are explained.

Brief Description of Terminology

Object-Relational Mapping(ORM) is a process of mapping java objects and database tables.
ORM has many advantages over JDBC, some of them:
Java Persistence API(JPA) is one of the possible approaches to ORM. JPA has several popular implementations like Hibernate, Apache OpenJPA and EclipseLink. Persistence metadata is used to map between java objects and database tables. JPA typically defines the metadata via annotations in the Java class. Alternatively the metadata can be defined via XML.
In this example annotations are used.

Hibernate is an ORM solution for Java. It is an open source persistent framework. It is a high performance Object-Relational persistence and Query service for Java applications. Hibernate maps database tables to java classes. It uses various Java APIs, like JDBC, Java Transaction API(JTA) and Java Naming and Directory Interface (JNDI).

Some of Hibernate Advantages: JDBC is acronym of Java Database Connectivity.

CRUD is acronym of Create, Retrieve, Update, Delete.


Used Technologies



Project Main View

This sample web application explains the CRUD operations on USER table:




1. Building SelimSQL Database

Build a new database and user table by executing the following script.
For executing script, you can download and install this tool: SelimSQL Database Developer

a) Build a new database using SSqlDeveloper tool:

JDBC Class: selimsql.jdbc.DbDriver
JDBC.Url  : jdbc:selimsql:fileNewDatabase:/MyData/MyDb

Press the "Connect" button.
Enter the user and password of you.

(jdbc.username): admin
(jdbc.password) may be empty!

b) Build a new table and related indexes by executing the following 5 scripts one by one:

Create Table User (
  Id integer NOT NULL,
  Code VARCHAR(20) NOT NULL,
  Name VARCHAR(20) NOT NULL,
  Surname VARCHAR(20) NOT NULL,
  Password VARCHAR(20) NOT NULL,
  Email VARCHAR(50) NOT NULL,
  Phone VARCHAR(20),
  Status SmallInt NOT NULL
);
--Note: Select the script above and press "Sql Execute" button.

Create Unique Index UserPK On User(Id);
Create Unique Index UserCodeUIdx On User(Code);
Create Unique Index UserEmailUIdx On User(Email);

Create Sequence SEQ_USERPK;

c) Insert a User row example(optional):

Insert into User(Id, Code, Name, Surname, Email, Password, Phone, Status)
Values(SequenceNextValue('SEQ_USERPK'), 'admin', 'Admin', 'Admin', 'admin@test.com', 'admin', null, 1);

d) After the execution of script;

check "src\main\resources\spring\application.properties" named config file in project as follow:
jdbc.driverClassName=selimsql.jdbc.DbDriver

#Database jdbc connection url that you have just built:
jdbc.url=jdbc:selimsql:file:C:/MyData/MyDb
jdbc.username=admin

#Database user password that you have entered:
jdbc.password=[may be empty]


2. Project Maven Dependency

Add spring framework and necessary database dependencies in Maven pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<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.selimsql.lesson</groupId>
  <artifactId>SpringMvcHibernateJPA</artifactId>
  <name>SpringMvcHibernateJPA</name>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <!-- Generic properties -->
    <java.version>1.7</java.version>
	
    <springframework.version>4.0.6.RELEASE</springframework.version>

    <hibernate.version>4.3.6.Final</hibernate.version>

    <!-- Database:SelimSql -->
    <selimSqlDb.version>1.2.7</selimSqlDb.version>

    <!-- Web -->
    <javax.servlet.version>3.1.0</javax.servlet.version>
    <javax.jsp.version>2.3.1</javax.jsp.version>
    <jstl.version>1.2</jstl.version>
  </properties>


  <dependencies>
    <!-- Spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${springframework.version}</version>
    </dependency>
	
    <!-- Spring ORM -->
    <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>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>5.1.3.Final</version>
    </dependency>

    <!-- For BasicDataSource -->
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.4</version>
    </dependency>


    <!-- Servlet + JSP + JSTL -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${javax.servlet.version}</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>${javax.jsp.version}</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>${jstl.version}</version>
    </dependency>


    <!-- jsr303 validation -->
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>1.1.0.Final</version>
    </dependency>

	
    <!-- SelimSql database driver -->
    <dependency>
      <groupId>selimSql</groupId>
      <artifactId>selimSql</artifactId>
      <version>${selimSqlDb.version}</version>
    </dependency>

  </dependencies>

  
  <!-- For Download SelimSql Database Driver -->
  <repositories>
    <repository>
      <id>com.selimsql.database.driver.release</id>
      <name>SelimSql Database Driver Repository</name>
      <url>http://www.selimsql.com/release</url>
    </repository>
  </repositories>


  <build>
    <finalName>SpringMvcHibernateJPA</finalName>
    <pluginManagement>
      <plugins>
        <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.0</version>
              <configuration>
                  <source>${java.version}</source>
                  <target>${java.version}</target>
                  <showWarnings>true</showWarnings>
              </configuration>
          </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-war-plugin</artifactId>
          <version>2.3</version>
          <configuration>
            <!--
            <warSourceDirectory>src/main/webapp</warSourceDirectory>
            <warName>SpringMvcHibernateJPA</warName>
            -->
            <failOnMissingWebXml>false</failOnMissingWebXml>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>



3. Table Row Data Model

Add a User named persistence class to implement user’s data:
package com.selimsql.lesson.domain;

import java.io.Serializable;

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

  private static final long serialVersionUID = 7847427564396352348L;

  @Id
  @Column(name="Id", unique=true, nullable=false)
  private Integer id; //uses SEQ_USERPK to get new Id!

  @Column(name="Code", unique=true, nullable=false, length=20)
  private String code;

  @Column(name="Name", nullable=false, length=20)
  private String name;

  @Column(name="Surname", nullable=false, length=20)
  private String surname;

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

  @Column(name="Email", unique=true, nullable=false, length=50)
  private String email;

  @Column(name="Phone", length=20)
  private String phone;

  @Column(name="Status", nullable=false)
  private Integer status;

  //Getter and Setter methods..
}


4. Data Access Object(DAO) Layer

User DAO interface class:
package com.selimsql.lesson.dao;

import java.util.List;

import com.selimsql.lesson.domain.User;
import com.selimsql.lesson.dto.UserDTO;

public interface UserDao {

  List<User> queryUserList(UserDTO userDTO);

  User findById(Integer id);

  User findByCode(String code);

  User findByEmail(String email);

  int getNextIdFromSequence();

  void insertOrUpdateRow(User row);

  void updateRow(User row);

  void deleteRow(User row);
}


User Dao implementation class for Hibernate JPA operations:
package com.selimsql.lesson.dao;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import com.selimsql.lesson.domain.User;
import com.selimsql.lesson.dto.UserDTO;
import com.selimsql.lesson.util.Util;

@Repository("userDao")
public class UserDaoImp implements UserDao {

  @Autowired
  private SessionFactory sessionFactory;

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

  private Criteria createEntityCriteria(){
    return getSession().createCriteria(User.class);
  }

  public User getByKey(Integer key) {
    return (User) getSession().get(User.class, key);
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<User> queryUserList(UserDTO userDTO) {
    Criteria criteria = createEntityCriteria();

    String code = userDTO.getCode();
    if (StringUtils.hasLength(code))
      criteria.add(Restrictions.ilike("code", code + "%"));

    String name = userDTO.getName();
    if (StringUtils.hasLength(name))
      criteria.add(Restrictions.ilike("name", name + "%"));

    String surname = userDTO.getSurname();
    if (StringUtils.hasLength(surname))
      criteria.add(Restrictions.ilike("surname", surname + "%"));

    criteria.addOrder(Order.asc("name"));

    List<User> list = criteria.list();

    return list;
  }

  @Override
  public User findById(Integer id) {
    User user = getByKey(id);
    return user;
  }

  @Override
  public User findByCode(String code) {
    Criteria criteria = createEntityCriteria();
    criteria.add(Restrictions.eq("code", code));
    User user = (User)criteria.uniqueResult();
    return user;
  }

  @Override
  public User findByEmail(String email) {
    Criteria criteria = createEntityCriteria();
    criteria.add(Restrictions.eq("email", email));
    User user = (User)criteria.uniqueResult();
    return user;
  }

  @Override
  public int getNextIdFromSequence() {
    String sql = "Select SequenceNextValue(SequenceName)"
          + "  From _DB_Sequence Where SequenceName = 'SEQ_USERPK'";

    SQLQuery sqlQuery = getSession().createSQLQuery(sql);
    Object objNextId = sqlQuery.uniqueResult();
    return Util.getInt(objNextId);
  }

  @Override
  public void insertOrUpdateRow(User row) {
    getSession().save(row);
  }

  @Override
  public void updateRow(User row) {
    getSession().merge(row);
  }

  @Override
  public void deleteRow(User row) {
    getSession().delete(row);
  }
}


5. Service Layer

User Service Implementation:
package com.selimsql.lesson.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;

import com.selimsql.lesson.dao.UserDao;
import com.selimsql.lesson.domain.User;
import com.selimsql.lesson.dto.UserDTO;
import com.selimsql.lesson.util.Util;

@Service("userService")
@Transactional(propagation = Propagation.REQUIRED, readOnly = true, rollbackFor = Throwable.class)
public class UserServiceImp implements UserService {

  @Autowired
  private UserDao userDao;

  @Override
  public List<User> queryUserList(UserDTO userDTO) {
    List<User> list = userDao.queryUserList(userDTO);
    return list;
  }

  @Override
  public User findById(Integer id) {
    User user = userDao.findById(id);
    return user;
  }

  @Override
  public User findByCode(String code) {
    User user = userDao.findByCode(code);
    return user;
  }

  @Override
  public User findByEmail(String email) {
    User user = userDao.findByEmail(email);
    return user;
  }

  @Override
  @Transactional(readOnly=false)
  public boolean newUserSave(User user, BindingResult result) {
    final boolean addUser = true;
    validateNewData(user, addUser, result);

    if (result.hasErrors())
      return false;

    insertOrUpdateRow(user);
    return true;
  }

  private void validateNewData(User user, boolean add, Errors errors) {
    String code = (user==null ? null : user.getCode());
    if (Util.isEmpty(code)) {
      errors.rejectValue("code", "required.Code");
    }
    else {
      User userBefore = findByCode(code);
      if (userBefore!=null) {
        if (add) {
          errors.rejectValue("code", "Row.codeX.already.exist.Please.enter.different.code", new Object[]{code}, "Error");
        }
        else
        //if (update)
        if (Util.isNotEqual(user.getId(), userBefore.getId()))
        {
          errors.rejectValue("code", "message.generic", new Object[]{"UserCode:" + code + " has already been defined!"}, "Error");
        }
      }

      String codeSmoothed = Util.codeFromStr(code);
      if (Util.isNotEqual(code, codeSmoothed)) {
        errors.rejectValue("code", "message.generic", new Object[]{"Code is invalid! Suggestion code:" + codeSmoothed}, "Error");
      }
    }

    //------------------------------
    String email = (user==null ? null : user.getEmail());
    if (Util.isEmpty(email)) {
      errors.rejectValue("email", "required.Email");
    }
    else {
      User userBefore = findByEmail(email);
      if (userBefore!=null) {
        if (add) {
          errors.rejectValue("email", "Row.emailX.already.exist.Please.enter.different.email", new Object[]{email}, "Error");
        }
        else
        //if (update)
        if (Util.isNotEqual(user.getId(), userBefore.getId()))
        {
          errors.rejectValue("email", "message.generic", new Object[]{"UserEmail:" + email + " has already been defined!"}, "Error");
        }
      }

      if (Util.isEMailValid(email)==false) {
        errors.rejectValue("email", "invalid.Email");
      }
    }

    ValidationUtils.rejectIfEmpty(errors, "name", "required.Name");
    ValidationUtils.rejectIfEmpty(errors, "surname", "required.Surname");
    ValidationUtils.rejectIfEmpty(errors, "password", "required.Password");
    ValidationUtils.rejectIfEmpty(errors, "status", "required.Status");
  }//validate_NewData

  @Override
  @Transactional(readOnly=false)
  public void insertOrUpdateRow(User row) {
    if (row.getId()==null) {
      Integer idSeq = userDao.getNextIdFromSequence();
      row.setId(idSeq);
    }

    userDao.insertOrUpdateRow(row);
  }


  @Override
  @Transactional(readOnly=false)
  public boolean updateUserSave(User user, BindingResult result) {
    final boolean addUser = false; //update!
    validateNewData(user, addUser, result);

    if (result.hasErrors())
      return false;

    updateRow(user);
    return true;
  }

  @Override
  @Transactional(readOnly=false)
  public void updateRow(User row) {
    userDao.updateRow(row);
  }

  @Override
  @Transactional(readOnly=false)
  public void deleteRow(User row) {
    userDao.deleteRow(row);
  }
}


6. Controller Layer

User controller service: Scope is session based for keeping every user query parameters. User CRUD operations are validated also.
package com.selimsql.lesson.controller;

import java.io.Serializable;
import java.util.List;

import javax.validation.Valid;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.selimsql.lesson.configuration.SpringAppContext;
import com.selimsql.lesson.constant.Constants;
import com.selimsql.lesson.constant.StatusEnum;
import com.selimsql.lesson.domain.User;
import com.selimsql.lesson.dto.UserDTO;
import com.selimsql.lesson.exceptions.CustomRuntimeException;
import com.selimsql.lesson.util.Util;

@Controller
@Scope(value = "session")
public class UserController implements Serializable {

  private static final long   serialVersionUID   = 1L;

  private static final String VIEW_userList      = "userList";
  private static final String VIEW_userRow       = "userRow";
  private static final String VIEW_userRowSuccess= "userRowSuccess";

  private UserDTO userDTO;
  private List<User> listUser;


  private UserController() {
    super();
    resetUserDTO();
  }

  private UserDTO resetUserDTO() {
    this.userDTO = new UserDTO(); //Empty query params at first!
    return userDTO;
  }

  private List<User> resetListUser() {
    this.listUser = null; //Empty list at first!
    return listUser;
  }

  @RequestMapping(value = { "/", "/home", "/userList" }, method = RequestMethod.GET)
  public String userListFirst(ModelMap model) {
    resetListUser();
    return userListShow(model);
  }

  @RequestMapping(value = "/userQuery", method = RequestMethod.POST)
  public String userQuery(@Valid UserDTO userDTO, ModelMap model) {
    this.userDTO = userDTO;
    this.listUser = SpringAppContext.getUserServiceBean().queryUserList(userDTO);
    return userListShow(model);
  }

  @RequestMapping(value = "/userListShow", method = RequestMethod.GET)
  //In: this.userDTO
  //In: this.listUser
  public String userListShow(ModelMap model) {
    model.addAttribute("userDTO", userDTO);
    model.addAttribute("listUser", listUser);
    return VIEW_userList;
  }

  @RequestMapping(value = "/userListRefresh", method = RequestMethod.GET)
  public String userListRefresh(ModelMap model) {
    this.listUser = SpringAppContext.getUserServiceBean().queryUserList(userDTO);
    return userListShow(model);
  }

  /**
   * This method will provide the page to add a new user.
   */
  @RequestMapping(value = "/newUser", method = RequestMethod.GET)
  public String newUser(ModelMap model) {
    User user = new User();
    user.setId(null); //On Insert: Id from SEQ_USERPK
    user.setStatus(StatusEnum.ACTIVE.getValue());

    model.addAttribute("user", user);
    model.addAttribute("operation", Constants.AUTHORITYVALUE_Add);

    return VIEW_userRow;
  }

  /**
   * This method will be called on form submission, handling POST request for
   * inserting user in database. It also validates the user input
   */
  @RequestMapping(value = "/newUser", method = RequestMethod.POST)
  public String newUserSave(@Valid User user, BindingResult result, ModelMap model) {
    boolean status = SpringAppContext.getUserServiceBean().newUserSave(user, result);
    if (status) {
      model.addAttribute("success", "UserId:" + user.getId() + ", " + user.getName() + " " + user.getSurname() + " row has been added.");
      return VIEW_userRowSuccess;
    }

    //On Error:
    model.addAttribute("operation", Constants.AUTHORITYVALUE_Add);
    return VIEW_userRow;
  }

  @RequestMapping(value = "/showUser-{id}", method = RequestMethod.GET)
  public String showUser(@PathVariable String id, ModelMap model) {
    Integer userId = Integer.valueOf(Util.getInt(id));
    User user = SpringAppContext.getUserServiceBean().findById(userId);
    if (user==null)
      throw new CustomRuntimeException("PU", "UserId:" + userId + " row is absent!");

    model.addAttribute("user", user);
    model.addAttribute("operation", Constants.AUTHORITYVALUE_Show);

    return VIEW_userRow;
  }

  /**
   * This method will provide page to update an existing user.
   */
  @RequestMapping(value = "/updateUser-{id}", method = RequestMethod.GET)
  public String updateUser(@PathVariable String id, ModelMap model) {
    Integer userId = Integer.valueOf(Util.getInt(id));
    User user = SpringAppContext.getUserServiceBean().findById(userId);
    if (user==null)
      throw new CustomRuntimeException("PU", "UserId:" + userId + " row is absent!");

    model.addAttribute("user", user);
    model.addAttribute("operation", Constants.AUTHORITYVALUE_Update);

    return VIEW_userRow;
  }

  /*
   * This method will be called on form submission, handling POST request for
   * updating user in database. It also validates the user input.
   */
  @RequestMapping(value = "/updateUser-{id}", method = RequestMethod.POST)
  public String updateUserSave(@Valid User user, BindingResult result, ModelMap model, @PathVariable String id) {
    boolean status = SpringAppContext.getUserServiceBean().updateUserSave(user, result);
    if (status) {
      model.addAttribute("success", "UserId:" + id + ", " + user.getName() + " " + user.getSurname() + " row has been updated.");
      return VIEW_userRowSuccess;
    }

    //On Error:
    model.addAttribute("operation", Constants.AUTHORITYVALUE_Update);
    return VIEW_userRow;
  }

  /*
   * This method will provide page to delete an existing user.
   */
  @RequestMapping(value = "/deleteUser-{id}", method = RequestMethod.GET)
  public String deleteUser(@PathVariable String id, ModelMap model) {
    Integer userId = Integer.valueOf(Util.getInt(id));
    User user = SpringAppContext.getUserServiceBean().findById(userId);
    if (user==null)
      throw new CustomRuntimeException("PU", "UserId:" + userId + " row is absent!");

    model.addAttribute("user", user);
    model.addAttribute("operation", Constants.AUTHORITYVALUE_Delete);

    return VIEW_userRow;
  }

  /*
   * This method will be called on form submission, handling POST request for
   * deleting user in database. It also validates the user input.
   */
  @RequestMapping(value = "/deleteUser-{id}", method = RequestMethod.POST)
  public String deleteUserSave(@Valid User user, BindingResult result, ModelMap model, @PathVariable String id) {
    SpringAppContext.getUserServiceBean().deleteRow(user);
    model.addAttribute("success", "UserId:" + id + ", " + user.getName() + " " + user.getSurname() + " row has been deleted.");
    return VIEW_userRowSuccess;
  }
}


7. Application Home Page

"userList.jsp" named file is home page. UserController directs the flow to this page.
This page displays the user list with insert, update and delete action links.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>

<%@ taglib prefix="f" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<!DOCTYPE html>
<html lang='en'>
<head>
 <jsp:include page="/WEB-INF/viewsCommon/htmlHeader.jsp"/>
</head>

<body>

<div class="generic-container">

<!-- Default panel contents -->
<h2>
 <span>User List</span>
</h2>

 <c:url value="/userQuery" var="actionUrl"/>
 <f:form method="POST" action="${actionUrl}" modelAttribute="userDTO">
 <table>
   <tr>
      <td align="right">Code</td>
      <td>
         <f:input type="text" path="code" id="code"/>
      </td>

      <td align="right">Name</td>
      <td>
         <f:input type="text" path="name" id="name"/>
      </td>

      <td align="right">Surname</td>
      <td>
         <f:input type="text" path="surname" id="surname"/>
      </td>
   </tr>

   <tr>
      <td> </td>
      <td colspan="3">
         <input type="submit" value="Query"/>

           
         <a href="<c:url value='/newUser'/>">New User</a>
      </td>
   </tr>
 </table>
 </f:form>

<br/>
<table>
    <thead>
    <tr>
        <th align="right">Id</th>
        <th align="left">Code</th>
        <th align="left">Name</th>
        <th align="left">Surname</th>
        <th align="left">Email</th>
        <th align="center">Status</th>
        <th align="left">Operation</th>
    </tr>
   </thead>

    <tbody>
 <c:forEach items="${listUser}" var="user">
      <tr>
         <td align="right">${user.id}</td>
         <td align="left">${user.code}</td>
         <td align="left">${user.name}</td>
         <td align="left">${user.surname}</td>
         <td align="left">${user.email}</td>
         <td align="center"><fmt:message key="Status${user.status}"/></td>

         <td>
          <a href="<c:url value='/showUser-${user.id}'/>">Show</a>
          <a href="<c:url value='/updateUser-${user.id}'/>">Update</a>
          <a href="<c:url value='/deleteUser-${user.id}'/>">Delete</a>
         </td>
      </tr>
    </c:forEach>
     </tbody>
   </table>
</div>

</body>
</html>


8. Row Edit Form Page

"userRow.jsp" named file is for CRUD page. UserController directs the flow to this page for insert, update or delete the row.
User add/update operations are validated like this:



<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>

<%@ taglib prefix="f" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<!DOCTYPE html>
<html>
<head>
 <jsp:include page="/WEB-INF/viewsCommon/htmlHeader.jsp"/>
</head>

<body>
<div class="container">

<h3>User Row(${operation})</h3>

<br/>
<f:form method="POST" modelAttribute="user">
   <table>
    <tr>
      <td align="right">Id (*)</td>
      <td>
         <c:choose>
            <c:when test="${operation eq 'Add'}">
               [AUTO]
            </c:when>
            <c:otherwise>
               ${user.id}
            </c:otherwise>
         </c:choose>
      </td>
    </tr>


    <tr>
      <td align="right">Name (*)</td>
      <td>
         <f:input type="text" path="name" id="name"/>
         <f:errors path="name" class="has-error"/>
      </td>
    </tr>

    <tr>
      <td align="right">Surname (*)</td>
      <td>
         <f:input type="text" path="surname" id="surname"/>
         <f:errors path="surname" class="has-error"/>
      </td>
    </tr>

    <tr>
      <td align="right">Code (*)</td>
      <td>
         <f:input type="text" path="code" id="code"/>
         <f:errors path="code" class="has-error"/>
      </td>
    </tr>

    <tr>
      <td align="right">Password (*)</td>
      <td>
         <f:input type="password" path="password" id="password"/>
         <f:errors path="password" class="has-error"/>
      </td>
    </tr>

    <tr>
      <td align="right">Email (*)</td>
      <td>
         <f:input type="text" path="email" id="email"/>
         <f:errors path="email" class="has-error"/>
      </td>
    </tr>

    <tr>
      <td align="right">Telephone</td>
      <td>
         <f:input type="text" path="phone" id="phone"/>
      </td>
    </tr>


    <tr>
      <td align="right">Status (*)</td>
      <td>
         <f:select path="status" id="status">
            <f:option value="1"><fmt:message key="Status1"/></f:option>
            <f:option value="0"><fmt:message key="Status0"/></f:option>
            <f:option value="9"><fmt:message key="Status9"/></f:option>
         </f:select>
         <f:errors path="status" class="has-error"/>
      </td>
    </tr>

    <tr>
      <td> </td>
      <td>
       <c:choose>
         <c:when test="${operation eq 'Show'}">
            <a href="<c:url value='/userListShow'/>">Okay</a>
         </c:when>
         <c:otherwise>
            <input type="submit" value="${operation}"/>
              or  
            <a href="<c:url value='/userListShow'/>">Cancel</a>
         </c:otherwise>
       </c:choose>
      </td>
    </tr>
   </table>
</f:form>

</div>

</body>
</html>


9. Spring MVC Root Application Configuration

"RootConfig.java" class is for root application configuration:
package com.selimsql.lesson.configuration;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.selimsql.lesson")
public class RootConfig extends WebMvcConfigurerAdapter {

   @Bean
   public ViewResolver viewResolver() {
      InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
      viewResolver.setViewClass(JstlView.class);
      viewResolver.setPrefix("/WEB-INF/views/");
      viewResolver.setSuffix(".jsp");
      return viewResolver;
   }

    /**
     * Configure MessageSource to lookup any validation/error message in internationalized property files
     */
   @Bean
   public MessageSource messageSource() {
       ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
       messageSource.setBasename("messages/messages");
       return messageSource;
   }

   /**
     * Configure ResourceHandlers to serve static resources like CSS/Javascript etc...
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }
}


10. Application Database Hibernate Session/DataSource Configuration

"HibernateConfiguration.java" class is for database hibernate datasource configuration:
package com.selimsql.lesson.configuration;

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;


@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.selimsql.lesson.configuration" })
@PropertySource(value = { "classpath:spring/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.selimsql.lesson.domain" });
    sessionFactory.setHibernateProperties(hibernateProperties());
    return sessionFactory;
  }

  @Bean
  public DataSource dataSource() {
    BasicDataSource dataSource = new BasicDataSource(); //Uses Poolable Connection.

    String driverClassName = environment.getProperty("jdbc.driverClassName");
    dataSource.setDriverClassName(driverClassName);

    String driverUrl = environment.getProperty("jdbc.url");
    dataSource.setUrl(driverUrl);

    String user = environment.getProperty("jdbc.username");
    dataSource.setUsername(user);

    String pass = environment.getProperty("jdbc.password");
    dataSource.setPassword(pass);

    return dataSource;
  }

  @Bean
  public Properties hibernateProperties() {
    Properties properties = new Properties();
    String key = "hibernate.dialect";
    String dialect = environment.getRequiredProperty(key);
    properties.put(key, dialect);

    key = "hibernate.show_sql";
    String showSql = environment.getRequiredProperty(key);
    properties.put(key, showSql);

    key = "hibernate.format_sql";
    String formatSql = environment.getRequiredProperty(key);
    properties.put(key, formatSql);
    return properties;
  }

  @Bean
  @Autowired
  public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
    HibernateTransactionManager txManager = new HibernateTransactionManager();
    txManager.setSessionFactory(sessionFactory);
    return txManager;
  }
}


11. Spring Application Context

For getting java class beans manually:
package com.selimsql.lesson.configuration;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import com.selimsql.lesson.service.UserService;

@Component
public class SpringAppContext implements ApplicationContextAware {

    private static ApplicationContext appContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
       appContext = applicationContext;
    }

    private static Object getBean(String beanName) {
      Assert.notNull(appContext, "ApplicationContext must be not null!");

      try {
         Object obj = appContext.getBean(beanName);
         return obj;
      }
      catch(NoSuchBeanDefinitionException nsbex) {
         throw nsbex;
      }
      catch(BeanCreationException bcex) {
         //throw bcex;
         return null;
      }
      catch(Exception ex) {
         return null;
      }
    }

    public static UserService getUserServiceBean() {
       return (UserService)getBean("userService");
    }
}


12. Spring Application Initializer

No "web.xml" is needed by this initializer class:
package com.selimsql.lesson.configuration;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
   
   @Override
   protected Class<?>[] getRootConfigClasses() {
      return new Class[] { RootConfig.class };
   }

   @Override
   protected Class<?>[] getServletConfigClasses() {
      return null;
   }

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }
}


Run Web Application

Build and deploy this application on a Web Application Server.
For example, you can deploy this on "Apache Tomcat Version8" server.

Open a browser and try this link:
http://localhost:8080/SpringMvcHibernateJPA/


Download Project Example

Download source: SpringMvcHibernateJPASSqlUserCRUDExample.zip
File size: 30KB


References



Related Posts

Related Posts


Android Mobile Apps

Copyright © 2009 - 2019 SelimSql