Simple CRUD Using Spring Boot, JPA and MySQL

You can view and download the complete source code of this tutorial from my github account.

The demo for the API is available on https://crudbudget.herokuapp.com/api.

In this tutorial, we will create a simple CRUD (Create Read Update Delete) backend API to manage Expenses using Spring Boot, JPA and MySQL.

This API will then be consumed by frontend web or app.

For this tutorial, we will need the following tools: (The older or newer version should also works).

  1. Spring Tool Suite (I use v3.8.2)
  2. MySQL Community Server and MySQL Workbench (GUI Tool)
  3. Postman to test the API call

Project Setting

First, we need to create the project using Spring Initializr (https://start.spring.io/), a web based tool to create Spring Boot projects.

Fill out the form with the following information:

  • Project : Maven Project
  • Language : Java
  • Spring Boot : 2.1.5
  • Group : com.danielniko
  • Artifact : crudbudget
  • Options : Packaging –> Jar, Java –> 8
  • Dependencies : Web, JPA, MySQL

Do not worry if you forgot to add dependencies in this form as you can easily add then in the pom.xml file later on.

Click “Generate the project” to download the project zip file and extract it to your Spring Tool Suite (STS) workspace.

Open STS and import the file by selecting File –> Import –> Maven –> Existing Maven Projects.

  • Root Directory : (browse to the extracted zip file)
  • Make sure pom.xml is checked.

For other input, just go with the default value, then click “Finish”.

If there is no error in setting, wait for several minutes as STS will download all dependencies needed.

Common Error that can occurs at the time of this writing.

Error : Unknown (Line 1 in pom.xml)

Solution : This happen in spring boot 2.1.5.RELEASE, so just downgrade to 2.1.3.RELEASE. Modify the version to 2.1.3.RELEASE.

Right click on the project in the Package Explorer and Choose Maven –> Update Project. Accept the default values and click “OK”.

Now, try to Run the application. Choose Run –> Run Configurations… on the Top menu.

Choose “Spring Boot App” from the left tree and click the new button icon.

  • Name : crudbudget
  • Project : crudbudget
  • Main type : Choose CrudBudgetApplication

Apply and click “Run” and watch the console for any error messages.

If you got the following error : Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured, it is to be expected because we have not configure the database connection yet.


Database Creation and Connection

Spring Boot actually support database, tables, relationship creation automatically when running the application. However, this is not always a good case as sometimes we are given a fixed database structure from the beginning.

I this tutorial, we will create the database manually.

Create new file “schema.sql” in src/main/resources with the following content. This file will not do anything in Spring Boot other than just an information for DDL creation.


create database crudbudget;
create table expense (
    expense_id int auto_increment,
    name varchar(30) not null,
    description varchar(200),
    category_id int not null,
    amount decimal(13,2) not null,
    created_date timestamp not null,
    modified_date timestamp,
    primary key (expense_id)
);
create table category (
    category_id int auto_increment,
    name varchar(30) not null,
    description varchar(200),
    created_date timestamp,
    modified_date timestamp,
    primary key (category_id)
);
alter table expense 
add foreign key (category_id) references category(category_id)
;
insert into category (name, description, created_date, modified_date)
values('test','This is a test category',curdate(), curdate())
;

Execute the above sql commands on your MySQL workbench to create our tables: Expense and Category with one Category can have many Expenses. We also insert one sampe category to test the inquiry later on.

Next, open “application.properties” file in src/main/resources and input the following :


## Spring DATASOURCE
spring.datasource.url = jdbc:mysql://localhost:3306/crudbudget?useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username = your_db_username
spring.datasource.password = your_db_password

## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

## Hibernate Logging
logging.level.org.hibernate.SQL= DEBUG

Make sure your database is up and running and your database credential is correct and try to run “crudbudget” again.

Furthermore, your pom.xml file should contain the following dependencies when you create the project using Spring Initializr. If not, just add these dependencies.

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

If there are no error messages, that means Spring Boot can succesfully connect to your DB. Now we can start program the application logic.


Programming JPA and REST endpoints

Create new classes, Expense.java and Category.java inside com.danielniko.crudbudget.domain to hold Expense and Category entity/domain

package com.danielniko.crudbudget.domain;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

@Entity
@EntityListeners(AuditingEntityListener.class)
public class Expense {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long expenseId;
    private String name;
    private String description;
    private double amount;
    
    @Column(name = "created_date", nullable = false, updatable = false)
    @CreatedDate
    private Date createdDate;

    @Column(name = "modified_date")
    @LastModifiedDate
    private Date modifiedDate;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "categoryId")
    private Category category;
	
    public Expense() {}
    
    public Expense(String name, String description, Category category, double amount) {
    	this.name = name;
    	this.description = description;
    	this.amount = amount;
    	this.category = category;
    }

	public Long getExpenseId() {
		return expenseId;
	}

	public void setExpenseId(Long expenseId) {
		this.expenseId = expenseId;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getName() {
		return name;
	}

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

	public double getAmount() {
		return amount;
	}

	public void setAmount(double amount) {
		this.amount = amount;
	}

	public Category getCategory() {
		return category;
	}

	public void setCategory(Category category) {
		this.category = category;
	}

	public Date getCreatedDate() {
		return createdDate;
	}

	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}

	public Date getModifiedDate() {
		return modifiedDate;
	}

	public void setModifiedDate(Date modifiedDate) {
		this.modifiedDate = modifiedDate;
	}

	@Override
	public String toString() {
		return "Expense [expenseId=" + expenseId + ", name=" + name + ", description=" + description + ", amount="
				+ amount + "]";
	}
	
}

 

package com.danielniko.crudbudget.domain;

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

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@Entity
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Category {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long categoryId;
	
    private String name;
    private String description;
	
    @Column(name = "created_date", nullable = false, updatable = false)
    @CreatedDate
    private Date createdDate;

    @Column(name = "modified_date")
    @LastModifiedDate
    private Date modifiedDate;
	
	@OneToMany(cascade = CascadeType.ALL, mappedBy="category")
	@JsonIgnore
    private List<Expense> expenses;

	public Long getCategoryId() {
		return categoryId;
	}
	public void setCategoryId(Long categoryId) {
		this.categoryId = categoryId;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public List<Expense> getExpenses() {
		return expenses;
	}
	public void setExpenses(List<Expense> expenses) {
		this.expenses = expenses;
	}
	public Date getCreatedDate() {
		return createdDate;
	}
	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}
	public Date getModifiedDate() {
		return modifiedDate;
	}
	public void setModifiedDate(Date modifiedDate) {
		this.modifiedDate = modifiedDate;
	}
	@Override
	public String toString() {
		return "Category [categoryId=" + categoryId + ", name=" + name + "]";
	}

}

We use several annotations in those 2 classes. First we use @Entity to let Spring know that this is entity class and should be used to in JPA operations to represent tables in database.

Next, we use @EntityListeners(AuditingEntityListener.class) to automatically insert timestamp on created_date during INSERT and modified_date on UPDATE operation (Usually for auditing purposes). This annotation is paired with @Column@CreatedDate and @LastModifiedDate. In order for this to work, we need to also enable the auditing in our application class. Open CrudbudgetApplication.java and add @EnableJpaAuditing

package com.danielniko.crudbudget;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class CrudbudgetApplication {

	public static void main(String[] args) {
		SpringApplication.run(CrudbudgetApplication.class, args);
	}

}

Currently, we dont annotate properties such as name, description, etc with @Column because we want to keep it simple. However, it is better to annotate your properties with @Column to include more attributes such as max length, nullable or default value.

Moreover, we use @ManyToOne in Expense and @OneToMany in Category because 1 Category can have many Expenses. Next we use @JoinColumn  to complete Foreign Key relationship between two entities which we already set in the previous SQL statement.

Next, create classes to be used as data access object to perform data manipulation. Fortunately , Spring already provides common CRUD operations so we just extend CrudRepository to access the methods.

Create ExpenseRepository.class and CategoryRepository.class inside com.danielniko.crudbudget.repository package.

package com.danielniko.crudbudget.repository;

import org.springframework.data.repository.CrudRepository;

import com.danielniko.crudbudget.domain.Expense;

public interface ExpenseRepository extends CrudRepository <Expense, Long> {

}

package com.danielniko.crudbudget.repository;

import org.springframework.data.repository.CrudRepository;

import com.danielniko.crudbudget.domain.Category;

public interface CategoryRepository extends CrudRepository <Category, Long> {

}

Finally, we can create the REST endpoint. Spring provides direct access to REST data endpoint without we manually create controller for each entity.

By adding the base path for the rest endpoint, we can directly perform CRUD manipulation on the entities.

Open again your application.properties file and add the following entry at the bottom. We use “/api” as the base path.

spring.data.rest.basePath=/api

Next, add the following dependency on your pom.xml

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-rest</artifactId>
		</dependency>

Now run “crudbudget” again. Open localhost:8080/api and see how Spring automatically provides REST endpoints for our entities.

{
  "_links" : {
    "expenses" : {
      "href" : "http://localhost:8080/api/expenses"
    },
    "categories" : {
      "href" : "http://localhost:8080/api/categories"
    },
    "profile" : {
      "href" : "http://localhost:8080/api/profile"
    }
  }
}

We can even insert directly using POST method. Open your postman and use the following information :
POST : localhost:8080/api/categories
Use application/json as header and add raw Request Body as follow

{
 "name":"danielniko",
 "description":"from postman"
}

Press send and view the console log in Spring Tool Suite and the data will be inserted succesfully.
The response generated is as follows.

{
    "name": "danielniko",
    "description": "from postman",
    "createdDate": "2019-06-10T09:29:16.557+0000",
    "modifiedDate": "2019-06-10T09:29:16.557+0000",
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/categories/8"
        },
        "category": {
            "href": "http://localhost:8080/api/categories/8"
        },
        "expenses": {
            "href": "http://localhost:8080/api/categories/8/expenses"
        }
    }
}


As you can see, the created date and modified date is inserted automatically. It is a very good functionality from Spring to enable fast timestamp auditing.
For expense, it is quite trickier because we need to supply the Category object too inside the request body
POST : localhost:8080/api/expenses

{
	"name":"expense test",
	"description":"from postman",
	"category" : "http://localhost:8080/api/categories/8",
	"amount":"500000"
}

AIX Create Task Scheduler using Crontab

Problem : I want to run a scheduled bash script every day at 00: 00

Example : For backup of tomcat log file so everyday it will rename previous day catalina.out to catalina.out.[YYYYMMDD] and write today log to catalina.out

Condition :

– OS running IBM AIX 6.0

– logrotate installed.

Solution :

Create your bash script (ex : tomcat_log.sh) :

#!/bin/sh

logrotate /home/danielniko/tomcat_logrotate -s /home/danielniko/rotate.status

Check existing cron jobs (in my case, I already add the job)

$ crontab -l

0 0 * * * /oss/cron/tomcat_log.sh

To remove the entry in crontab list, use the following. Command “sed” delete the line with text containing tomcat_log.sh

$ crontab -l | sed '\!tomcat_log.sh!d' | crontab 

$ crontab -l

Executing crontab –l again will show that our previous job already deleted.

Now lets add the job again.

$ crontab -l | awk '{print} END {print "0 0 * * * /oss/cron/tomcat_log.sh"}' | crontab

$ crontab -l
0 0 * * * /home/danielniko/open.sh

 

Explanation :

We are creating a job that runs every 0 minute at every 0 hour every day. The * symbols means every.

So each fields has the following meanings:

# field #   meaning        allowed values
# -------   ------------   --------------
#    1      minute         0-59, *
#    2      hour           0-23, *
#    3      day of month   1-31, *
#    4      month          1-12, * (or names)
#    5      day of week    0-7, * (0 or 7 is Sun, or use names)

Simple CRUD Using Java, Hibernate and MySQL

You can view and download the complete source code of this tutorial from my github account.

In this tutorial, we will create a simple CRUD (Create Read Update Delete) User Management Console Application using Java, Hibernate and MySQL.

For this tutorial, we will need the following tools: (The older or newer version should also works).

1. Eclipse IDE for Java EE Developers (Indigo – ver. 3.7)

2. MySQL Community Server and MySQL Workbench (GUI Tool)

3. MySQL Connector for Java

4. Hibernate ORM


First, lets create the database and table for User using the following SQL scripts. Copy and run this script in the MySQL Workbench (GUI Tool) –> SQL Editor:

create database UserDB;
use UserDB;
grant all on UserDB.* to 'admin'@'localhost' identified by 'test'; 

CREATE TABLE UserDB.`users` (
  `userid` int(11) NOT NULL AUTO_INCREMENT,
  `firstname` varchar(45) DEFAULT NULL,
  `lastname` varchar(45) DEFAULT NULL,
  `dob` date DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

Go to eclipse and create a new project. Select File—>New—>Java Project. Enter “SimpleJava Hibernate” as the project name. Accept all the default value. Click Finish.

Please refer to this project directory in case you miss something along the way

structure

After creating the project, we need to add MySQL connector .jar file to our project build path. To do so, right click our newly created project “SimpleJavaHibernate” and choose Properties to open Properties window.

Select Java Build Path in the left side tree view to open right side detail view. Click Add External JARs.. button to open File browser dialog and point it to the MySQL connector .jar file which you have downloaded earlier.

Furthermore, we need to add Hibernate library to our project. Right click again the project and select Properties –>Java Build Path. This time, click Add Library. Select User Library from the list of selection. Click User Library. Next, click New. Enter “Hibernate” as the library name. Ok. Click our newly created User Library and click Add Jar. Select all the .jar file in both provided and required folder which located inside this directory structure [your hibernate download folder]—>hibernate-search-4.1.0.CR3-dist—>hibernate-search-4.1.0.CR3—>dist—>lib

Verify your build path to match configuration in picture below:

build path

This is all the configuration that we need to do and now let us get to the code.

Create four packages in the src folder.

  • com.daniel: contains the main method as the entry point for our console application
  • com.daniel.dao: contains the logic for database operation
  • com.daniel.model: contains the POJO (Plain Old Java Object). Each class in this package represents the database table. For this tutorial, however, we only have one table.
  • com.daniel.util : contains the class for initiating database connection

Next, create a new Java class. in com.daniel.model folder. Name it “User.java” and insert these following codes. Each of the variables in this class represents the field in USERS table in our database.

package com.daniel.model;

import java.util.Date;

public class User {

    private int userid;
    private String firstName;
    private String lastName;
    private Date dob;
    private String email;
    public int getUserid() {
        return userid;
    }
    public void setUserid(int userid) {
        this.userid = userid;
    }
    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 Date getDob() {
        return dob;
    }
    public void setDob(Date dob) {
        this.dob = dob;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    @Override
    public String toString() {
        return "User [userid=" + userid + ", firstName=" + firstName
                + ", lastName=" + lastName + ", dob=" + dob + ", email="
                + email + "]";
    }    
}

Create a new class in com.daniel.util package and name it HibernateUtil.java. This class will read the configuration in our hibernate.cfg.xml file which handles the database connection to our MySQL server.

package com.daniel.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

Create the aforementioned hibernate.cfg.xml configuration file directly under SimpleJavaHibernate folder. Put the following information inside.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost/UserDB</property>
        <property name="connection.username">admin</property>
        <property name="connection.password">test</property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <!-- Disable the second-level cache -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>

        <!-- Mapping files -->
        <mapping resource="user.hbm.xml" />

    </session-factory>
</hibernate-configuration>

Notice that inside the file, there is an information about mapping resource which point to user.hbm.xml file. So, create an .xml file directly under SimpleJavaHibernate folder to map our Plain Old Java Object (POJO) variables with fields in database. Name it user.hbm.xml and write the following code inside

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.daniel.model.User" table="users">
        <id name="userid" type="int" column="userid">
            <generator class="increment" />
        </id>
        <property name="firstName">
            <column name="firstname" />
        </property>
        <property name="lastName">
            <column name="lastname" />
        </property>
        <property name="dob">
            <column name="dob" />
        </property>
        <property name="email">
            <column name="email" />
        </property>
    </class>
</hibernate-mapping>

Next, create a new class in com.daniel.dao package, name it UserDao.java. Dao stands for Data Access Object. It contains the logic for database operation.

package com.daniel.dao;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.daniel.model.User;
import com.daniel.util.HibernateUtil;

public class UserDao {

    public void addUser(User user) {
        Transaction trns = null;
        Session session = HibernateUtil.getSessionFactory().openSession();
        try {
            trns = session.beginTransaction();
            session.save(user);
            session.getTransaction().commit();
        } catch (RuntimeException e) {
            if (trns != null) {
                trns.rollback();
            }
            e.printStackTrace();
        } finally {
            session.flush();
            session.close();
        }
    }

    public void deleteUser(int userid) {
        Transaction trns = null;
        Session session = HibernateUtil.getSessionFactory().openSession();
        try {
            trns = session.beginTransaction();
            User user = (User) session.load(User.class, new Integer(userid));
            session.delete(user);
            session.getTransaction().commit();
        } catch (RuntimeException e) {
            if (trns != null) {
                trns.rollback();
            }
            e.printStackTrace();
        } finally {
            session.flush();
            session.close();
        }
    }

    public void updateUser(User user) {
        Transaction trns = null;
        Session session = HibernateUtil.getSessionFactory().openSession();
        try {
            trns = session.beginTransaction();
            session.update(user);
            session.getTransaction().commit();
        } catch (RuntimeException e) {
            if (trns != null) {
                trns.rollback();
            }
            e.printStackTrace();
        } finally {
            session.flush();
            session.close();
        }
    }

    public List<User> getAllUsers() {
        List<User> users = new ArrayList<User>();
        Transaction trns = null;
        Session session = HibernateUtil.getSessionFactory().openSession();
        try {
            trns = session.beginTransaction();
            users = session.createQuery("from User").list();
        } catch (RuntimeException e) {
            e.printStackTrace();
        } finally {
            session.flush();
            session.close();
        }
        return users;
    }

    public User getUserById(int userid) {
        User user = null;
        Transaction trns = null;
        Session session = HibernateUtil.getSessionFactory().openSession();
        try {
            trns = session.beginTransaction();
            String queryString = "from User where id = :id";
            Query query = session.createQuery(queryString);
            query.setInteger("id", userid);
            user = (User) query.uniqueResult();
        } catch (RuntimeException e) {
            e.printStackTrace();
        } finally {
            session.flush();
            session.close();
        }
        return user;
    }
}

Finally, create our main application class inside the com.daniel package and name it App.java

package com.daniel;

import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.daniel.dao.UserDao;
import com.daniel.model.User;
import com.daniel.util.DbUtil;

public class App {

    public static void main(String[] args) {
        UserDao dao = new UserDao();

        // Add new user
        User user = new User();
        user.setFirstName("Daniel");
        user.setLastName("NikoJdbc");
        try {
            Date dob = new SimpleDateFormat("yyyy-MM-dd").parse("1986-01-02");
            user.setDob(dob);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        user.setEmail("daniel@example.com");
        dao.addUser(user);
//
//        // Update user
        user.setEmail("daniel@updatedJdbc.com");
        user.setUserid(1);
        dao.updateUser(user);

        // Delete user
        //dao.deleteUser(2);

        // Get all users
        for (User iter : dao.getAllUsers()) {
            System.out.println(iter);
        }

        // Get user by id
        System.out.println(dao.getUserById(8));

        try {
            DbUtil.getConnection().close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}

That is it. Run the project from eclipse and see the output from Console window

Simple CRUD Using Jsp, Servlet and MySQL

You can view and download the complete source code of this tutorial from my github account.

In this tutorial, we will create a simple CRUD (Create Read Update Delete) User Management Web Application using Jsp, Servlet and MySQL.

For this tutorial, we will need the following tools: (The older or newer version should also works). Moreover, basic Java knowledge is assumed.

1. Eclipse IDE for Java EE Developers (Indigo – ver. 3.7)

2. Apache Tomcat ver 7.0

3. MySQL Community Server and MySQL Workbench (GUI Tool)

4. MySQL Connector for Java

5. jstl.jar and standard.jar. You can get these jars from your Tomcat. Check in this directory : (your tomcat directory)—>apache-tomcat-7.0.26-windows-x86—>apache-tomcat-7.0.26—>webapps—>examples—>WEB-INF—>lib

I will tell you where you should put these jars later.

6. jQuery for javascript capability. In this case, we only use it for the datepicker component


First, lets create the database and table for User using the following SQL scripts:

create database UserDB;
use UserDB;
grant all on UserDB.* to 'admin'@'localhost' identified by 'test'; 

CREATE TABLE UserDB.`users` (
  `userid` int(11) NOT NULL AUTO_INCREMENT,
  `firstname` varchar(45) DEFAULT NULL,
  `lastname` varchar(45) DEFAULT NULL,
  `dob` date DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

Go to eclipse. Before we create a new project for our application, we need to setup the server. Select File—>New—>Other. From the tree, Select Server.

Choose Apache—>Tomcat v7.0 Server and set the runtime environment.

Next, create a new project. Select File—>New—>Dynamic Web Project.

Enter “SimpleJspServletDB” as the project name. Select target runtime to Apache Tomcat v7.0 which we already setup before. Click Finish.

Please refer to this project directory in case you miss something along the way

directory

Copy the standard.jar, mysql-connector jar and jstl jar to WEB-INF—>lib folder.

Create four packages in the src folder.

  • com.daniel.controller: contains the servlets
  • com.daniel.dao: contains the logic for database operation
  • com.daniel.model: contains the POJO (Plain Old Java Object). Each class in this package represents the database table. For this tutorial, however, we only have one table.
  • com.daniel.util : contains the class for initiating database connection

Next, create a new Java class. in com.daniel.model folder. Name it “User.java” and insert these following codes. Each of the variables in this class represents the field in USERS table in our database.

package com.daniel.model;

import java.util.Date;

public class User {

    private int userid;
    private String firstName;
    private String lastName;
    private Date dob;
    private String email;
    public int getUserid() {
        return userid;
    }
    public void setUserid(int userid) {
        this.userid = userid;
    }
    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 Date getDob() {
        return dob;
    }
    public void setDob(Date dob) {
        this.dob = dob;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    @Override
    public String toString() {
        return "User [userid=" + userid + ", firstName=" + firstName
                + ", lastName=" + lastName + ", dob=" + dob + ", email="
                + email + "]";
    }    
}

Create a new class in com.daniel.util package and name it DbUtil.java. This class handles the database connection to our MySQL server. In this class, we read a .properties file which contains the information necessary for the connection.

package com.daniel.util;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class DbUtil {

    private static Connection connection = null;

    public static Connection getConnection() {
        if (connection != null)
            return connection;
        else {
            try {
                Properties prop = new Properties();
                InputStream inputStream = DbUtil.class.getClassLoader().getResourceAsStream("/db.properties");
                prop.load(inputStream);
                String driver = prop.getProperty("driver");
                String url = prop.getProperty("url");
                String user = prop.getProperty("user");
                String password = prop.getProperty("password");
                Class.forName(driver);
                connection = DriverManager.getConnection(url, user, password);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return connection;
        }

    }
}

Create the properties file directly under the src folder. Create a new file, name it db.properties. Put the following information inside.

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/UserDB
user=admin
password=test

Next, create a new class in com.daniel.dao package, name it UserDao.java. Dao stands for Data Access Object. It contains the logic for  database operation.

package com.daniel.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.daniel.model.User;
import com.daniel.util.DbUtil;

public class UserDao {

    private Connection connection;

    public UserDao() {
        connection = DbUtil.getConnection();
    }

    public void addUser(User user) {
        try {
            PreparedStatement preparedStatement = connection
                    .prepareStatement("insert into users(firstname,lastname,dob,email) values (?, ?, ?, ? )");
            // Parameters start with 1
            preparedStatement.setString(1, user.getFirstName());
            preparedStatement.setString(2, user.getLastName());
            preparedStatement.setDate(3, new java.sql.Date(user.getDob().getTime()));
            preparedStatement.setString(4, user.getEmail());
            preparedStatement.executeUpdate();

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void deleteUser(int userId) {
        try {
            PreparedStatement preparedStatement = connection
                    .prepareStatement("delete from users where userid=?");
            // Parameters start with 1
            preparedStatement.setInt(1, userId);
            preparedStatement.executeUpdate();

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void updateUser(User user) {
        try {
            PreparedStatement preparedStatement = connection
                    .prepareStatement("update users set firstname=?, lastname=?, dob=?, email=?" +
                            "where userid=?");
            // Parameters start with 1
            preparedStatement.setString(1, user.getFirstName());
            preparedStatement.setString(2, user.getLastName());
            preparedStatement.setDate(3, new java.sql.Date(user.getDob().getTime()));
            preparedStatement.setString(4, user.getEmail());
            preparedStatement.setInt(5, user.getUserid());
            preparedStatement.executeUpdate();

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public List<User> getAllUsers() {
        List<User> users = new ArrayList<User>();
        try {
            Statement statement = connection.createStatement();
            ResultSet rs = statement.executeQuery("select * from users");
            while (rs.next()) {
                User user = new User();
                user.setUserid(rs.getInt("userid"));
                user.setFirstName(rs.getString("firstname"));
                user.setLastName(rs.getString("lastname"));
                user.setDob(rs.getDate("dob"));
                user.setEmail(rs.getString("email"));
                users.add(user);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return users;
    }

    public User getUserById(int userId) {
        User user = new User();
        try {
            PreparedStatement preparedStatement = connection.
                    prepareStatement("select * from users where userid=?");
            preparedStatement.setInt(1, userId);
            ResultSet rs = preparedStatement.executeQuery();

            if (rs.next()) {
                user.setUserid(rs.getInt("userid"));
                user.setFirstName(rs.getString("firstname"));
                user.setLastName(rs.getString("lastname"));
                user.setDob(rs.getDate("dob"));
                user.setEmail(rs.getString("email"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return user;
    }
}

Finally, create a new Servlet inside the com.daniel.controller package and name it UserController.java

package com.daniel.controller;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.daniel.dao.UserDao;
import com.daniel.model.User;

public class UserController extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static String INSERT_OR_EDIT = "/user.jsp";
    private static String LIST_USER = "/listUser.jsp";
    private UserDao dao;

    public UserController() {
        super();
        dao = new UserDao();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String forward="";
        String action = request.getParameter("action");

        if (action.equalsIgnoreCase("delete")){
            int userId = Integer.parseInt(request.getParameter("userId"));
            dao.deleteUser(userId);
            forward = LIST_USER;
            request.setAttribute("users", dao.getAllUsers());    
        } else if (action.equalsIgnoreCase("edit")){
            forward = INSERT_OR_EDIT;
            int userId = Integer.parseInt(request.getParameter("userId"));
            User user = dao.getUserById(userId);
            request.setAttribute("user", user);
        } else if (action.equalsIgnoreCase("listUser")){
            forward = LIST_USER;
            request.setAttribute("users", dao.getAllUsers());
        } else {
            forward = INSERT_OR_EDIT;
        }

        RequestDispatcher view = request.getRequestDispatcher(forward);
        view.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        User user = new User();
        user.setFirstName(request.getParameter("firstName"));
        user.setLastName(request.getParameter("lastName"));
        try {
            Date dob = new SimpleDateFormat("MM/dd/yyyy").parse(request.getParameter("dob"));
            user.setDob(dob);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        user.setEmail(request.getParameter("email"));
        String userid = request.getParameter("userid");
        if(userid == null || userid.isEmpty())
        {
            dao.addUser(user);
        }
        else
        {
            user.setUserid(Integer.parseInt(userid));
            dao.updateUser(user);
        }
        RequestDispatcher view = request.getRequestDispatcher(LIST_USER);
        request.setAttribute("users", dao.getAllUsers());
        view.forward(request, response);
    }
}

Now, it’s time for us to create the jsp, the view for our application. Under the WebContent folder, create a jsp file, name it index.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<jsp:forward page="/UserController?action=listUser" />
</body>
</html>

This jsp serves as the entry point for our application. In this case, it will redirect the request to our servlet to list all the users in the database.

Next, create the jsp to list all the users in the WebContent folder. Name it listUser.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Show All Users</title>
</head>
<body>
    <table border=1>
        <thead>
            <tr>
                <th>User Id</th>
                <th>First Name</th>
                <th>Last Name</th>
                <th>DOB</th>
                <th>Email</th>
                <th colspan=2>Action</th>
            </tr>
        </thead>
        <tbody>
            <c:forEach items="${users}" var="user">
                <tr>
                    <td><c:out value="${user.userid}" /></td>
                    <td><c:out value="${user.firstName}" /></td>
                    <td><c:out value="${user.lastName}" /></td>
                    <td><fmt:formatDate pattern="yyyy-MMM-dd" value="${user.dob}" /></td>
                    <td><c:out value="${user.email}" /></td>
                    <td><a href="UserController?action=edit&userId=<c:out value="${user.userid}"/>">Update</a></td>
                    <td><a href="UserController?action=delete&userId=<c:out value="${user.userid}"/>">Delete</a></td>
                </tr>
            </c:forEach>
        </tbody>
    </table>
    <p><a href="UserController?action=insert">Add User</a></p>
</body>
</html>

In this jsp, we use JSTL to connect between the jsp and the servlet. We should refrain from using scriplet inside the jsp because it will make the jsp more difficult to maintain. Not to mention it will make the jsp looks ugly.

Next, create a new jsp in WebContent folder and name it user.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<link type="text/css"
    href="css/ui-lightness/jquery-ui-1.8.18.custom.css" rel="stylesheet" />
<script type="text/javascript" src="js/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.18.custom.min.js"></script>
<title>Add new user</title>
</head>
<body>
    <script>
        $(function() {
            $('input[name=dob]').datepicker();
        });
    </script>

    <form method="POST" action='UserController' name="frmAddUser">
        User ID : <input type="text" readonly="readonly" name="userid"
            value="<c:out value="${user.userid}" />" /> <br /> 
        First Name : <input
            type="text" name="firstName"
            value="<c:out value="${user.firstName}" />" /> <br /> 
        Last Name : <input
            type="text" name="lastName"
            value="<c:out value="${user.lastName}" />" /> <br /> 
        DOB : <input
            type="text" name="dob"
            value="<fmt:formatDate pattern="MM/dd/yyyy" value="${user.dob}" />" /> <br /> 
        Email : <input type="text" name="email"
            value="<c:out value="${user.email}" />" /> <br /> <input
            type="submit" value="Submit" />
    </form>
</body>
</html>

Lastly, check the web.xml file located in WebContent—>WEB-INF folder in your project structure. Make sure it looks like this

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>SimpleJspServletDB</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <description></description>
    <display-name>UserController</display-name>
    <servlet-name>UserController</servlet-name>
    <servlet-class>com.daniel.controller.UserController</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>UserController</servlet-name>
    <url-pattern>/UserController</url-pattern>
  </servlet-mapping>
</web-app>

That is it. Right click the project name and run it using Run As–>Run on server option.

usermgt