In the post Spring Batch Processing Using JDBCTemplate batchUpdate() Method we have already seen how you can use batchUpdate() method with BatchPreparedStatementSetter interface for processing similar queries as batch. In this post we’ll see another option for batch processing in Spring where list of objects is passed.
Spring Batch processing with a List of objects
For batch processing with Spring both the JdbcTemplate and the NamedParameterJdbcTemplate provides an alternate way to use batchUpdate() method. Instead of implementing a special batch interface BatchPreparedStatementSetter, you provide all parameter values in the call as a list. Spring framework loops over these values and uses an internal prepared statement setter.
If you are using NamedParameterJdbcTemplate then you provide an array of SqlParameterSource, one entry for each member of the batch. To create this array you can use SqlParameterSourceUtils.createBatch method.
If you are using JdbcTemplate then you need to provide an Object array.
Let’s see example of batch processing in Spring with both JdbcTemplate and NamedParameterJdbcTemplate to make it clearer. Project structure used is same as used in this post Spring Batch Processing Using JDBCTemplate batchUpdate() Method, so please refer it for setting the project structure.
Spring batch processing using JdbcTemplate
Java classes needed for Spring batch processing example are as follows-
- Employee Bean class (Employee.java)
- DAO interface (EmployeeDAO.java)
- DAO interface implementation class (EmployeeDAOImpl.java)
Employee.java
public class Employee { private int empId; private String empName; private int age; public Employee(String empName, int age){ this.empName = empName; this.age = age; } public int getEmpId() { return empId; } public void setEmpId(int empId) { this.empId = empId; } public String getEmpName() { return empName; } public void setEmpName(String empName) { this.empName = empName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
EmployeeDAO.java
public interface EmployeeDAO { public int[] batchInsert(final List<Employee> employees); }
EmployeeDAOImpl.java
import java.util.ArrayList; import java.util.List; import org.netjs.dao.EmployeeDAO; import org.netjs.model.Employee; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository public class EmployeeDAOImpl implements EmployeeDAO{ @Autowired private JdbcTemplate jdbcTemplate; @Override public int[] batchInsert(final List<Employee> employees) { final String INSERT_EMP_QUERY = "insert into employee (name, age) values (?, ?)"; List<Object[]> empList = new ArrayList<Object[]>(); for(Employee emp : employees) { Object[] values = new Object[] {emp.getEmpName(), emp.getAge()}; empList.add(values); } return this.jdbcTemplate.batchUpdate(INSERT_EMP_QUERY, empList); } }
As you can see in the class an Object[] array is created with the values for each Employee and that is passed as parameter in batchUpdate() method. Spring framework will do the work of looping over these values and use an internal prepared statement setter to set values in the query.
XML Configuration (appContext.xml)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="org.netjs.DAOImpl" /> <!-- For reading properties files --> <context:property-placeholder location="classpath:config/db.properties" /> <!-- Data Source configuration --> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value = "${db.driverClassName}" /> <property name="url" value = "${db.url}" /> <property name="username" value = "${db.username}" /> <property name="password" value = "${db.password}" /> <property name="initialSize" value = "${pool.initialSize}" /> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> </beans>
Spring batch processing using NamedParameterJdbcTemplate
Example using NamedParameterJdbcTemplate where an array of SqlParameterSource is passed as parameter in batchUpdate() method.
import java.util.List; import org.netjs.dao.EmployeeDAO; import org.netjs.model.Employee; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils; import org.springframework.stereotype.Repository; @Repository public class EmployeeDAOImpl implements EmployeeDAO{ @Autowired private NamedParameterJdbcTemplate namedParameterJdbcTemplate; @Override public int[] batchInsert(final List<Employee> employees) { final String INSERT_EMP_QUERY = "insert into employee (name, age) values (:empName, :age)"; return this.namedParameterJdbcTemplate.batchUpdate(INSERT_EMP_QUERY, SqlParameterSourceUtils.createBatch(employees)); } }
XML Configuration (appContext.xml)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="org.netjs.DAOImpl" /> <!-- For reading properties files --> <context:property-placeholder location="classpath:config/db.properties" /> <!-- Data Source configuration --> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value = "${db.driverClassName}" /> <property name="url" value = "${db.url}" /> <property name="username" value = "${db.username}" /> <property name="password" value = "${db.password}" /> <property name="initialSize" value = "${pool.initialSize}" /> </bean> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> <constructor-arg ref="dataSource"></constructor-arg> </bean> </beans>
Test class
You can use the following code in order to test the batch insertion of rows in DB table.
public class App { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext ("appcontext.xml"); EmployeeDAO empDAO = context.getBean("employeeDAOImpl", EmployeeDAOImpl.class); List<Employee> empList = createEmpList(); int[] rows = empDAO.batchInsert(empList); System.out.println("Number of rows inserted- " + rows.length); } private static List<Employee> createEmpList(){ Employee emp1 = new Employee("Ben", 25); Employee emp2 = new Employee("Virat", 29); Employee emp3 = new Employee("Joe", 26); List<Employee> empList= new ArrayList<Employee>(); empList.add(emp1); empList.add(emp2); empList.add(emp3); return empList; } }
Passing parameters as Map in NamedParameterJdbcTemplate
If you want to pass parameters as Map the way it is generally done for NamedParameterJdbcTemplate then batchUpdate() method does provide an overloaded variant where array of Maps can be passed. In that case EmployeeDAOImpl class can be written as following.
import java.util.HashMap; import java.util.List; import java.util.Map; import org.netjs.dao.EmployeeDAO; import org.netjs.model.Employee; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @Repository public class EmployeeDAOImpl implements EmployeeDAO{ @Autowired private NamedParameterJdbcTemplate namedParameterJdbcTemplate; @Override public int[] batchInsert(final List<Employee> employees) { final String INSERT_EMP_QUERY = "insert into employee (name, age) values (:name, :age)"; // Map array Map<String, Object>[] paramMap = new HashMap[employees.size()]; for(int i = 0; i < employees.size(); i++) { Employee emp = employees.get(i); Map<String, Object> tempMap = new HashMap<String, Object>(); tempMap.put("name", emp.getEmpName()); tempMap.put("age", emp.getAge()); paramMap[i] = tempMap; } return this.namedParameterJdbcTemplate.batchUpdate(INSERT_EMP_QUERY, paramMap); } }
That's all for this topic Spring Batch Processing With List of Objects. If you have any doubt or any suggestions to make please drop a comment. Thanks!
>>>Return to Spring Tutorial Page
Related Topics
You may also like-