You are on page 1of 12

Spring JDBC and JdbcTemplate CRUD with DataSource Example Tutorial

Databases are integral part of most of the Enterprise Applications. So when it comes to a Java EE
framework, having good integration with JDBC is very important.
Spring Framework provides excellent integration with JDBC API and provides JdbcTemplate utility class
that we can use to avoid bolier-plate code from our database operations logic such as Opening/Closing
Connection, ResultSet, PreparedStatement etc.
Lets first look at a simple Spring JDBC CRUD application and then we will see how JdbcTemplate class
can help us in writing modular code with ease, without worrying whether resources are closed properly or
not.
Spring Tool Suite to develop Spring based applications is very helpful, so we will use STS to create our
Spring JDBC application. Our final project structure will look like below image.

Create a simple Spring Maven Project from the STS Menu, you can choose whatever name you like or
stick with my project name as SpringJDBCExample.
Spring JDBC Dependencies
First of all we need to include Spring JDBC and Database drivers in the maven project pom.xml file. My
final pom.xml file looks like below.

1
2
3
4
5
6
7
8
9
10
11
12
13

pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/X
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>SpringJDBCExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<!-- Spring -->


<spring-framework.version>4.0.2.RELEASE</spring-framework.version>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

<!-- Logging -->


<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
</properties>
<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Spring JDBC Support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>

Most of the part is automatically generated by STS, however I have update Spring Framework version to
use latest version as 4.0.2.RELEASE.
Also we have added required artifacts spring-jdbc and mysql-connector-java. First one contains
the Spring Framework JDBC support classes and second one is database driver. I am using MySQL
database for our testing purposes, so I have added MySQL JConnector jar dependencies. If you are
using some other RDBMS then you should make the corresponding changes in the dependencies.

Database Setup
Lets create a simple table that we will use in our application for CRUD operations example.
Employee.sql
CREATE TABLE `Employee` (
1
`id` int(11) unsigned NOT NULL,
2
`name` varchar(20) DEFAULT NULL,
3
`role` varchar(20) DEFAULT NULL,
4
PRIMARY KEY (`id`)
5
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6
Model Class
We will use DAO Pattern for JDBC operations, so lets create a java bean that will model our Employee
table.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
DAO

Employee.java
package com.journaldev.spring.jdbc.model;
public class Employee {
private int id;
private String name;
private String role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@Override
public String toString(){
return "{ID="+id+",Name="+name+",Role="+role+"}";
}
}
Interface and Implementation

For DAO pattern, we will first have an interface declaring all the operations we want to implement.

1
2
3
4
5
6

EmployeeDAO.java
package com.journaldev.spring.jdbc.dao;
import java.util.List;
import com.journaldev.spring.jdbc.model.Employee;

7 //CRUD operations
8 public interface EmployeeDAO {
9
10
//Create
11
public void save(Employee employee);
12
//Read
public Employee getById(int id);
13
//Update
14
public void update(Employee employee);
15
//Delete
16
public void deleteById(int id);
17
//Get All
18
public List<Employee> getAll();
19
}
20
EmployeeDAOImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

package com.journaldev.spring.jdbc.dao;
import
import
import
import
import
import

java.sql.Connection;
java.sql.PreparedStatement;
java.sql.ResultSet;
java.sql.SQLException;
java.util.ArrayList;
javax.sql.DataSource;

import com.journaldev.spring.jdbc.model.Employee;
public class EmployeeDAOImpl implements EmployeeDAO {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public void save(Employee employee) {
String query = "insert into Employee (id, name, role) values (?,?,?)";
Connection con = null;
PreparedStatement ps = null;
try{
con = dataSource.getConnection();
ps = con.prepareStatement(query);
ps.setInt(1, employee.getId());
ps.setString(2, employee.getName());
ps.setString(3, employee.getRole());
int out = ps.executeUpdate();
if(out !=0){
System.out.println("Employee saved with id="+employee.getId());
}else System.out.println("Employee save failed with
id="+employee.getId());
}catch(SQLException e){
e.printStackTrace();
}finally{
try {
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

@Override
public Employee getById(int id) {
String query = "select name, role from Employee where id = ?";
Employee emp = null;
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
con = dataSource.getConnection();
ps = con.prepareStatement(query);
ps.setInt(1, id);
rs = ps.executeQuery();
if(rs.next()){
emp = new Employee();
emp.setId(id);
emp.setName(rs.getString("name"));
emp.setRole(rs.getString("role"));
System.out.println("Employee Found::"+emp);
}else{
System.out.println("No Employee found with id="+id);
}
}catch(SQLException e){
e.printStackTrace();
}finally{
try {
rs.close();
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return emp;
}
@Override
public void update(Employee employee) {
String query = "update Employee set name=?, role=? where id=?";
Connection con = null;
PreparedStatement ps = null;
try{
con = dataSource.getConnection();
ps = con.prepareStatement(query);
ps.setString(1, employee.getName());
ps.setString(2, employee.getRole());
ps.setInt(3, employee.getId());
int out = ps.executeUpdate();
if(out !=0){
System.out.println("Employee updated with
id="+employee.getId());
}else System.out.println("No Employee found with
id="+employee.getId());
}catch(SQLException e){
e.printStackTrace();
}finally{
try {
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

@Override
public void deleteById(int id) {
String query = "delete from Employee where id=?";
Connection con = null;
PreparedStatement ps = null;
try{
con = dataSource.getConnection();
ps = con.prepareStatement(query);
ps.setInt(1, id);
int out = ps.executeUpdate();
if(out !=0){
System.out.println("Employee deleted with id="+id);
}else System.out.println("No Employee found with id="+id);
}catch(SQLException e){
e.printStackTrace();
}finally{
try {
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

@Override
public List<Employee> getAll() {
String query = "select id, name, role from Employee";
List<Employee> empList = new ArrayList<Employee>();
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
con = dataSource.getConnection();
ps = con.prepareStatement(query);
rs = ps.executeQuery();
while(rs.next()){
Employee emp = new Employee();
emp.setId(rs.getInt("id"));
emp.setName(rs.getString("name"));
emp.setRole(rs.getString("role"));
empList.add(emp);
}
}catch(SQLException e){
e.printStackTrace();
}finally{
try {
rs.close();
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return empList;
}
}

The implementation of CRUD operations are simple to understand. If you want to learn more about
DataSource, please read JDBC DataSource Example.

Spring Bean Configuration


If you look at all the classes above, they are all using standard JDBC API and there is no reference to
Spring JDBC framework. Spring JDBC framework classes comes into picture when we create Spring
Bean Configuration file and define the beans. We will create the DataSource in the Spring Bean context
file and set it to our DAO implementation class.
My Spring Bean Configuration file looks like below.
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
1
<beans xmlns="http://www.springframework.org/schema/beans"
2
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
xsi:schemaLocation="http://www.springframework.org/schema/beans
4
http://www.springframework.org/schema/beans/spring-beans.xsd">
5
6
<bean id="employeeDAO" class="com.journaldev.spring.jdbc.dao.EmployeeDAOImpl">
7
<property name="dataSource" ref="dataSource" />
8
</bean>
9
10 <bean id="dataSource" class=
11 "org.springframework.jdbc.datasource.DriverManagerDataSource">
12
13 <property name="driverClassName" value="com.mysql.jdbc.Driver" />
14 <property name="url" value="jdbc:mysql://localhost:3306/TestDB" />
15 <property name="username" value="pankaj" />
16 <property name="password" value="pankaj123" />
17 </bean>
18 </beans>
First of all we are creating a DataSource object of class DriverManagerDataSource. This class
provides the basic implementation of DataSource that we can use. We are passing MySQL database
URL, username and password as properties to the DataSource bean.
Again dataSource bean is set to the EmployeeDAOImpl bean and we are ready with our Spring JDBC
implementation. The implementation is loosely coupled and if we want to switch to some other
implementation or move to other database server, all we need is to make corresponding changes in the
bean configurations. This is one of the major advantage provided by Spring JDBC framework.
Spring JDBC Test Class
Lets write a simple test class to make sure everything is working fine.
SpringMain.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

package com.journaldev.spring.jdbc.main;
import java.util.List;
import java.util.Random;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.spring.jdbc.dao.EmployeeDAO;
import com.journaldev.spring.jdbc.model.Employee;
public class SpringMain {
public static void main(String[] args) {
//Get the Spring Context
ClassPathXmlApplicationContext ctx =

new ClassPathXmlApplicationContext("spring.xml");
//Get the EmployeeDAO Bean
EmployeeDAO employeeDAO = ctx.getBean("employeeDAO", EmployeeDAO.class);

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

//Run some tests for JDBC CRUD operations


Employee emp = new Employee();
int rand = new Random().nextInt(1000);
emp.setId(rand);
emp.setName("Pankaj");
emp.setRole("Java Developer");
//Create
employeeDAO.save(emp);
//Read
Employee emp1 = employeeDAO.getById(rand);
System.out.println("Employee Retrieved::"+emp1);
//Update
emp.setRole("CEO");
employeeDAO.update(emp);
//Get All
List<Employee> empList = employeeDAO.getAll();
System.out.println(empList);
//Delete
employeeDAO.deleteById(rand);
//Close Spring Context
ctx.close();
}

System.out.println("DONE");

}
I am using Random Class to generate random number for employee id. When we run above program,
we get following output.

Mar 25, 2014 12:54:18 PM org.springframework.context.support.ClassPathXmlApplicationCon


INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4b9
Mar 25, 2014 12:54:18 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader
INFO: Loading XML bean definitions from class path resource [spring.xml]
Mar 25, 2014 12:54:19 PM org.springframework.jdbc.datasource.DriverManagerDataSource se
INFO: Loaded JDBC driver: com.mysql.jdbc.Driver
Employee saved with id=726
Employee Found::{ID=726,Name=Pankaj,Role=Java Developer}
Employee Retrieved::{ID=726,Name=Pankaj,Role=Java Developer}
Employee updated with id=726
[{ID=726,Name=Pankaj,Role=CEO}]
Employee deleted with id=726
Mar 25, 2014 12:54:19 PM org.springframework.context.support.ClassPathXmlApplicationCon
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@4b9af9
DONE
Spring JdbcTemplate Example
1
2
3
4
5
6
7
8
9
10
11
12

If you look at the DAO implementation class, there is a lot of boiler-plate code where we are opening and
closing Connection, PreparedStatements and ResultSet. This can lead to resource leak if someone
forgets to close the resources properly. We can

use org.springframework.jdbc.core.JdbcTemplate class to avoid these errors. This is the central


class in Spring JDBC core package and provides a lot of methods to execute queries and automatically
parse ResultSet to get the Object or list of Objects.
All we need is to provide the arguments as Object array and implement Callback interfaces such
asPreparedStatementSetter and RowMapper for mapping arguments or converting ResultSet data to
bean objects.
Lets look at another implementation of EmployeeDAO where we will use JdbcTemplate class for
executing different types of queries.

1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2

EmployeeDAOJDBCTemplateImpl.java
package com.journaldev.spring.jdbc.dao;
import
import
import
import
import

java.sql.ResultSet;
java.sql.SQLException;
java.util.ArrayList;
java.util.List;
java.util.Map;

import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import com.journaldev.spring.jdbc.model.Employee;
public class EmployeeDAOJDBCTemplateImpl implements EmployeeDAO {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public void save(Employee employee) {
String query = "insert into Employee (id, name, role) values (?,?,?)";
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
Object[] args = new Object[] {employee.getId(), employee.getName(),
employee.getRole()};
int out = jdbcTemplate.update(query, args);
if(out !=0){
System.out.println("Employee saved with id="+employee.getId());
}else System.out.println("Employee save failed with id="+employee.getId());
}
@Override
public Employee getById(int id) {
String query = "select id, name, role from Employee where id = ?";
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
reuse

//using RowMapper anonymous class, we can create a separate RowMapper for

Employee emp = jdbcTemplate.queryForObject(query, new Object[]{id}, new


RowMapper<Employee>(){

@Override
9
public Employee mapRow(ResultSet rs, int rowNum)
3
throws SQLException {
0
Employee emp = new Employee();
3
emp.setId(rs.getInt("id"));
1
emp.setName(rs.getString("name"));
3
emp.setRole(rs.getString("role"));
2
return emp;
3
}});
3
3
return emp;
4
}
3
5
@Override
3
public void update(Employee employee) {
6
String query = "update Employee set name=?, role=? where id=?";
3
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
7
Object[] args = new Object[] {employee.getName(), employee.getRole(),
3
employee.getId()};
8
3
int out = jdbcTemplate.update(query, args);
9
if(out !=0){
4
System.out.println("Employee updated with id="+employee.getId());
0
}else System.out.println("No Employee found with id="+employee.getId());
4
}
1
4
@Override
2
public void deleteById(int id) {
4
3
String query = "delete from Employee where id=?";
4
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
4
4
int out = jdbcTemplate.update(query, id);
5
if(out !=0){
4
System.out.println("Employee deleted with id="+id);
6
}else System.out.println("No Employee found with id="+id);
4
}
7
4
@Override
8
public List<Employee> getAll() {
4
String query = "select id, name, role from Employee";
9
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
5
List<Employee> empList = new ArrayList<Employee>();
0
5
List<Map<String,Object>> empRows = jdbcTemplate.queryForList(query);
1
5
for(Map<String,Object> empRow : empRows){
2
Employee emp = new Employee();
5
emp.setId(Integer.parseInt(String.valueOf(empRow.get("id"))));
3
emp.setName(String.valueOf(empRow.get("name")));
5
emp.setRole(String.valueOf(empRow.get("role")));
4
empList.add(emp);
5
}
5
return empList;
}
5
6
5}
7
5
8
5
9
6

0
6
1
6
2
6
3
6
4
6
5
6
6
6
7
6
8
6
9
7
0
7
1
7
2
7
3
7
4
7
5
7
6
7
7
7
8
7
9
8
0
8
1
8
2
8
3
8
4
8
5
8
6
8
7
8
8
8
9
9
0
9

1
9
2
9
3

Important points to look into above code are:

Use of Object array to pass PreparedStatement arguments, we could also use


PreparedStatementSetter implementation but passing Object array seems easy to use.

No code related to opening and closing connections, statements or result set. All that
is handled internally by JdbcTemplate class.
RowMapper anonymous class implementation to map the ResultSet data to Employee
bean object inqueryForObject() method.
queryForList() method returns list of Map whereas Map contains the row data mapped
with key as the column name and value from the database row matching the criteria.

To use JdbcTemplate implementation, all we need is to change the employeeDAO class in the Spring
Bean configuration file as shown below.
1
2
3

<bean id="employeeDAO"
class="com.journaldev.spring.jdbc.dao.EmployeeDAOJDBCTemplateImpl">
<property name="dataSource" ref="dataSource" />
</bean>

When you will run the main class, the output will be similar to the one seen above with normal JDBC
implementation. Thats all for Spring JDBC Example tutorial, download the sample project from below link
and play around with it to learn more.

You might also like