Spring JDBC – Ví dụ PreparedStatement, ResultSetExtractor, RowMapper, NamedParameterJdbcTemplate trong Spring JDBC

Spring JDBC – Ví dụ PreparedStatement, ResultSetExtractor, RowMapper, NamedParameterJdbcTemplate trong Spring JDBC

Trong bài này chúng ta sẽ tìm hiểu một số class trong Spring JDBC như ResultSetExtractor, RowMapper, NamedParameterJdbcTemplate, SimpleJdbcTemplate.

Tạo cơ sở dữ liệu

Tạo database “spring-jdbc”

CREATE SCHEMA `spring-jdbc` ;

(Xem lại: Cài đặt và cấu hình MySQL)

Tạo table “user_info”

CREATE TABLE `spring-jdbc`.`user_info` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `address` VARCHAR(255) NULL,
  PRIMARY KEY (`id`));

Spring JDBC - Ví dụ PreparedStatement, ResultSetExtractor, RowMapper, NamedParameterJdbcTemplate, SimpleJdbcTemplate trong Spring JDBC

Code ví dụ:

Spring JDBC - Ví dụ PreparedStatement, ResultSetExtractor, RowMapper, NamedParameterJdbcTemplate trong Spring JDBC

Thư viện sử dụng:

<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>stackjava.com</groupId>
  <artifactId>SpringJDBC</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>6.0.6</version>
    </dependency>

  </dependencies>
</project>

File spring config:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/spring-jdbc" />
    <property name="username" value="root" />
    <property name="password" value="admin1234" />
  </bean>

  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"></property>
  </bean>

  <bean id="npJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">  
    <constructor-arg ref="dataSource"></constructor-arg>  
  </bean>  

</beans>

 

PreparedStatement

Trong bài trước, khi thực hiện query insert mình có nói khi insert với tham số truyền vào thì spring JDBC sẽ insert thông qua PreparedStatement thay vì Statement.

Ở phần này chúng ta sẽ chỉ rõ việc thực hiện query với PreparedStatement thông qua PreparedStatementCallback

Ví dụ:

package stackjava.com.springjdbc.mainapp;

import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCallback;

public class DemoPreparedStatementCallback {
  public static void main(String[] args) throws SQLException {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    JdbcTemplate jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
    String sql = "INSERT INTO user_info (name, address) VALUES (?, ?);";
    // jdbcTemplate.update(sql, "Harry Potter", "England");

    jdbcTemplate.execute(sql, new PreparedStatementCallback<Boolean>() {
      public Boolean doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
        ps.setString(1, "Harry Potter");
        ps.setString(2, "England");
        return ps.execute();
      }
    });

    ((ClassPathXmlApplicationContext) ctx).close();
    System.out.println("Inserted!");
  }
}

Kết quả:

NamedParameterJdbcTemplate

NamedParameterJdbcTemplate hỗ trợ việc insert data bằng việc đặt tên các tham số, với cách này chúng ta sử dụng tên các tham số thay vì dùng dấu ‘?’, cách này tốt hơn việc chúng ta phải nhớ tên các column.

Ví dụ:

package stackjava.com.springjdbc.mainapp;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

public class DemoPreparedStatementCallback {
  public static void main(String[] args) throws SQLException {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    NamedParameterJdbcTemplate npJdbcTemplate = (NamedParameterJdbcTemplate) ctx.getBean("npJdbcTemplate");
    
    String sql = "INSERT INTO user_info (name, address) VALUES (:name, :address);";
    Map<String, String> paramMap = new HashMap<String, String>();
    paramMap.put("name", "Sylvester Stallon");
    paramMap.put("address", "USA");

    npJdbcTemplate.execute(sql, paramMap, new PreparedStatementCallback<Boolean>() {
      public Boolean doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
        return ps.execute();
      }
    });

    ((ClassPathXmlApplicationContext) ctx).close();
    System.out.println("Inserted!");
  }
}

Khi sử dụng method execute của NamedParameterJdbcTemplate, các đối tham số trong câu SQL sẽ tự động lấy tương ứng với các đối tượng trong paramMap có key trùng với param name để truyền vào PreparedStatement.

Kết quả:

NamedParameterJdbcTemplate

ResultSetExtractor, RowMapper

Cả ResultSetExtractor và RowMapper đều được sử dụng để chuyển đổi dữ liệu từ câu query select thành các đối tượng mong muốn:

package stackjava.com.springjdbc.entities;

public class User {
  private int id;
  private String name;
  private String address;

  public User() {
  }

  public User(int id, String name, String address) {
    this.id = id;
    this.name = name;
    this.address = address;
  }

  @Override
  public String toString() {
    return "User [id=" + id + ", name=" + name + ", address=" + address + "]";
  }

  // getter - setter

}
package stackjava.com.springjdbc.entities;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

public class UserMapper implements RowMapper<User>{

  public User mapRow(ResultSet rs, int rowNum) throws SQLException {
    User user= new User();
    user.setId(rs.getInt("id"));
    user.setName(rs.getString("name"));
    user.setAddress(rs.getString("address"));
    return user;

  }

}
package stackjava.com.springjdbc.mainapp;

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

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;

import stackjava.com.springjdbc.entities.User;
import stackjava.com.springjdbc.entities.UserMapper;

public class DemoResultSetExtractor_RowMapper {
  public static void main(String[] args) throws SQLException {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    JdbcTemplate jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
    String sql = "SELECT * FROM user_info";
    System.out.println("------------ Using row ResultSetExtractor ----------------------");
    List<User> listUser1 = jdbcTemplate.query(sql, new ResultSetExtractor<List<User>>() {
      public List<User> extractData(ResultSet rs) throws SQLException, DataAccessException {
        List<User> list = new ArrayList<User>();
        while (rs.next()) {
          User user = new User();
          user.setId(rs.getInt("id"));
          user.setName(rs.getString("address"));
          user.setAddress(rs.getString("address"));
          list.add(user);
        }
        return list;
      }
    });
    for (User user: listUser1) {
      System.out.println(user);
    }

    System.out.println("------------ Using RowMapper ----------------------");
    List<User> listUser2 = jdbcTemplate.query(sql, new UserMapper());
    for (User user : listUser2) {
      System.out.println(user);
    }

    ((ClassPathXmlApplicationContext) ctx).close();
  }
}

Kết quả:

------------ Using row ResultSetExtractor ----------------------
User [id=1, name=England, address=England]
User [id=2, name=USA, address=USA]
------------ Using RowMapper ----------------------
User [id=1, name=Harry Potter, address=England]
User [id=2, name=Sylvester Stallon, address=USA]

Okay, Done!

Phần sau chúng ta sẽ tìm hiểu về Spring JDBC Batch, và Transaction với Spring JDBC.

Download code ví dụ trên tại đây

Spring JDBC – Ví dụ PreparedStatement, ResultSetExtractor, RowMapper, NamedParameterJdbcTemplate trong Spring JDBC

References:

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/RowMapper.html

https://docs.spring.io/spring/docs/1.0.0/javadoc-api/org/springframework/jdbc/core/ResultSetExtractor.html

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/PreparedStatementCallback.html

stackjava.com